all: assorted cleanups; introduce undocumented '--sysinfo' option

This commit is contained in:
Markus F.X.J. Oberhumer
2023-10-05 03:51:27 +02:00
parent 7f9d381c7b
commit 632c7c4826
30 changed files with 498 additions and 339 deletions
+2 -7
View File
@@ -7,12 +7,8 @@
# instead. And see the top-level Makefile for some pre-defined CMake
# build configurations.
MAKEFLAGS += -r
export SHELL = /bin/sh
ifndef srcdir
srcdir := $(dir $(lastword $(MAKEFILE_LIST)))
srcdir := $(shell echo '$(srcdir)' | sed 's,/*$$,,' || echo 'ERROR')
srcdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
endif
ifndef top_srcdir
top_srcdir := $(srcdir)/..
@@ -98,8 +94,7 @@ endif
# "make check-whitespace"
#
CHECK_WHITESPACE =
ifeq ($(shell uname),Linux)
ifeq ($(shell uname),Linux) # needs bash, perl, xargs, etc.
CHECK_WHITESPACE = $(top_srcdir)/misc/scripts/check_whitespace.sh $(top_srcdir)
ifneq ($(wildcard $(top_srcdir)/.git/.),)
CHECK_WHITESPACE = $(top_srcdir)/misc/scripts/check_whitespace_git.sh $(top_srcdir)
+3
View File
@@ -95,11 +95,14 @@ TEST_CASE("noncopyable") {
Test t = {};
CHECK(t.v == 1);
#if (ACC_CC_MSC) // MSVC thinks that Test is not std::is_trivially_copyable; true or compiler bug?
// @COMPILER_BUG @MSVC_BUG
t.v = 0;
#else
mem_clear(&t);
#endif
CHECK(t.v == 0);
constexpr Test x = {};
static_assert(x.v == 1);
}
/*************************************************************************
+1
View File
@@ -757,6 +757,7 @@ extern const char gitrev[];
void show_header();
void show_help(int verbose=0);
void show_license();
void show_sysinfo(const char *options_var);
void show_usage();
void show_version(bool one_line=false);
+1 -17
View File
@@ -33,23 +33,7 @@
// direct screen access
**************************************************************************/
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN 1
#endif
#if (defined(_MSC_VER) && (_MSC_VER >= 1000 && _MSC_VER < 1200)) && !defined(__clang__)
/* avoid -W4 warnings in <conio.h> */
#pragma warning(disable : 4032)
/* avoid -W4 warnings in <windows.h> */
#pragma warning(disable : 4201 4214 4514)
#endif
#if defined(_MSC_VER) && !defined(__clang__)
/* avoid warnings in some versions of <windows.h> */
#pragma warning(disable : 5105)
#endif
#if defined(__RSXNT__)
#define timeval win32_timeval /* struct timeval already in <sys/time.h> */
#endif
#include <windows.h>
#include "../util/windows_lean.h"
#if (HAVE_CONIO_H)
#include <conio.h>
#endif
-4
View File
@@ -26,8 +26,6 @@
*/
#pragma once
#ifndef UPX_SCREEN_H__
#define UPX_SCREEN_H__ 1
#if (USE_SCREEN)
@@ -100,6 +98,4 @@ void screen_show_frames(screen_t *);
#endif /* USE_SCREEN */
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
+87
View File
@@ -435,4 +435,91 @@ void show_version(bool one_line) {
// clang-format on
}
/*************************************************************************
// sysinfo
// undocumented and subject to change
**************************************************************************/
void show_sysinfo(const char *options_var) {
FILE *f = con_term;
show_header();
if (opt->verbose >= 1) {
con_fprintf(f, "UPX version: ");
fflush(f);
show_version(true);
}
fflush(stdout);
// Compilation Flags
if (opt->verbose >= 2) {
size_t cf_count = 0;
auto cf_print = [f, &cf_count](const char *name, const char *fmt, upx_int64_t v) noexcept {
if (cf_count++ == 0)
con_fprintf(f, "\nCompilation flags:\n");
con_fprintf(f, " %s = ", name);
con_fprintf(f, fmt, v);
con_fprintf(f, "\n");
};
// OS and libc
#if defined(WINVER)
cf_print("WINVER", "0x%04llx", WINVER + 0);
#endif
#if defined(_WIN32_WINNT)
cf_print("_WIN32_WINNT", "0x%04llx", _WIN32_WINNT + 0);
#endif
#if defined(__MSVCRT_VERSION__)
cf_print("__MSVCRT_VERSION__", "0x%04llx", __MSVCRT_VERSION__ + 0);
#endif
#if defined(_USE_MINGW_ANSI_STDIO)
cf_print("_USE_MINGW_ANSI_STDIO", "%lld", _USE_MINGW_ANSI_STDIO + 0);
#endif
#if defined(__USE_MINGW_ANSI_STDIO)
cf_print("__USE_MINGW_ANSI_STDIO", "%lld", __USE_MINGW_ANSI_STDIO + 0);
#endif
#if defined(__GLIBC__)
cf_print("__GLIBC__", "%lld", __GLIBC__ + 0);
#endif
#if defined(__GLIBC_MINOR__)
cf_print("__GLIBC_MINOR__", "%lld", __GLIBC_MINOR__ + 0);
#endif
// compiler
#if defined(_MSC_VER) && defined(_MSC_FULL_VER)
cf_print("_MSC_VER", "%lld", _MSC_VER + 0);
cf_print("_MSC_FULL_VER", "%lld", _MSC_FULL_VER + 0);
#endif
UNUSED(cf_count);
UNUSED(cf_print);
}
// run-time
#if defined(HAVE_LOCALTIME) && defined(HAVE_GMTIME)
{
auto tm2str = [](char *s, size_t size, const struct tm *tmp) noexcept {
snprintf(s, size, "%04d-%02d-%02d %02d:%02d:%02d", (int) tmp->tm_year + 1900,
(int) tmp->tm_mon + 1, (int) tmp->tm_mday, (int) tmp->tm_hour,
(int) tmp->tm_min, (int) tmp->tm_sec);
};
char s[40];
const time_t t = time(nullptr);
tm2str(s, sizeof(s), localtime(&t));
con_fprintf(f, "\n");
con_fprintf(f, "Local time is: %s\n", s);
tm2str(s, sizeof(s), gmtime(&t));
con_fprintf(f, "UTC time is: %s\n", s);
}
#endif
if (options_var && options_var[0]) {
const char *e = getenv(options_var);
con_fprintf(f, "\n");
if (e && e[0])
con_fprintf(f, "Contents of environment variable %s: '%s'\n\n", options_var, e);
else
con_fprintf(f, "Environment variable '%s' is not set.\n\n", options_var);
}
}
/* vim:set ts=4 sw=4 et: */
+11 -2
View File
@@ -374,6 +374,9 @@ static int do_option(int optc, const char *arg) {
case 909:
set_cmd(CMD_FILEINFO);
break;
case 910:
set_cmd(CMD_SYSINFO);
break;
case 'h':
case 'H':
case '?':
@@ -807,6 +810,8 @@ int main_get_options(int argc, char **argv) {
{"help", 0, N, 'h' + 256}, // give help
{"license", 0, N, 'L'}, // display software license
{"list", 0, N, 'l'}, // list compressed exe
{"sysinfo", 0x90, N, 910}, // display system info // undocumented and subject to change
{"sys-info", 0x90, N, 910}, // display system info // undocumented and subject to change
{"test", 0, N, 't'}, // test compressed file integrity
{"uncompress", 0, N, 'd'}, // decompress
{"version", 0, N, 'V' + 256}, // display version number
@@ -1250,14 +1255,18 @@ int upx_main(int argc, char *argv[]) may_throw {
break;
case CMD_FILEINFO:
break;
case CMD_LICENSE:
show_license();
case CMD_SYSINFO:
show_sysinfo(OPTIONS_VAR);
e_exit(EXIT_OK);
break;
case CMD_HELP:
show_help(1);
e_exit(EXIT_OK);
break;
case CMD_LICENSE:
show_license();
e_exit(EXIT_OK);
break;
case CMD_VERSION:
show_version();
e_exit(EXIT_OK);
+1
View File
@@ -47,6 +47,7 @@ enum {
CMD_TEST,
CMD_LIST,
CMD_FILEINFO,
CMD_SYSINFO,
CMD_HELP,
CMD_LICENSE,
CMD_VERSION,
-4
View File
@@ -26,8 +26,6 @@
*/
#pragma once
#ifndef UPX_P_DJGPP2_H__
#define UPX_P_DJGPP2_H__ 1
/*************************************************************************
// djgpp2/coff
@@ -104,6 +102,4 @@ protected:
void stripDebug();
};
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
+1
View File
@@ -29,6 +29,7 @@
*/
#pragma once
#ifndef __UPX_P_LX_EXC_H
#define __UPX_P_LX_EXC_H 1
+1
View File
@@ -30,6 +30,7 @@
*/
#pragma once
#ifndef __UPX_P_LX_INTERP_H //{
#define __UPX_P_LX_INTERP_H 1
+1
View File
@@ -30,6 +30,7 @@
*/
#pragma once
#ifndef __UPX_P_LX_SH_H //{
#define __UPX_P_LX_SH_H 1
+1 -1
View File
@@ -185,7 +185,7 @@ bool Packer::compress(SPAN_P(byte) i_ptr, unsigned i_len, SPAN_P(byte) o_ptr,
opt->crp.crp_ucl.max_match < cconf.conf_ucl.max_match)
cconf.conf_ucl.max_match = opt->crp.crp_ucl.max_match;
#if (WITH_NRV)
if (ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512 * 1024))
if ((ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512 * 1024)) && !opt->prefer_ucl)
step = 0;
#endif
}
+8 -11
View File
@@ -1,17 +1,15 @@
#
# UPX stub Makefile - needs GNU make 3.81 or better
#
# Preferred: see misc/podman/rebuild-stubs how to use Podman/Docker.
# Otherwise you will need a number of special build tools like various
# cross-assemblers and cross-compilers - see README.SRC.
#
# Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
# UPX stub Makefile - needs GNU make
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
#
# NOTE: see misc/podman/rebuild-stubs/20-image-run-shell.sh
# how to rebuild the UPX stubs
MAKEFLAGS += -rR
.SUFFIXES:
.SECONDEXPANSION:
.NOTPARALLEL:
.SECONDEXPANSION:
.SUFFIXES:
export LC_ALL = C
export SHELL = /bin/sh
@@ -22,8 +20,7 @@ space := $(empty) $(empty)
tab := $(empty) $(empty)
ifndef srcdir
srcdir := $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
srcdir := $(shell echo '$(srcdir)' | sed 's,/*$$,,')
srcdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
endif
ifndef top_srcdir
top_srcdir := $(srcdir)/../..
+2 -1
View File
@@ -280,6 +280,7 @@ void upx_memswap(void *a, void *b, size_t n) {
static void memswap_no_overlap(byte *a, byte *b, size_t n) {
#if defined(__clang__) && __clang_major__ < 15
// work around a clang < 15 ICE (Internal Compiler Error)
// @COMPILER_BUG @CLANG_BUG
upx_memswap(a, b, n);
#else // clang bug
upx_alignas_max byte tmp_buf[16];
@@ -763,7 +764,7 @@ int fn_strcmp(const char *n1, const char *n2) {
}
/*************************************************************************
// misc.
// misc
**************************************************************************/
bool set_method_name(char *buf, size_t size, int method, int level) {
+48
View File
@@ -0,0 +1,48 @@
/* windows_lean.h -- <windows.h> include wrapper
This file is part of the UPX executable compressor.
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
UPX and the UCL library are free software; you can redistribute them
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
*/
#pragma once
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN 1
#endif
#if (defined(_MSC_VER) && (_MSC_VER >= 1000 && _MSC_VER < 1200)) && !defined(__clang__)
/* avoid -W4 warnings in <conio.h> */
#pragma warning(disable : 4032)
/* avoid -W4 warnings in <windows.h> */
#pragma warning(disable : 4201 4214 4514)
#endif
#if defined(_MSC_VER) && !defined(__clang__)
/* avoid warnings in some versions of <windows.h> */
#pragma warning(disable : 5105)
#endif
#if defined(__RSXNT__) && !defined(timeval)
#define timeval win32_timeval /* struct timeval already in <sys/time.h> */
#endif
#include <windows.h>
+40 -17
View File
@@ -28,6 +28,7 @@
#if WITH_XSPAN
// namespace
#if 1
#define XSPAN_NAMESPACE_NAME XSpan
#define XSPAN_NAMESPACE_BEGIN namespace XSPAN_NAMESPACE_NAME {
@@ -51,12 +52,12 @@ noinline void xspan_fail_range_range(void) may_throw;
void xspan_check_range(const void *ptr, const void *base, ptrdiff_t size_in_bytes) may_throw;
// help constructor to distinguish between number of elements and bytes
struct XSpanCount {
explicit forceinline XSpanCount(size_t n) noexcept : count(n) {}
struct XSpanCount final {
explicit forceinline constexpr XSpanCount(size_t n) noexcept : count(n) {}
size_t count; // public
};
struct XSpanSizeInBytes {
explicit forceinline XSpanSizeInBytes(size_t bytes) noexcept : size_in_bytes(bytes) {}
struct XSpanSizeInBytes final {
explicit forceinline constexpr XSpanSizeInBytes(size_t bytes) noexcept : size_in_bytes(bytes) {}
size_t size_in_bytes; // public
};
@@ -117,8 +118,8 @@ struct XSpan_is_convertible : public std::is_convertible<From *, To *> {};
#else
// manual implementation
namespace detail {
// helper for "void"
namespace XSpan_detail {
// XSpan_void_to_T - helper for "void"
template <class T, class U>
struct XSpan_void_to_T {
typedef U type;
@@ -131,19 +132,18 @@ template <class T>
struct XSpan_void_to_T<T, const void> {
typedef T type;
};
// XSpan_ptr_is_convertible
template <class From, class To>
struct XSpan_ptr_is_convertible : public std::false_type {};
template <class T>
struct XSpan_ptr_is_convertible<T, T> : public std::true_type {};
template <class T>
struct XSpan_ptr_is_convertible<T, const T> : public std::true_type {};
} // namespace detail
} // namespace XSpan_detail
template <class From, class To>
struct XSpan_is_convertible
: public detail::XSpan_ptr_is_convertible<From,
typename detail::XSpan_void_to_T<From, To>::type> {};
struct XSpan_is_convertible : public XSpan_detail::XSpan_ptr_is_convertible<
From, typename XSpan_detail::XSpan_void_to_T<From, To>::type> {};
#endif
#if DEBUG
@@ -193,15 +193,38 @@ template <class T>
struct Ptr;
// XSpanInternalDummyArg: some type that is hard to match by accident
class XSpanInternalDummyArgFake; // not implemented on purpose
// (this should result in efficient code and fully get optimized away)
#if 0
// too simple, can be matched by nullptr
class XSpanInternalDummyArgFake; // not implemented on purpose
typedef XSpanInternalDummyArgFake *XSpanInternalDummyArg;
#define XSpanInternalDummyArgInit nullptr
#else
struct XSpanInternalDummyArg {
explicit forceinline XSpanInternalDummyArg(int, XSpanInternalDummyArgFake *) noexcept {}
#elif 1
// use an enum
struct XSpanInternalDummyArg final {
enum DummyEnum {};
explicit forceinline constexpr XSpanInternalDummyArg(DummyEnum &&) noexcept {}
};
#define XSpanInternalDummyArgInit (XSPAN_NS(XSpanInternalDummyArg)(0, nullptr))
#define XSpanInternalDummyArgInit \
(XSPAN_NS(XSpanInternalDummyArg)(XSPAN_NS(XSpanInternalDummyArg)::DummyEnum{}))
#else
// use a class with a private constructor
struct XSpanInternalDummyArg final {
static forceinline constexpr XSpanInternalDummyArg make() noexcept {
return XSpanInternalDummyArg{};
}
private:
explicit forceinline constexpr XSpanInternalDummyArg() noexcept {}
#if !(ACC_CC_MSC) // MSVC wants to use the copy and move constructors; correct or compiler bug?
// @COMPILER_BUG @MSVC_BUG
XSpanInternalDummyArg(const XSpanInternalDummyArg &) = delete;
XSpanInternalDummyArg(XSpanInternalDummyArg &&) noexcept = delete;
XSpanInternalDummyArg &operator=(const XSpanInternalDummyArg &) = delete;
XSpanInternalDummyArg &operator=(XSpanInternalDummyArg &&) noexcept = delete;
#endif
};
#define XSpanInternalDummyArgInit \
(XSPAN_NS(XSpanInternalDummyArg)(XSPAN_NS(XSpanInternalDummyArg)::make()))
#endif
// poison a pointer: point to a non-null invalid address
@@ -209,7 +232,7 @@ struct XSpanInternalDummyArg {
// - this should be efficient (so no mmap() guard page etc.)
// - this should play nice with runtime checkers like ASAN, MSAN, valgrind, etc.
// - this should play nice with static analyzers like clang-tidy etc.
static forceinline void *XSPAN_GET_POISON_VOID_PTR() {
static forceinline void *XSPAN_GET_POISON_VOID_PTR() noexcept {
// return (void *) (upx_uintptr_t) 251; // NOLINT(performance-no-int-to-ptr)
return (void *) 251;
}
+2 -2
View File
@@ -58,7 +58,7 @@ private:
// debug - internal sanity check; also serves as pseudo-documentation
#if DEBUG
noinline void assertInvariants() const {
noinline void assertInvariants() const may_throw {
if __acc_cte (configRequirePtr)
assert(ptr != nullptr);
if __acc_cte (configRequireBase)
@@ -68,7 +68,7 @@ private:
xspan_check_range(ptr, base, size_in_bytes);
}
#else
forceinline void assertInvariants() const noexcept {}
forceinline constexpr void assertInvariants() const noexcept {}
#endif
static inline pointer makeNotNull(pointer p) {
+1 -1
View File
@@ -55,7 +55,7 @@ private:
// inverse logic for ensuring valid pointers from existing objects
inline pointer ensurePtr() const { return ptr; }
// debug
inline void assertInvariants() const noexcept {}
forceinline constexpr void assertInvariants() const noexcept {}
public:
#if XSPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION || 1