diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 668f3226..7f2c1870 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,5 +4,6 @@ updates: - package-ecosystem: 'github-actions' directory: '/' schedule: - # Check for updates to GitHub Actions every weekday - interval: 'daily' + # Check for updates to GitHub Actions every Wednesday + interval: 'weekly' + day: 'wednesday' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c001e52b..3bf2ecfb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -205,7 +205,6 @@ jobs: # windows-2019 used to work but got broken with the 20220821.1 runner-image # update; we cannot download that image for inspection, and debugging the # remote image is painful, so disable for now - # see https://github.com/actions/runner-images.git ####- { name: windows-2019-amd64, os: windows-2019 } - { name: windows-2022-amd64, os: windows-2022 } steps: @@ -215,7 +214,7 @@ jobs: - name: 'Check out test suite' run: 'git clone --depth=1 https://github.com/upx/upx-testsuite ../deps/upx-testsuite' - name: 'Inspect runner-image settings' - # debug remote image; also see https://github.com/actions/runner-images.git + # debug remote image; see https://github.com/actions/runner-images.git if: ${{ false }} run: | Get-Command bash; Get-Command cmake; Get-Command make @@ -377,8 +376,8 @@ jobs: - { zig_target: x86_64-macos.13-none } - { zig_target: x86_64-windows-gnu } env: - # 2023-03-18 - ZIG_DIST_VERSION: 0.11.0-dev.2157+f56f3c582 + # 2023-04-17 + ZIG_DIST_VERSION: 0.11.0-dev.2624+bc804eb84 # for zig-cc wrapper scripts (see below): ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING ZIG_FLAGS: ${{ matrix.zig_flags }} diff --git a/.github/workflows/close-stale-issues.yml b/.github/workflows/close-stale-issues.yml index 4bcf158d..5c7adf20 100644 --- a/.github/workflows/close-stale-issues.yml +++ b/.github/workflows/close-stale-issues.yml @@ -23,11 +23,11 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v7 + - uses: actions/stale@v8 with: operations-per-run: 300 exempt-all-milestones: true - exempt-issue-labels: 'blocker,enhancement,help wanted,regression' + exempt-issue-labels: 'blocker,bug,enhancement,help wanted,regression' days-before-stale: 60 days-before-close: 30 stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Please remove the stale label or add a comment or this issue will be closed in 30 days.' diff --git a/.github/workflows/minimal-ci.yml b/.github/workflows/minimal-ci.yml index 0420ad15..695505a5 100644 --- a/.github/workflows/minimal-ci.yml +++ b/.github/workflows/minimal-ci.yml @@ -7,7 +7,7 @@ jobs: job-alpine-cmake: strategy: fail-fast: false - matrix: {container: ['alpine:3.12','alpine:3.17','alpine:edge','i386/alpine:edge']} + matrix: { container: ['alpine:3.12','alpine:3.17','alpine:edge','i386/alpine:edge'] } name: ${{ format('container {0}', matrix.container) }} runs-on: ubuntu-latest container: ${{ matrix.container }} @@ -23,7 +23,7 @@ jobs: - { name: 'Build gcc', run: 'make -C upx UPX_XTARGET=gcc-static CC="gcc -static" CXX="g++ -static"' } - { name: 'Strip release binaries', run: 'strip -p --strip-unneeded upx/build/*/*/release/upx' } - name: ${{ format('Upload artifact {0}', env.artifact_name) }} - if: ${{ !startsWith(matrix.container, 'i386/alpine') }} # missing nodejs + if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: missing nodejs on host uses: actions/upload-artifact@v3 with: name: ${{ env.artifact_name }} diff --git a/.gitignore b/.gitignore index 4275a77e..fcd73630 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ tmp* *.py[cdo] *.so *.swp +*.tmp *.ttp doc/*.man diff --git a/CMakeLists.txt b/CMakeLists.txt index ec68b290..8a6f7572 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,7 +187,7 @@ endif() # compile a target with -O2 even in Debug build function(upx_compile_target_debug_with_O2 t) if(MSVC) - # msvc uses some Debug compile options like -RTC1 that are incompatible with -O2 + # MSVC uses some Debug compile options like -RTC1 that are incompatible with -O2 else() target_compile_options(${t} PRIVATE $<$:-O2>) endif() @@ -196,7 +196,7 @@ endfunction() function(upx_sanitize_target t) if(NOT UPX_CONFIG_DISABLE_SANITIZE) if(MSVC) - # msvc uses -GS (similar to -fstack-protector) by default + # MSVC uses -GS (similar to -fstack-protector) by default elseif(CMAKE_C_PLATFORM_ID MATCHES "^MinGW" OR MINGW OR CYGWIN) # avoid link errors with current MinGW-w64 versions # see https://www.mingw-w64.org/contribute/#sanitizers-asan-tsan-usan @@ -242,7 +242,7 @@ if(MSVC) else() target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror}) endif() -endif() +endif() # UPX_CONFIG_DISABLE_ZSTD set(t upx) target_include_directories(${t} PRIVATE vendor) @@ -301,7 +301,7 @@ if(NOT CMAKE_CROSSCOMPILING AND NOT UPX_CONFIG_DISABLE_SELF_PACK_TEST) upx_add_test(upx-self-pack-n2b upx -3 --nrv2b ${upx_self_exe} ${fo} -o upx-packed-n2b${exe}) upx_add_test(upx-self-pack-n2d upx -3 --nrv2d ${upx_self_exe} ${fo} -o upx-packed-n2d${exe}) upx_add_test(upx-self-pack-n2e upx -3 --nrv2e ${upx_self_exe} ${fo} -o upx-packed-n2e${exe}) - upx_add_test(upx-self-pack-lzma upx -3 --lzma ${upx_self_exe} ${fo} -o upx-packed-lzma${exe}) + upx_add_test(upx-self-pack-lzma upx -1 --lzma ${upx_self_exe} ${fo} -o upx-packed-lzma${exe}) upx_add_test(upx-list upx -l upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe}) upx_add_test(upx-fileinfo upx --fileinfo upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe}) upx_add_test(upx-test upx -t upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe}) diff --git a/Makefile b/Makefile index b1eb7d8f..c2a19005 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,9 @@ release: build/release .SECONDEXPANSION: .SUFFIXES: +# # END of Makefile; extra stuff follows +# #*********************************************************************** # extra builds: some pre-defined build configurations diff --git a/misc/rebuild-stubs-with-podman/Dockerfile b/misc/rebuild-stubs-with-podman/Dockerfile index e7498d9e..a29e347f 100644 --- a/misc/rebuild-stubs-with-podman/Dockerfile +++ b/misc/rebuild-stubs-with-podman/Dockerfile @@ -24,7 +24,7 @@ RUN dpkg --add-architecture i386 \ # manually install compat libs from Ubuntu 16.04; REQUIRED RUN cd /root \ && aria2c --checksum=sha-256=de22baf3dd851a10e16fbf66a243e70149ca46e06b2939fdc79429196cefc090 \ - 'http://archive.kernel.org/ubuntu-archive/ubuntu/pool/main/m/mpfr4/libmpfr4_3.1.6-1_amd64.deb' \ + 'https://archive.kernel.org/ubuntu-archive/ubuntu/pool/main/m/mpfr4/libmpfr4_3.1.6-1_amd64.deb' \ && mkdir packages \ && for f in ./*.deb; do dpkg -x $f ./packages; done \ && mv -v -n ./packages/usr/lib/x86_64-linux-gnu/lib* /usr/lib/x86_64-linux-gnu/ \ diff --git a/src/Makefile b/src/Makefile index d83a2ba8..23e20d88 100644 --- a/src/Makefile +++ b/src/Makefile @@ -103,7 +103,7 @@ 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) endif -check-whitespace : PHONY ; $(CHECK_WHITESPACE) +check-whitespace: PHONY; $(CHECK_WHITESPACE) endif # vim:set ts=8 sw=8 noet: diff --git a/src/bele.h b/src/bele.h index e4527d0a..4c7f7aaf 100644 --- a/src/bele.h +++ b/src/bele.h @@ -129,62 +129,62 @@ static forceinline constexpr upx_uint64_t no_bswap64(upx_uint64_t v) noexcept { // get/set 16/32/64 **************************************************************************/ -inline unsigned get_be16(const void *p) { return ne16_to_be16(get_ne16(p)); } -inline unsigned get_be32(const void *p) { return ne32_to_be32(get_ne32(p)); } -inline upx_uint64_t get_be64(const void *p) { return ne64_to_be64(get_ne64(p)); } -inline unsigned get_le16(const void *p) { return ne16_to_le16(get_ne16(p)); } -inline unsigned get_le32(const void *p) { return ne32_to_le32(get_ne32(p)); } -inline upx_uint64_t get_le64(const void *p) { return ne64_to_le64(get_ne64(p)); } -inline void set_be16(void *p, unsigned v) { set_ne16(p, ne16_to_be16(v)); } -inline void set_be32(void *p, unsigned v) { set_ne32(p, ne32_to_be32(v)); } -inline void set_be64(void *p, upx_uint64_t v) { set_ne64(p, ne64_to_be64(v)); } -inline void set_le16(void *p, unsigned v) { set_ne16(p, ne16_to_le16(v)); } -inline void set_le32(void *p, unsigned v) { set_ne32(p, ne32_to_le32(v)); } -inline void set_le64(void *p, upx_uint64_t v) { set_ne64(p, ne64_to_le64(v)); } +inline unsigned get_be16(const void *p) noexcept { return ne16_to_be16(get_ne16(p)); } +inline unsigned get_be32(const void *p) noexcept { return ne32_to_be32(get_ne32(p)); } +inline upx_uint64_t get_be64(const void *p) noexcept { return ne64_to_be64(get_ne64(p)); } +inline unsigned get_le16(const void *p) noexcept { return ne16_to_le16(get_ne16(p)); } +inline unsigned get_le32(const void *p) noexcept { return ne32_to_le32(get_ne32(p)); } +inline upx_uint64_t get_le64(const void *p) noexcept { return ne64_to_le64(get_ne64(p)); } +inline void set_be16(void *p, unsigned v) noexcept { set_ne16(p, ne16_to_be16(v)); } +inline void set_be32(void *p, unsigned v) noexcept { set_ne32(p, ne32_to_be32(v)); } +inline void set_be64(void *p, upx_uint64_t v) noexcept { set_ne64(p, ne64_to_be64(v)); } +inline void set_le16(void *p, unsigned v) noexcept { set_ne16(p, ne16_to_le16(v)); } +inline void set_le32(void *p, unsigned v) noexcept { set_ne32(p, ne32_to_le32(v)); } +inline void set_le64(void *p, upx_uint64_t v) noexcept { set_ne64(p, ne64_to_le64(v)); } /************************************************************************* // get/set 24/26 **************************************************************************/ -inline unsigned get_be24(const void *p) { +inline unsigned get_be24(const void *p) noexcept { const byte *b = ACC_CCAST(const byte *, p); return (b[0] << 16) | (b[1] << 8) | (b[2] << 0); } -inline unsigned get_le24(const void *p) { +inline unsigned get_le24(const void *p) noexcept { const byte *b = ACC_CCAST(const byte *, p); return (b[0] << 0) | (b[1] << 8) | (b[2] << 16); } -inline void set_be24(void *p, unsigned v) { +inline void set_be24(void *p, unsigned v) noexcept { byte *b = ACC_PCAST(byte *, p); b[0] = ACC_ICONV(byte, (v >> 16) & 0xff); b[1] = ACC_ICONV(byte, (v >> 8) & 0xff); b[2] = ACC_ICONV(byte, (v >> 0) & 0xff); } -inline void set_le24(void *p, unsigned v) { +inline void set_le24(void *p, unsigned v) noexcept { byte *b = ACC_PCAST(byte *, p); b[0] = ACC_ICONV(byte, (v >> 0) & 0xff); b[1] = ACC_ICONV(byte, (v >> 8) & 0xff); b[2] = ACC_ICONV(byte, (v >> 16) & 0xff); } -inline unsigned get_le26(const void *p) { return get_le32(p) & 0x03ffffff; } -inline unsigned get_le19_5(const void *p) { return 0x7ffff & (get_le32(p) >> 5); } -inline unsigned get_le14_5(const void *p) { return 0x03fff & (get_le32(p) >> 5); } +inline unsigned get_le26(const void *p) noexcept { return get_le32(p) & 0x03ffffff; } +inline unsigned get_le19_5(const void *p) noexcept { return 0x7ffff & (get_le32(p) >> 5); } +inline unsigned get_le14_5(const void *p) noexcept { return 0x03fff & (get_le32(p) >> 5); } -inline void set_le26(void *p, unsigned v) { +inline void set_le26(void *p, unsigned v) noexcept { // preserve the top 6 bits // set_le32(p, (get_le32(p) & 0xfc000000) | (v & 0x03ffffff)); // optimized version, saving a runtime bswap32 set_ne32(p, (get_ne32(p) & ne32_to_le32(0xfc000000)) | (ne32_to_le32(v) & ne32_to_le32(0x03ffffff))); } -inline void set_le19_5(void *p, unsigned v) { +inline void set_le19_5(void *p, unsigned v) noexcept { set_le32(p, (get_le32(p) & 0xff00001f) | ((v & 0x07ffff) << 5)); } -inline void set_le14_5(void *p, unsigned v) { +inline void set_le14_5(void *p, unsigned v) noexcept { set_le32(p, (get_le32(p) & 0xfff8001f) | ((v & 0x003fff) << 5)); } @@ -206,42 +206,42 @@ static forceinline upx_int64_t sign_extend(upx_uint64_t v, unsigned bits) noexce return ACC_ICAST(upx_int64_t, v); } -inline int get_be16_signed(const void *p) { +inline int get_be16_signed(const void *p) noexcept { unsigned v = get_be16(p); return sign_extend(v, 16); } -inline int get_be24_signed(const void *p) { +inline int get_be24_signed(const void *p) noexcept { unsigned v = get_be24(p); return sign_extend(v, 24); } -inline int get_be32_signed(const void *p) { +inline int get_be32_signed(const void *p) noexcept { unsigned v = get_be32(p); return sign_extend(v, 32); } -inline upx_int64_t get_be64_signed(const void *p) { +inline upx_int64_t get_be64_signed(const void *p) noexcept { upx_uint64_t v = get_be64(p); return sign_extend(v, 64); } -inline int get_le16_signed(const void *p) { +inline int get_le16_signed(const void *p) noexcept { unsigned v = get_le16(p); return sign_extend(v, 16); } -inline int get_le24_signed(const void *p) { +inline int get_le24_signed(const void *p) noexcept { unsigned v = get_le24(p); return sign_extend(v, 24); } -inline int get_le32_signed(const void *p) { +inline int get_le32_signed(const void *p) noexcept { unsigned v = get_le32(p); return sign_extend(v, 32); } -inline upx_int64_t get_le64_signed(const void *p) { +inline upx_int64_t get_le64_signed(const void *p) noexcept { upx_uint64_t v = get_le64(p); return sign_extend(v, 64); } @@ -257,11 +257,13 @@ inline upx_int64_t get_le64_signed(const void *p) { // to have gcc bug 17519 fixed - see http://gcc.gnu.org/PR17519 ] **************************************************************************/ -struct alignas(1) BE16 { +struct alignas(1) BE16 final { typedef unsigned integral_conversion_type; // automatic conversion to unsigned byte d[2]; - BE16 &operator=(unsigned v) noexcept { + forceinline operator unsigned() const noexcept { return get_be16(d); } + + forceinline BE16 &operator=(unsigned v) noexcept { set_be16(d, v); return *this; } @@ -302,16 +304,17 @@ struct alignas(1) BE16 { return *this; } - operator unsigned() const noexcept { return get_be16(d); } - - bool operator<(const BE16 &v) const noexcept { return unsigned(*this) < unsigned(v); } + bool operator==(const BE16 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } + bool operator<(const BE16 &x) const noexcept { return unsigned(*this) < unsigned(x); } }; -struct alignas(1) BE32 { +struct alignas(1) BE32 final { typedef unsigned integral_conversion_type; // automatic conversion to unsigned byte d[4]; - BE32 &operator=(unsigned v) noexcept { + forceinline operator unsigned() const noexcept { return get_be32(d); } + + forceinline BE32 &operator=(unsigned v) noexcept { set_be32(d, v); return *this; } @@ -352,16 +355,17 @@ struct alignas(1) BE32 { return *this; } - operator unsigned() const noexcept { return get_be32(d); } - - bool operator<(const BE32 &v) const noexcept { return unsigned(*this) < unsigned(v); } + bool operator==(const BE32 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } + bool operator<(const BE32 &x) const noexcept { return unsigned(*this) < unsigned(x); } }; -struct alignas(1) BE64 { +struct alignas(1) BE64 final { typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t byte d[8]; - BE64 &operator=(upx_uint64_t v) noexcept { + forceinline operator upx_uint64_t() const noexcept { return get_be64(d); } + + forceinline BE64 &operator=(upx_uint64_t v) noexcept { set_be64(d, v); return *this; } @@ -402,16 +406,17 @@ struct alignas(1) BE64 { return *this; } - operator upx_uint64_t() const noexcept { return get_be64(d); } - - bool operator<(const BE64 &v) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(v); } + bool operator==(const BE64 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } + bool operator<(const BE64 &x) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(x); } }; -struct alignas(1) LE16 { +struct alignas(1) LE16 final { typedef unsigned integral_conversion_type; // automatic conversion to unsigned byte d[2]; - LE16 &operator=(unsigned v) noexcept { + forceinline operator unsigned() const noexcept { return get_le16(d); } + + forceinline LE16 &operator=(unsigned v) noexcept { set_le16(d, v); return *this; } @@ -452,16 +457,17 @@ struct alignas(1) LE16 { return *this; } - operator unsigned() const noexcept { return get_le16(d); } - - bool operator<(const LE16 &v) const noexcept { return unsigned(*this) < unsigned(v); } + bool operator==(const LE16 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } + bool operator<(const LE16 &x) const noexcept { return unsigned(*this) < unsigned(x); } }; -struct alignas(1) LE32 { +struct alignas(1) LE32 final { typedef unsigned integral_conversion_type; // automatic conversion to unsigned byte d[4]; - LE32 &operator=(unsigned v) noexcept { + forceinline operator unsigned() const noexcept { return get_le32(d); } + + forceinline LE32 &operator=(unsigned v) noexcept { set_le32(d, v); return *this; } @@ -502,16 +508,17 @@ struct alignas(1) LE32 { return *this; } - operator unsigned() const noexcept { return get_le32(d); } - - bool operator<(const LE32 &v) const noexcept { return unsigned(*this) < unsigned(v); } + bool operator==(const LE32 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } + bool operator<(const LE32 &x) const noexcept { return unsigned(*this) < unsigned(x); } }; -struct alignas(1) LE64 { +struct alignas(1) LE64 final { typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t byte d[8]; - LE64 &operator=(upx_uint64_t v) noexcept { + forceinline operator upx_uint64_t() const noexcept { return get_le64(d); } + + forceinline LE64 &operator=(upx_uint64_t v) noexcept { set_le64(d, v); return *this; } @@ -552,9 +559,8 @@ struct alignas(1) LE64 { return *this; } - operator upx_uint64_t() const noexcept { return get_le64(d); } - - bool operator<(const LE64 &v) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(v); } + bool operator==(const LE64 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } + bool operator<(const LE64 &x) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(x); } }; /************************************************************************* @@ -642,39 +648,6 @@ inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN(unsigned(a), // misc support **************************************************************************/ -template <> -struct upx_is_integral : public std::true_type {}; -template <> -struct upx_is_integral : public std::true_type {}; -template <> -struct upx_is_integral : public std::true_type {}; -template <> -struct upx_is_integral : public std::true_type {}; -template <> -struct upx_is_integral : public std::true_type {}; -template <> -struct upx_is_integral : public std::true_type {}; - -// for use with qsort() -extern "C" { -int __acc_cdecl_qsort be16_compare(const void *, const void *); -int __acc_cdecl_qsort be24_compare(const void *, const void *); -int __acc_cdecl_qsort be32_compare(const void *, const void *); -int __acc_cdecl_qsort be64_compare(const void *, const void *); -int __acc_cdecl_qsort le16_compare(const void *, const void *); -int __acc_cdecl_qsort le24_compare(const void *, const void *); -int __acc_cdecl_qsort le32_compare(const void *, const void *); -int __acc_cdecl_qsort le64_compare(const void *, const void *); -int __acc_cdecl_qsort be16_compare_signed(const void *, const void *); -int __acc_cdecl_qsort be24_compare_signed(const void *, const void *); -int __acc_cdecl_qsort be32_compare_signed(const void *, const void *); -int __acc_cdecl_qsort be64_compare_signed(const void *, const void *); -int __acc_cdecl_qsort le16_compare_signed(const void *, const void *); -int __acc_cdecl_qsort le24_compare_signed(const void *, const void *); -int __acc_cdecl_qsort le32_compare_signed(const void *, const void *); -int __acc_cdecl_qsort le64_compare_signed(const void *, const void *); -} // extern "C" - // native types #if (ACC_ABI_BIG_ENDIAN) typedef BE16 NE16; @@ -698,6 +671,44 @@ typedef LE64 NE64; #define ne64_compare_signed le64_compare_signed #endif +// upx_is_integral +#define TT_IS_INTEGRAL(T) \ + template <> \ + struct upx_is_integral : public std::true_type {}; \ + template <> \ + struct upx_is_integral : public std::true_type {}; \ + template <> \ + struct upx_is_integral : public std::true_type {}; \ + template <> \ + struct upx_is_integral : public std::true_type {} +TT_IS_INTEGRAL(BE16); +TT_IS_INTEGRAL(BE32); +TT_IS_INTEGRAL(BE64); +TT_IS_INTEGRAL(LE16); +TT_IS_INTEGRAL(LE32); +TT_IS_INTEGRAL(LE64); +#undef TT_IS_INTEGRAL + +// for use with qsort() +extern "C" { +int __acc_cdecl_qsort be16_compare(const void *, const void *); +int __acc_cdecl_qsort be24_compare(const void *, const void *); +int __acc_cdecl_qsort be32_compare(const void *, const void *); +int __acc_cdecl_qsort be64_compare(const void *, const void *); +int __acc_cdecl_qsort le16_compare(const void *, const void *); +int __acc_cdecl_qsort le24_compare(const void *, const void *); +int __acc_cdecl_qsort le32_compare(const void *, const void *); +int __acc_cdecl_qsort le64_compare(const void *, const void *); +int __acc_cdecl_qsort be16_compare_signed(const void *, const void *); +int __acc_cdecl_qsort be24_compare_signed(const void *, const void *); +int __acc_cdecl_qsort be32_compare_signed(const void *, const void *); +int __acc_cdecl_qsort be64_compare_signed(const void *, const void *); +int __acc_cdecl_qsort le16_compare_signed(const void *, const void *); +int __acc_cdecl_qsort le24_compare_signed(const void *, const void *); +int __acc_cdecl_qsort le32_compare_signed(const void *, const void *); +int __acc_cdecl_qsort le64_compare_signed(const void *, const void *); +} // extern "C" + /************************************************************************* // Provide namespaces and classes to abstract endianness policies. // diff --git a/src/bele_policy.h b/src/bele_policy.h index 0370b3a7..f1e8cf26 100644 --- a/src/bele_policy.h +++ b/src/bele_policy.h @@ -216,10 +216,12 @@ private: ACC_CXX_DISABLE_NEW_DELETE }; -// native policy (aka host policy) +// Native Endianness policy (aka host policy) #if (ACC_ABI_BIG_ENDIAN) +typedef BEPolicy NEPolicy; typedef BEPolicy HostPolicy; #elif (ACC_ABI_LITTLE_ENDIAN) +typedef LEPolicy NEPolicy; typedef LEPolicy HostPolicy; #else #error "ACC_ABI_ENDIAN" diff --git a/src/check/dt_check.cpp b/src/check/dt_check.cpp index e3718751..46d8b400 100644 --- a/src/check/dt_check.cpp +++ b/src/check/dt_check.cpp @@ -83,6 +83,7 @@ int upx_doctest_check() { return upx_doctest_check(0, nullptr); } // compile-time checks **************************************************************************/ +// need extra paranthesis because the C preprocessor does not understand C++ templates ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) @@ -90,10 +91,25 @@ ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) +ACC_COMPILE_TIME_ASSERT_HEADER((is_same_all_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((is_same_all_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((is_same_all_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_all_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_all_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_all_v) ) + +ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_any_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((is_same_any_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((is_same_any_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((is_same_any_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_any_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_any_v) ) +ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_any_v) ) + ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap16(0x04030201) == 0x0201) ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap32(0x04030201) == 0x04030201) ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap64(0x0807060504030201ull) == 0x0807060504030201ull) -#if !(ACC_CC_MSC) +#if !(ACC_CC_MSC) // unfortunately *not* constexpr with current MSVC ACC_COMPILE_TIME_ASSERT_HEADER(bswap16(0x04030201) == 0x0102) ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(0x04030201) == 0x01020304) ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(0x0807060504030201ull) == 0x0102030405060708ull) @@ -145,83 +161,100 @@ ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 > 0) namespace { +template +struct CheckIntegral { + template + static void checkU(void) { +#if __cplusplus < 202002L + COMPILE_TIME_ASSERT(std::is_pod::value) // deprecated in C++20 +#endif + COMPILE_TIME_ASSERT(std::is_standard_layout::value) + COMPILE_TIME_ASSERT(std::is_trivial::value) + // extra checks, these are probably implied by std::is_trivial + COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible::value) + COMPILE_TIME_ASSERT(std::is_trivially_copyable::value) + COMPILE_TIME_ASSERT(std::is_trivially_default_constructible::value) + // UPX + COMPILE_TIME_ASSERT(upx_is_integral::value) + COMPILE_TIME_ASSERT(upx_is_integral_v) + } + static void check(void) { + checkU(); + checkU::type>(); +#if !defined(__GNUC__) + // TODO later: "volatile" seems to be broken with some older g++/libstdc++ versions?? + checkU::type>(); + checkU::type>(); +#endif + } +}; +template +struct CheckAlignment { + static void check(void) { + COMPILE_TIME_ASSERT_ALIGNED1(T) + struct alignas(1) Test1 { + char a; + T b; + }; + struct alignas(1) Test2 { + char a; + T b[3]; + }; + COMPILE_TIME_ASSERT_ALIGNED1(Test1) + COMPILE_TIME_ASSERT_ALIGNED1(Test2) + Test1 t1[7]; + Test2 t2[7]; + COMPILE_TIME_ASSERT(sizeof(Test1) == 1 + sizeof(T)) + COMPILE_TIME_ASSERT(sizeof(t1) == 7 + 7 * sizeof(T)) + COMPILE_TIME_ASSERT(sizeof(Test2) == 1 + 3 * sizeof(T)) + COMPILE_TIME_ASSERT(sizeof(t2) == 7 + 21 * sizeof(T)) + UNUSED(t1); + UNUSED(t2); + } +}; template struct TestBELE { static noinline bool test(void) { - // POD checks - { - COMPILE_TIME_ASSERT(std::is_standard_layout::value) - COMPILE_TIME_ASSERT(std::is_trivial::value) - // extra checks, these are probably implied by std::is_trivial - COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible::value) - COMPILE_TIME_ASSERT(std::is_trivially_copyable::value) - COMPILE_TIME_ASSERT(std::is_trivially_default_constructible::value) - // UPX - COMPILE_TIME_ASSERT(upx_is_integral::value) - COMPILE_TIME_ASSERT(upx_is_integral_v) - } - // alignment checks - { - COMPILE_TIME_ASSERT_ALIGNED1(T) - struct alignas(1) test1_t { - char a; - T b; - }; - struct alignas(1) test2_t { - char a; - T b[3]; - }; - COMPILE_TIME_ASSERT_ALIGNED1(test1_t) - COMPILE_TIME_ASSERT_ALIGNED1(test2_t) - test1_t t1[7]; - test2_t t2[7]; - COMPILE_TIME_ASSERT(sizeof(test1_t) == 1 + sizeof(T)) - COMPILE_TIME_ASSERT(sizeof(t1) == 7 + 7 * sizeof(T)) - COMPILE_TIME_ASSERT(sizeof(test2_t) == 1 + 3 * sizeof(T)) - COMPILE_TIME_ASSERT(sizeof(t2) == 7 + 21 * sizeof(T)) - UNUSED(t1); - UNUSED(t2); - } + CheckIntegral::check(); + CheckAlignment::check(); // arithmetic checks (modern compilers will optimize this away) - { - T allbits; - allbits = 0; - allbits += 1; - allbits -= 2; - T v1; - v1 = 1; - v1 *= 2; - v1 /= 1; - v1 -= 1; - T v2; - v2 = 1; - assert((v1 == v2)); - assert(!(v1 != v2)); - assert((v1 <= v2)); - assert((v1 >= v2)); - assert(!(v1 < v2)); - assert(!(v1 > v2)); - v2 ^= allbits; - assert(!(v1 == v2)); - assert((v1 != v2)); - assert((v1 <= v2)); - assert(!(v1 >= v2)); - assert((v1 < v2)); - assert(!(v1 > v2)); - v2 += 2; - assert(v1 == 1); - assert(v2 == 0); - v1 <<= 1; - v1 |= v2; - v1 >>= 1; - v2 &= v1; - v2 /= v1; - v2 *= v1; - assert(v1 == 1); - assert(v2 == 0); - if ((v1 ^ v2) != 1) - return false; - } + T allbits; + allbits = 0; + allbits += 1; + allbits -= 2; + T v1; + v1 = 1; + v1 *= 2; + v1 /= 1; + v1 -= 1; + T v2; + v2 = 1; + assert((v1 == v2)); + assert(!(v1 != v2)); + assert((v1 <= v2)); + assert((v1 >= v2)); + assert(!(v1 < v2)); + assert(!(v1 > v2)); + v2 ^= allbits; + assert(!(v1 == v2)); + assert((v1 != v2)); + assert((v1 <= v2)); + assert(!(v1 >= v2)); + assert((v1 < v2)); + assert(!(v1 > v2)); + v2 += 2; + assert(v1 == 1); + assert(v2 == 0); + v1 <<= 1; + v1 |= v2; + v1 >>= 1; + v2 &= v1; + v2 /= v1; + v2 *= v1; + assert(v1 == 1); + assert(v2 == 0); + if ((v1 ^ v2) != 1) + return false; return true; } }; @@ -278,6 +311,18 @@ void upx_compiler_sanity_check(void) { COMPILE_TIME_ASSERT_ALIGNED1(LE32) COMPILE_TIME_ASSERT_ALIGNED1(LE64) + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + CheckIntegral::check(); + COMPILE_TIME_ASSERT(sizeof(upx_charptr_unit_type) == 1) COMPILE_TIME_ASSERT_ALIGNED1(upx_charptr_unit_type) COMPILE_TIME_ASSERT(sizeof(*((charptr) nullptr)) == 1) diff --git a/src/compress/compress_lzma.cpp b/src/compress/compress_lzma.cpp index 33e76072..0ec44d90 100644 --- a/src/compress/compress_lzma.cpp +++ b/src/compress/compress_lzma.cpp @@ -194,8 +194,8 @@ static bool prepare_result(lzma_compress_result_t *res, unsigned src_len, int me lzma_compress_config_t::num_fast_bytes_t::assertValue(res->num_fast_bytes); res->num_probs = 1846 + (768u << (res->lit_context_bits + res->lit_pos_bits)); - // printf("\nlzma_compress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, - // res->lit_context_bits, res->dict_size, res->num_probs); + NO_printf("\nlzma_compress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, + res->lit_context_bits, res->dict_size, res->num_probs); return true; error: @@ -375,7 +375,7 @@ int upx_lzma_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsi // UPX extra stuff in first byte: 5 high bits convenience for stub decompressor unsigned t = res->lit_context_bits + res->lit_pos_bits; os.WriteByte(Byte((t << 3) | res->pos_bits)); - os.WriteByte(Byte((res->lit_pos_bits << 4) | (res->lit_context_bits))); + os.WriteByte(Byte((res->lit_pos_bits << 4) | res->lit_context_bits)); // compress rh = enc.Code(&is, &os, nullptr, nullptr, &progress); @@ -399,10 +399,10 @@ int upx_lzma_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsi error: *dst_len = (unsigned) os.b_pos; - // printf("\nlzma_compress: %d: %u %u %u %u %u, %u - > %u\n", r, res->pos_bits, - // res->lit_pos_bits, - // res->lit_context_bits, res->dict_size, res->num_probs, src_len, *dst_len); - // printf("%u %u %u\n", is.__m_RefCount, os.__m_RefCount, progress.__m_RefCount); + NO_printf("\nlzma_compress: %d: %u %u %u %u %u, %u - > %u\n", r, res->pos_bits, + res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs, src_len, + *dst_len); + NO_printf("%u %u %u\n", is.__m_RefCount, os.__m_RefCount, progress.__m_RefCount); return r; } @@ -458,8 +458,8 @@ int upx_lzma_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, un assert(cresult->result_lzma.lit_context_bits == (unsigned) s.Properties.lc); assert(cresult->result_lzma.num_probs == (unsigned) LzmaGetNumProbs(&s.Properties)); const lzma_compress_result_t *res = &cresult->result_lzma; - // printf("\nlzma_decompress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, - // res->lit_context_bits, res->dict_size, res->num_probs); + NO_printf("\nlzma_decompress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, + res->lit_context_bits, res->dict_size, res->num_probs); UNUSED(res); } s.Probs = (CProb *) malloc(sizeof(CProb) * LzmaGetNumProbs(&s.Properties)); diff --git a/src/conf.h b/src/conf.h index 3291ec93..b6457e4a 100644 --- a/src/conf.h +++ b/src/conf.h @@ -96,7 +96,17 @@ struct upx_std_is_bounded_array : public std::true_type {}; template inline constexpr bool upx_std_is_bounded_array_v = upx_std_is_bounded_array::value; -// see bele.h +// is_same_all and is_same_any: std::is_same for multiple types +template +struct is_same_all : public std::conjunction...> {}; +template +inline constexpr bool is_same_all_v = is_same_all::value; +template +struct is_same_any : public std::disjunction...> {}; +template +inline constexpr bool is_same_any_v = is_same_any::value; + +// upx_is_integral is overloaded for BE16 & friends; see bele.h template struct upx_is_integral : public std::is_integral {}; template @@ -148,7 +158,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(upx_charptr_unit_type) == 1) typedef upx_int64_t upx_off_t; #undef off_t #if 0 -// at some future point we can do this... +// TODO cleanup: at some future point we can do this... #define off_t DO_NOT_USE_off_t #else #define off_t upx_off_t @@ -593,9 +603,9 @@ template struct OptVar { typedef T value_type; - static const T default_value = default_value_; - static const T min_value = min_value_; - static const T max_value = max_value_; + static constexpr T default_value = default_value_; + static constexpr T min_value = min_value_; + static constexpr T max_value = max_value_; static void assertValue(const T &v) { // info: this generates annoying warnings "unsigned >= 0 is always true" diff --git a/src/headers.h b/src/headers.h index e2e0b2a5..df9ff9cd 100644 --- a/src/headers.h +++ b/src/headers.h @@ -49,9 +49,10 @@ // disable some pedantic warnings #if (ACC_CC_MSC) -#pragma warning(disable : 4244) // -Wconversion -#pragma warning(disable : 4267) // -Wconversion -#pragma warning(disable : 4820) // padding added after data member +#pragma warning(disable : 4127) // W4: conditional expression is constant +#pragma warning(disable : 4244) // W3: conversion from 'type1' to 'type2', possible loss of data +#pragma warning(disable : 4267) // W3: conversion from 'size_t' to 'type', possible loss of data +#pragma warning(disable : 4820) // W4: padding added after data member #endif #undef snprintf @@ -83,7 +84,7 @@ #include #endif -// C++ submodule headers +// UPX vendor git submodule headers #include #if WITH_BOOST_PFR #include diff --git a/src/main.cpp b/src/main.cpp index f3613a3e..b0c99961 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -119,16 +119,6 @@ __acc_static_noinline void e_usage(void) { e_exit(EXIT_USAGE); } -#if 0 // UNUSED -static void e_memory(void) -{ - show_head(); - fflush(con_term); - fprintf(stderr,"%s: out of memory\n", argv0); - e_exit(EXIT_MEMORY); -} -#endif // UNUSED - static void e_method(int m, int l) { fflush(con_term); fprintf(stderr, "%s: illegal method option -- %d/%d\n", argv0, m, l); @@ -159,22 +149,13 @@ static void e_envopt(const char *n) { } #endif /* defined(OPTIONS_VAR) */ -#if 0 // UNUSED -static void __acc_cdecl_sighandler e_sighandler(int signum) -{ - UNUSED(signum); - e_exit(EXIT_FATAL); -} -#endif // UNUSED - /************************************************************************* // check options **************************************************************************/ static void check_not_both(bool e1, bool e2, const char *c1, const char *c2) { if (e1 && e2) { - fprintf(stderr, "%s: ", argv0); - fprintf(stderr, "cannot use both '%s' and '%s'\n", c1, c2); + fprintf(stderr, "%s: cannot use both '%s' and '%s'\n", argv0, c1, c2); e_usage(); } } diff --git a/src/msg.cpp b/src/msg.cpp index 4615306b..8b6e77f4 100644 --- a/src/msg.cpp +++ b/src/msg.cpp @@ -26,12 +26,11 @@ */ #include "headers.h" -#include +#include // typeid() #include "conf.h" /************************************************************************* -// FIXME: if stdout is redirected to a file and stderr is not, should -// we write all error messages to both stderr and stdout ? +// **************************************************************************/ static int pr_need_nl = 0; @@ -112,7 +111,7 @@ void printErr(const char *iname, const Throwable *e) { snprintf(buf + l, sizeof(buf) - l, ": %s", strerror(e->getErrno())); #if 1 // some compilers (e.g. Borland C++) put a trailing '\n' - // into strerror() result + // into the strerror() result l = strlen(buf); while (l-- > 0 && (buf[l] == '\n' || buf[l] == ' ')) buf[l] = 0; @@ -154,7 +153,7 @@ void printUnhandledException(const char *iname, const std::exception *e) { } /************************************************************************* -// FIXME: should use colors and a consistent layout here +// info **************************************************************************/ static int info_header = 0; @@ -202,10 +201,8 @@ void info(const char *format, ...) { } void infoWarning(const char *format, ...) { - if (opt->info_mode <= 0) { - // FIXME - should still print something here + if (opt->info_mode <= 0) return; - } va_list args; char buf[1024]; va_start(args, format); diff --git a/src/p_elf.h b/src/p_elf.h index f227be94..62b51b49 100644 --- a/src/p_elf.h +++ b/src/p_elf.h @@ -25,11 +25,7 @@ */ - #pragma once -#ifndef __UPX_P_ELF_H -#define __UPX_P_ELF_H 1 - /************************************************************************* // N_Elf @@ -315,6 +311,7 @@ struct ElfClass_32 COMPILE_TIME_ASSERT(sizeof(Rel) == 8) COMPILE_TIME_ASSERT(sizeof(Rela) == 12) COMPILE_TIME_ASSERT(sizeof(Sym) == 16) + COMPILE_TIME_ASSERT(sizeof(External_Note) == 12) COMPILE_TIME_ASSERT_ALIGNED1(Ehdr) COMPILE_TIME_ASSERT_ALIGNED1(Phdr) COMPILE_TIME_ASSERT_ALIGNED1(Shdr) @@ -322,6 +319,7 @@ struct ElfClass_32 COMPILE_TIME_ASSERT_ALIGNED1(Rel) COMPILE_TIME_ASSERT_ALIGNED1(Rela) COMPILE_TIME_ASSERT_ALIGNED1(Sym) + COMPILE_TIME_ASSERT_ALIGNED1(External_Note) } }; @@ -356,6 +354,7 @@ struct ElfClass_64 COMPILE_TIME_ASSERT(sizeof(Rel) == 16) COMPILE_TIME_ASSERT(sizeof(Rela) == 24) COMPILE_TIME_ASSERT(sizeof(Sym) == 24) + COMPILE_TIME_ASSERT(sizeof(External_Note) == 12) COMPILE_TIME_ASSERT_ALIGNED1(Ehdr) COMPILE_TIME_ASSERT_ALIGNED1(Phdr) COMPILE_TIME_ASSERT_ALIGNED1(Shdr) @@ -363,6 +362,7 @@ struct ElfClass_64 COMPILE_TIME_ASSERT_ALIGNED1(Rel) COMPILE_TIME_ASSERT_ALIGNED1(Rela) COMPILE_TIME_ASSERT_ALIGNED1(Sym) + COMPILE_TIME_ASSERT_ALIGNED1(External_Note) } }; @@ -436,7 +436,4 @@ typedef ElfClass_LE64::Rela Elf_LE64_Rela; typedef ElfClass_LE64::Sym Elf_LE64_Sym; typedef ElfClass_LE64::External_Note Elf_LE64_External_Note; - -#endif /* already included */ - /* vim:set ts=4 sw=4 et: */ diff --git a/src/p_elf_enum.h b/src/p_elf_enum.h index 8f87dcaf..e0641b83 100644 --- a/src/p_elf_enum.h +++ b/src/p_elf_enum.h @@ -36,7 +36,7 @@ #ifdef WANT_EHDR_ENUM #undef WANT_EHDR_ENUM - enum { // e_ident[] + enum { // indices for e_ident[16] EI_CLASS = 4, EI_DATA = 5, /* Data encoding */ EI_VERSION = 6, @@ -52,12 +52,15 @@ ELFDATA2MSB = 2, /* 2's complement, big endian */ }; enum { // e_ident[EI_OSABI] - ELFOSABI_NONE = 0, // == ELFOSABI_SYSV + ELFOSABI_NONE = 0, // == ELFOSABI_SYSV ELFOSABI_NETBSD = 2, ELFOSABI_LINUX = 3, + ELFOSABI_SOLARIS = 6, + ELFOSABI_AIX = 7, ELFOSABI_FREEBSD = 9, ELFOSABI_OPENBSD = 12, ELFOSABI_ARM = 97, + ELFOSABI_STANDALONE = 255 // Standalone (embedded) application }; enum { // e_type ET_NONE = 0, /* No file type */ @@ -67,17 +70,18 @@ ET_CORE = 4, /* Core file */ }; enum { // e_machine - EM_386 = 3, + EM_386 = 3, // i386 EM_MIPS = 8, - EM_MIPS_RS3_LE = 10, /* MIPS R3000 little-endian */ + EM_MIPS_RS3_LE = 10, // MIPS R3000 little-endian EM_PPC = 20, EM_PPC64 = 21, EM_ARM = 40, - EM_X86_64 = 62, + EM_X86_64 = 62, // amd64 EM_AMD64 = EM_X86_64, - EM_AARCH64 = 183, + EM_AARCH64 = 183, // arm64 EM_ARM64 = EM_AARCH64, - + EM_RISCV = 243, // risc-v + EM_LOONGARCH = 258, }; enum { // e_version EV_CURRENT = 1, @@ -88,7 +92,7 @@ #ifdef WANT_PHDR_ENUM #undef WANT_PHDR_ENUM enum { // p_type - PT_NULL = 0, /* Ingore: a "comment" */ + PT_NULL = 0, /* Ignore: a "comment" */ PT_LOAD = 1, /* Loadable program segment */ PT_DYNAMIC = 2, /* Dynamic linking information */ PT_INTERP = 3, /* Name of program interpreter */ diff --git a/src/p_mach.h b/src/p_mach.h index 101d4a89..165c5017 100644 --- a/src/p_mach.h +++ b/src/p_mach.h @@ -26,6 +26,7 @@ */ +#pragma once #ifndef __UPX_P_MACHO_H #define __UPX_P_MACHO_H 1 @@ -33,15 +34,10 @@ __packed_struct(Mach_fat_header) BE32 magic; -# if 0 - enum { // note conflict with java bytecode PackLinuxI386 + enum : unsigned { // note conflict with java bytecode PackLinuxI386 FAT_MAGIC = 0xcafebabe, - FAT_MAGIC_SWAB = 0xbebafeca + FAT_MAGIC_SWAB = 0xbebafeca, }; -# else - static const unsigned FAT_MAGIC = 0xcafebabe; - static const unsigned FAT_MAGIC_SWAB = 0xbebafeca; -# endif BE32 nfat_arch; // Number of Mach_fat_arch which follow. __packed_struct_end() diff --git a/src/p_unix.h b/src/p_unix.h index baa0befc..0c705249 100644 --- a/src/p_unix.h +++ b/src/p_unix.h @@ -30,6 +30,7 @@ */ +#pragma once #ifndef __UPX_P_UNIX_H #define __UPX_P_UNIX_H 1 diff --git a/src/p_vmlinx.h b/src/p_vmlinx.h index b4337e29..b3cc90b0 100644 --- a/src/p_vmlinx.h +++ b/src/p_vmlinx.h @@ -26,6 +26,7 @@ */ +#pragma once #ifndef __UPX_P_VMLINX_H #define __UPX_P_VMLINX_H 1 diff --git a/src/p_vmlinz.h b/src/p_vmlinz.h index 4f8457ad..e658d8a5 100644 --- a/src/p_vmlinz.h +++ b/src/p_vmlinz.h @@ -26,6 +26,7 @@ */ +#pragma once #ifndef __UPX_P_VMLINZ_H #define __UPX_P_VMLINZ_H 1 diff --git a/src/p_w32pe_i386.cpp b/src/p_w32pe_i386.cpp index 6f7e33fb..95dec62a 100644 --- a/src/p_w32pe_i386.cpp +++ b/src/p_w32pe_i386.cpp @@ -145,9 +145,9 @@ bool PackW32PeI386::needForceOption() const { // return true if we need `--force` to pack this file bool r = false; r |= (ih.opthdrsize != 0xe0); - r |= ((ih.flags & EXECUTABLE) == 0); - r |= ((ih.flags & BITS_32_MACHINE) == 0); // 32 bit machine flag must be set - r |= (ih.coffmagic != 0x10b); // COFF magic is 0x10B in PE files + r |= ((ih.flags & IMAGE_FILE_EXECUTABLE_IMAGE) == 0); + r |= ((ih.flags & IMAGE_FILE_32BIT_MACHINE) == 0); // 32 bit machine flag must be set + r |= (ih.coffmagic != 0x10b); // COFF magic is 0x10B in PE files r |= (ih.entry == 0 && !isdll); r |= (ih.ddirsentries != 16); r |= (IDSIZE(PEDIR_EXCEPTION) != 0); // is this used on i386? @@ -175,7 +175,7 @@ void PackW32PeI386::defineSymbols(unsigned ncsection, unsigned upxsection, unsig // UPX0 & UPX1 in the compressed files, so we have to patch the PE header // in the memory. And the page on which the PE header is stored is read // only so we must make it rw, fix the flags (i.e. clear - // PEFL_WRITE of osection[x].flags), and make it ro again. + // IMAGE_SCN_MEM_WRITE of osection[x].flags), and make it ro again. // rva of the most significant byte of member "flags" in section "UPX0" const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1; diff --git a/src/p_w64pe_amd64.cpp b/src/p_w64pe_amd64.cpp index 2d5a5d87..d463b1bb 100644 --- a/src/p_w64pe_amd64.cpp +++ b/src/p_w64pe_amd64.cpp @@ -114,7 +114,7 @@ void PackW64PeAmd64::buildLoader(const Filter *ft) { if (sorelocs) { addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2", "PERELOC3", big_relocs ? "REL64BIG" : "", "RELOC64J"); - if __acc_cte (0) { + if (0) { addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "", big_relocs & 2 ? "PERELHI0" : ""); } @@ -148,9 +148,9 @@ bool PackW64PeAmd64::needForceOption() const { // return true if we need `--force` to pack this file bool r = false; r |= (ih.opthdrsize != 0xf0); // optional header size is 0xF0 in PE32+ files - r |= ((ih.flags & EXECUTABLE) == 0); - r |= ((ih.flags & BITS_32_MACHINE) != 0); // 32 bit machine flag may not be set - r |= (ih.coffmagic != 0x20b); // COFF magic is 0x20B in PE32+ files + r |= ((ih.flags & IMAGE_FILE_EXECUTABLE_IMAGE) == 0); + r |= ((ih.flags & IMAGE_FILE_32BIT_MACHINE) != 0); // 32 bit machine flag may not be set + r |= (ih.coffmagic != 0x20b); // COFF magic is 0x20B in PE32+ files r |= (ih.entry == 0 && !isdll); r |= (ih.ddirsentries != 16); return r; @@ -176,7 +176,7 @@ void PackW64PeAmd64::defineSymbols(unsigned ncsection, unsigned upxsection, unsi // UPX0 & UPX1 in the compressed files, so we have to patch the PE header // in the memory. And the page on which the PE header is stored is read // only so we must make it rw, fix the flags (i.e. clear - // PEFL_WRITE of osection[x].flags), and make it ro again. + // IMAGE_SCN_MEM_WRITE of osection[x].flags), and make it ro again. // rva of the most significant byte of member "flags" in section "UPX0" const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1; diff --git a/src/p_wince_arm.cpp b/src/p_wince_arm.cpp index d8d0042a..4626a739 100644 --- a/src/p_wince_arm.cpp +++ b/src/p_wince_arm.cpp @@ -167,7 +167,7 @@ bool PackWinCeArm::needForceOption() const { // return true if we need `--force` to pack this file bool r = false; r |= (ih.opthdrsize != 0xe0); - r |= ((ih.flags & EXECUTABLE) == 0); + r |= ((ih.flags & IMAGE_FILE_EXECUTABLE_IMAGE) == 0); r |= (ih.entry == 0 /*&& !isdll*/); r |= (ih.ddirsentries != 16); //// r |= (IDSIZE(PEDIR_EXCEPTION) != 0); // is this used on arm? diff --git a/src/packer.h b/src/packer.h index 6d148522..0102df0c 100644 --- a/src/packer.h +++ b/src/packer.h @@ -278,12 +278,49 @@ protected: unsigned image_size, int bits, bool bswap); // Target Endianness abstraction - unsigned get_te16(const void *p) const { return bele->get16(p); } - unsigned get_te32(const void *p) const { return bele->get32(p); } - upx_uint64_t get_te64(const void *p) const { return bele->get64(p); } - void set_te16(void *p, unsigned v) { bele->set16(p, v); } - void set_te32(void *p, unsigned v) { bele->set32(p, v); } - void set_te64(void *p, upx_uint64_t v) { bele->set64(p, v); } +#if 1 + // try to detect TE16 vs TE32 vs TE64 size mismatches; note that "byte" is explicitly allowed + template + static inline constexpr bool is_te16_type = is_same_any_v; + template + static inline constexpr bool is_te32_type = is_same_any_v; + template + static inline constexpr bool is_te64_type = is_same_any_v; + + template , T> > + inline unsigned get_te16(const T *p) const noexcept { + return bele->get16(p); + } + template , T> > + inline unsigned get_te32(const T *p) const noexcept { + return bele->get32(p); + } + template , T> > + inline upx_uint64_t get_te64(const T *p) const noexcept { + return bele->get64(p); + } + + template , T> > + inline void set_te16(T *p, unsigned v) noexcept { + bele->set16(p, v); + } + template , T> > + inline void set_te32(T *p, unsigned v) noexcept { + bele->set32(p, v); + } + template , T> > + inline void set_te64(T *p, upx_uint64_t v) noexcept { + bele->set64(p, v); + } +#else + // permissive version using "void *" + inline unsigned get_te16(const void *p) const noexcept { return bele->get16(p); } + inline unsigned get_te32(const void *p) const noexcept { return bele->get32(p); } + inline upx_uint64_t get_te64(const void *p) const noexcept { return bele->get64(p); } + inline void set_te16(void *p, unsigned v) noexcept { bele->set16(p, v); } + inline void set_te32(void *p, unsigned v) noexcept { bele->set32(p, v); } + inline void set_te64(void *p, upx_uint64_t v) noexcept { bele->set64(p, v); } +#endif protected: const N_BELE_RTP::AbstractPolicy *bele = nullptr; // target endianness diff --git a/src/pefile.cpp b/src/pefile.cpp index abd2749d..3a20b230 100644 --- a/src/pefile.cpp +++ b/src/pefile.cpp @@ -123,14 +123,22 @@ bool PeFile::testUnpackVersion(int version) const { // CHPE Compiled Hybrid PE: Microsoft internal only? // CHPEV2 Compiled Hybrid PE: ARM64EC, ARM64X /*static*/ int PeFile::checkMachine(unsigned cpu) { - // known but not supported + // unsupported + if (cpu == IMAGE_FILE_MACHINE_IA64) + throwCantPack("win64/ia64 is not supported"); + if (cpu == IMAGE_FILE_MACHINE_LOONGARCH64) + throwCantPack("win64/loong64 is not supported"); + if (cpu == IMAGE_FILE_MACHINE_RISCV64) + throwCantPack("win64/riscv64 is not supported"); + + // known but not (yet?) supported if (cpu == IMAGE_FILE_MACHINE_ARMNT) - throwCantPack("win32/arm32 is not supported"); // obsolete + throwCantPack("win32/armnt is not supported"); // obsolete if (cpu == IMAGE_FILE_MACHINE_ARM64) - throwCantPack("win64/arm64 is not supported"); + throwCantPack("win64/arm64 is not yet supported"); // FIXME: it seems that arm64ec actually uses MACHINE_AMD64 ??? if (cpu == IMAGE_FILE_MACHINE_ARM64EC) - throwCantPack("win64/arm64ec is not supported"); + throwCantPack("win64/arm64ec is not yet supported"); // supported if (cpu == IMAGE_FILE_MACHINE_AMD64) @@ -140,7 +148,7 @@ bool PeFile::testUnpackVersion(int version) const { if (cpu >= IMAGE_FILE_MACHINE_I386 && cpu <= 0x150) // what is this 0x150 ??? return UPX_F_W32PE_I386; - // other or unknown (alpha, mips, etc.) + // other or unknown (alpha, mips, powerpc, sh, etc.) throwCantPack("pefile: unsupported machine %#x", cpu); return 0; // pacify msvc } @@ -1339,7 +1347,7 @@ void PeFile::processTls2(Reloc *rel, const Interval *iv, unsigned newaddr, return; // add new relocation entries - if __acc_cte (tls_handler_offset > 0 && tls_handler_offset_reloc > 0) + if (tls_handler_offset > 0 && tls_handler_offset_reloc > 0) rel->add(tls_handler_offset + tls_handler_offset_reloc, reloc_type); unsigned ic; @@ -1388,10 +1396,10 @@ void PeFile::processTls2(Reloc *rel, const Interval *iv, unsigned newaddr, void PeFile::processLoadConf(Interval *iv) // pass 1 { - if (IDSIZE(PEDIR_LOADCONF) == 0) + if (IDSIZE(PEDIR_LOAD_CONFIG) == 0) return; - const unsigned lcaddr = IDADDR(PEDIR_LOADCONF); + const unsigned lcaddr = IDADDR(PEDIR_LOAD_CONFIG); const byte *const loadconf = ibuf.subref("bad loadconf %#x", lcaddr, 4); soloadconf = get_le32(loadconf); if (soloadconf == 0) @@ -2008,7 +2016,7 @@ void PeFile::checkHeaderValues(unsigned subsystem, unsigned mask, unsigned ih_en throwCantPack(buf); } // check CLR Runtime Header directory entry - if (IDSIZE(PEDIR_COMRT)) + if (IDSIZE(PEDIR_COM_DESCRIPTOR)) throwCantPack(".NET files are not yet supported"); if (isection == nullptr) @@ -2057,7 +2065,7 @@ unsigned PeFile::handleStripRelocs(upx_uint64_t ih_imagebase, upx_uint64_t defau if (!opt->force && ih_imagebase < default_imagebase) throwCantPack("--strip-relocs may not support this imagebase (try " "with --force)"); - return RELOCS_STRIPPED; + return IMAGE_FILE_RELOCS_STRIPPED; } else info("Base relocations stripping is disabled for this image"); return 0; @@ -2068,8 +2076,8 @@ static unsigned umax(unsigned a, unsigned b) { return (a >= b) ? a : b; } unsigned PeFile::readSections(unsigned objs, unsigned usize, unsigned ih_filealign, unsigned ih_datasize) { const unsigned xtrasize = UPX_MAX(ih_datasize, 65536u) + IDSIZE(PEDIR_IMPORT) + - IDSIZE(PEDIR_BOUNDIM) + IDSIZE(PEDIR_IAT) + IDSIZE(PEDIR_DELAYIMP) + - IDSIZE(PEDIR_RELOC); + IDSIZE(PEDIR_BOUND_IMPORT) + IDSIZE(PEDIR_IAT) + + IDSIZE(PEDIR_DELAY_IMPORT) + IDSIZE(PEDIR_RELOC); ibuf.alloc(usize + xtrasize); // BOUND IMPORT support. FIXME: is this ok? @@ -2086,15 +2094,15 @@ unsigned PeFile::readSections(unsigned objs, unsigned usize, unsigned ih_fileali overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size, ih_filealign); if (isection[ic].vsize == 0) isection[ic].vsize = isection[ic].size; - if ((isection[ic].flags & PEFL_BSS) || isection[ic].rawdataptr == 0 || - (isection[ic].flags & PEFL_INFO)) { + if ((isection[ic].flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) || + isection[ic].rawdataptr == 0 || (isection[ic].flags & IMAGE_SCN_LNK_INFO)) { // holes.add(isection[ic].vaddr,isection[ic].vsize); continue; } if (isection[ic].vaddr + isection[ic].size > usize) throwCantPack("section size problem"); - if (!isrtm && - ((isection[ic].flags & (PEFL_WRITE | PEFL_SHARED)) == (PEFL_WRITE | PEFL_SHARED))) + if (!isrtm && ((isection[ic].flags & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED)) == + (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED))) if (!opt->force) throwCantPack("writable shared sections not supported (try --force)"); if (jc && isection[ic].rawdataptr - jc > ih_filealign && !opt->force) @@ -2155,10 +2163,10 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, checkHeaderValues(ih.subsystem, subsystem_mask, ih.entry, ih.filealign); // remove certificate directory entry - if (IDSIZE(PEDIR_SEC)) - IDSIZE(PEDIR_SEC) = IDADDR(PEDIR_SEC) = 0; + if (IDSIZE(PEDIR_SECURITY)) + IDSIZE(PEDIR_SECURITY) = IDADDR(PEDIR_SECURITY) = 0; - if (ih.flags & RELOCS_STRIPPED) + if (ih.flags & IMAGE_FILE_RELOCS_STRIPPED) opt->win32_pe.strip_relocs = true; else ih.flags |= handleStripRelocs(ih.imagebase, default_imagebase, ih.dllflags); @@ -2187,8 +2195,8 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, if (ih.dllflags & IMAGE_DLLCHARACTERISTICS_GUARD_CF) { if (opt->force) { - const unsigned lcsize = IDSIZE(PEDIR_LOADCONF); - const unsigned lcaddr = IDADDR(PEDIR_LOADCONF); + const unsigned lcsize = IDSIZE(PEDIR_LOAD_CONFIG); + const unsigned lcaddr = IDADDR(PEDIR_LOAD_CONFIG); const unsigned gfpos = 14 * sizeof(ih.imagebase) + 6 * sizeof(LE32) + 4 * sizeof(LE16); if (lcaddr && lcsize >= gfpos + sizeof(LE32)) // GuardFlags: Set IMAGE_GUARD_SECURITY_COOKIE_UNUSED @@ -2218,7 +2226,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, bool allow_filter = true; if (/*FIXME ih.codebase == ih.database ||*/ ih.codebase + ih.codesize > ih.imagesize || - (isection[virta2objnum(ih.codebase, isection, objs)].flags & PEFL_CODE) == 0) + (isection[virta2objnum(ih.codebase, isection, objs)].flags & IMAGE_SCN_CNT_CODE) == 0) allow_filter = false; const unsigned oam1 = ih.objectalign - 1; @@ -2364,8 +2372,8 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, ODSIZE(PEDIR_DEBUG) = 0; ODADDR(PEDIR_IAT) = 0; ODSIZE(PEDIR_IAT) = 0; - ODADDR(PEDIR_BOUNDIM) = 0; - ODSIZE(PEDIR_BOUNDIM) = 0; + ODADDR(PEDIR_BOUND_IMPORT) = 0; + ODSIZE(PEDIR_BOUND_IMPORT) = 0; // tls & loadconf are put into section 1 ic = s1addr + s1size - aligned_sotls - soloadconf; @@ -2379,8 +2387,8 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, ic += aligned_sotls; processLoadConf(&rel, &loadconfiv, ic); - ODADDR(PEDIR_LOADCONF) = soloadconf ? ic : 0; - ODSIZE(PEDIR_LOADCONF) = soloadconf; + ODADDR(PEDIR_LOAD_CONFIG) = soloadconf ? ic : 0; + ODSIZE(PEDIR_LOAD_CONFIG) = soloadconf; ic += soloadconf; const bool rel_at_sections_start = last_section_rsrc_only; @@ -2467,9 +2475,11 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, } osection[2].rawdataptr = osection[1].rawdataptr + osection[1].size; - osection[0].flags = (unsigned) (PEFL_BSS | PEFL_EXEC | PEFL_WRITE | PEFL_READ); - osection[1].flags = (unsigned) (PEFL_DATA | PEFL_EXEC | PEFL_WRITE | PEFL_READ); - osection[2].flags = (unsigned) (PEFL_DATA | PEFL_WRITE | PEFL_READ); + osection[0].flags = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE; + osection[1].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | + IMAGE_SCN_MEM_EXECUTE; + osection[2].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; if (last_section_rsrc_only) { strcpy(osection[3].name, ".rsrc"); @@ -2477,8 +2487,8 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, osection[3].size = (soresources + fam1) & ~fam1; osection[3].vsize = osection[3].size; osection[3].rawdataptr = osection[2].rawdataptr + osection[2].size; - osection[2].flags = (unsigned) (PEFL_DATA | PEFL_READ); - osection[3].flags = (unsigned) (PEFL_DATA | PEFL_READ); + osection[2].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; + osection[3].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; oh.imagesize = (osection[3].vaddr + osection[3].vsize + oam1) & ~oam1; if (soresources == 0) { oh.objects = 3; @@ -2496,10 +2506,8 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, throwCantPack("object alignment too small"); if (opt->win32_pe.strip_relocs) - oh.flags |= RELOCS_STRIPPED; + oh.flags |= IMAGE_FILE_RELOCS_STRIPPED; - // for (ic = 0; ic < oh.filealign; ic += 4) - // set_le32(ibuf + ic,get_le32("UPX ")); ibuf.clear(0, oh.filealign); info("Image size change: %u -> %u KiB", ih.imagesize / 1024, oh.imagesize / 1024); @@ -2580,7 +2588,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, void PeFile::rebuildRelocs(SPAN_S(byte) & extra_info, unsigned bits, unsigned flags, upx_uint64_t imagebase) { assert(bits == 32 || bits == 64); - if (!ODADDR(PEDIR_RELOC) || !ODSIZE(PEDIR_RELOC) || (flags & RELOCS_STRIPPED)) + if (!ODADDR(PEDIR_RELOC) || !ODSIZE(PEDIR_RELOC) || (flags & IMAGE_FILE_RELOCS_STRIPPED)) return; if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this @@ -2850,8 +2858,8 @@ void PeFile::unpack0(OutputFile *fo, const ht &ih, ht &oh, ord_mask_t ord_mask, } // FIXME: ih.flags is checked here because of a bug in UPX 0.92 - if (ih.flags & RELOCS_STRIPPED) { - oh.flags |= RELOCS_STRIPPED; + if (ih.flags & IMAGE_FILE_RELOCS_STRIPPED) { + oh.flags |= IMAGE_FILE_RELOCS_STRIPPED; ODADDR(PEDIR_RELOC) = 0; ODSIZE(PEDIR_RELOC) = 0; } @@ -2880,8 +2888,8 @@ void PeFile::unpack0(OutputFile *fo, const ht &ih, ht &oh, ord_mask_t ord_mask, ODSIZE(PEDIR_DEBUG) = 0; ODADDR(PEDIR_IAT) = 0; ODSIZE(PEDIR_IAT) = 0; - ODADDR(PEDIR_BOUNDIM) = 0; - ODSIZE(PEDIR_BOUNDIM) = 0; + ODADDR(PEDIR_BOUND_IMPORT) = 0; + ODSIZE(PEDIR_BOUND_IMPORT) = 0; setOhHeaderSize(osection); oh.chksum = 0; @@ -2996,7 +3004,7 @@ void PeFile32::readPeHeader() { ((1u << IMAGE_SUBSYSTEM_EFI_APPLICATION) | (1u << IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) | (1u << IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) | (1u << IMAGE_SUBSYSTEM_EFI_ROM))) != 0; - isdll = !isefi && (ih.flags & DLL_FLAG) != 0; + isdll = !isefi && (ih.flags & IMAGE_FILE_DLL) != 0; use_dep_hack &= !isefi; use_clear_dirty_stack &= !isefi; } @@ -3049,7 +3057,7 @@ void PeFile64::readPeHeader() { ((1u << IMAGE_SUBSYSTEM_EFI_APPLICATION) | (1u << IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) | (1u << IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) | (1u << IMAGE_SUBSYSTEM_EFI_ROM))) != 0; - isdll = !isefi && (ih.flags & DLL_FLAG) != 0; + isdll = !isefi && (ih.flags & IMAGE_FILE_DLL) != 0; use_dep_hack &= !isefi; use_clear_dirty_stack &= !isefi; } diff --git a/src/pefile.h b/src/pefile.h index 06487cf3..5a7e81fc 100644 --- a/src/pefile.h +++ b/src/pefile.h @@ -215,11 +215,17 @@ protected: IMAGE_FILE_MACHINE_UNKNOWN = 0, IMAGE_FILE_MACHINE_AMD64 = 0x8664, // win64/pe (amd64) IMAGE_FILE_MACHINE_ARM = 0x01c0, // wince/arm (Windows CE) + IMAGE_FILE_MACHINE_ARMNT = 0x01c4, // win32/arm IMAGE_FILE_MACHINE_ARM64 = 0xaa64, // win64/arm64 IMAGE_FILE_MACHINE_ARM64EC = 0xa641, // win64/arm64ec - IMAGE_FILE_MACHINE_ARMNT = 0x01c4, // win32/arm IMAGE_FILE_MACHINE_I386 = 0x014c, // win32/pe (i386) - IMAGE_FILE_MACHINE_THUMB = 0x01c2, // wince/arm (Windows CE) + IMAGE_FILE_MACHINE_IA64 = 0x200, + IMAGE_FILE_MACHINE_LOONGARCH32 = 0x6232, + IMAGE_FILE_MACHINE_LOONGARCH64 = 0x6264, + IMAGE_FILE_MACHINE_RISCV32 = 0x5032, + IMAGE_FILE_MACHINE_RISCV64 = 0x5064, + IMAGE_FILE_MACHINE_RISCV128 = 0x5128, + IMAGE_FILE_MACHINE_THUMB = 0x01c2, // wince/arm (Windows CE) }; enum { @@ -227,48 +233,74 @@ protected: PEDIR_IMPORT = 1, PEDIR_RESOURCE = 2, PEDIR_EXCEPTION = 3, // Exception table - PEDIR_SEC = 4, // Certificate table (file pointer) - PEDIR_RELOC = 5, + PEDIR_SECURITY = 4, // Certificate table (file pointer) + PEDIR_BASERELOC = 5, PEDIR_DEBUG = 6, - PEDIR_COPYRIGHT = 7, // Architecture-specific data - PEDIR_GLOBALPTR = 8, // Global pointer + PEDIR_ARCHITECTURE = 7, // Architecture-specific data + PEDIR_GLOBALPTR = 8, // Global pointer PEDIR_TLS = 9, - PEDIR_LOADCONF = 10, // Load Config Table - PEDIR_BOUNDIM = 11, + PEDIR_LOAD_CONFIG = 10, // Load Config Table + PEDIR_BOUND_IMPORT = 11, PEDIR_IAT = 12, - PEDIR_DELAYIMP = 13, // Delay Import Descriptor - PEDIR_COMRT = 14, // Com+ Runtime Header + PEDIR_DELAY_IMPORT = 13, // Delay Import Descriptor + PEDIR_COM_DESCRIPTOR = 14, // Com+ Runtime Header + PEDIR_RELOC = PEDIR_BASERELOC, + }; + + // section flags + enum : unsigned { + IMAGE_SCN_CNT_CODE = 0x00000020, + IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, + IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080, + IMAGE_SCN_LNK_OTHER = 0x00000100, + IMAGE_SCN_LNK_INFO = 0x00000200, + IMAGE_SCN_LNK_REMOVE = 0x00000800, + IMAGE_SCN_LNK_COMDAT = 0x00001000, + IMAGE_SCN_GPREL = 0x00008000, + IMAGE_SCN_MEM_PURGEABLE = 0x00020000, + IMAGE_SCN_MEM_16BIT = 0x00020000, + IMAGE_SCN_MEM_LOCKED = 0x00040000, + IMAGE_SCN_MEM_PRELOAD = 0x00080000, + IMAGE_SCN_ALIGN_1BYTES = 0x00100000, + IMAGE_SCN_ALIGN_2BYTES = 0x00200000, + IMAGE_SCN_ALIGN_4BYTES = 0x00300000, + IMAGE_SCN_ALIGN_8BYTES = 0x00400000, + IMAGE_SCN_ALIGN_16BYTES = 0x00500000, + IMAGE_SCN_ALIGN_32BYTES = 0x00600000, + IMAGE_SCN_ALIGN_64BYTES = 0x00700000, + IMAGE_SCN_ALIGN_128BYTES = 0x00800000, + IMAGE_SCN_ALIGN_256BYTES = 0x00900000, + IMAGE_SCN_ALIGN_512BYTES = 0x00A00000, + IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000, + IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000, + IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000, + IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000, + IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000, + IMAGE_SCN_MEM_DISCARDABLE = 0x02000000, + IMAGE_SCN_MEM_NOT_CACHED = 0x04000000, + IMAGE_SCN_MEM_NOT_PAGED = 0x08000000, + IMAGE_SCN_MEM_SHARED = 0x10000000, + IMAGE_SCN_MEM_EXECUTE = 0x20000000, + IMAGE_SCN_MEM_READ = 0x40000000, + IMAGE_SCN_MEM_WRITE = 0x80000000, }; enum { - PEFL_CODE = 0x20, - PEFL_DATA = 0x40, - PEFL_BSS = 0x80, - PEFL_INFO = 0x200, - PEFL_EXTRELS = 0x01000000, // extended relocations - PEFL_DISCARD = 0x02000000, - PEFL_NOCACHE = 0x04000000, - PEFL_NOPAGE = 0x08000000, - PEFL_SHARED = 0x10000000, - PEFL_EXEC = 0x20000000, - PEFL_READ = 0x40000000, - PEFL_WRITE = 0x80000000, - }; - - enum { - RELOCS_STRIPPED = 0x0001, - EXECUTABLE = 0x0002, - LNUM_STRIPPED = 0x0004, - LSYMS_STRIPPED = 0x0008, - AGGRESSIVE_TRIM = 0x0010, - TWO_GIGS_AWARE = 0x0020, - FLITTLE_ENDIAN = 0x0080, - BITS_32_MACHINE = 0x0100, - DEBUG_STRIPPED = 0x0200, - REMOVABLE_SWAP = 0x0400, - SYSTEM_PROGRAM = 0x1000, - DLL_FLAG = 0x2000, - FBIG_ENDIAN = 0x8000, + IMAGE_FILE_RELOCS_STRIPPED = 0x0001, + IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002, + IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004, + IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008, + IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010, + IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020, + IMAGE_FILE_BYTES_REVERSED_LO = 0x0080, + IMAGE_FILE_32BIT_MACHINE = 0x0100, + IMAGE_FILE_DEBUG_STRIPPED = 0x0200, + IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400, + IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800, + IMAGE_FILE_SYSTEM = 0x1000, + IMAGE_FILE_DLL = 0x2000, + IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000, + IMAGE_FILE_BYTES_REVERSE_HI = 0x8000, }; enum { @@ -288,10 +320,11 @@ protected: enum { IMAGE_SUBSYSTEM_UNKNOWN = 0, IMAGE_SUBSYSTEM_NATIVE = 1, - IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Graphical - IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Character-mode + IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Graphical User Interface + IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Character User Interface IMAGE_SUBSYSTEM_WINDOWS_OS2_CUI = 5, IMAGE_SUBSYSTEM_WINDOWS_POSIX_CUI = 7, + IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, @@ -489,7 +522,7 @@ protected: LE16 objects; // NumberOfSections byte __[12]; // timestamp + reserved LE16 opthdrsize; // SizeOfOptionalHeader - LE16 flags; // Characteristics + LE16 flags; // IMAGE_FILE_xxx Characteristics // 0x18 IMAGE_OPTIONAL_HEADER32 LE16 coffmagic; // NEW: Stefan Widmann byte ___[2]; // linkerversion @@ -550,7 +583,7 @@ protected: LE16 objects; // NumberOfSections byte __[12]; // timestamp + reserved LE16 opthdrsize; // SizeOfOptionalHeader - LE16 flags; // Characteristics + LE16 flags; // IMAGE_FILE_xxx Characteristics // 0x18 IMAGE_OPTIONAL_HEADER64 LE16 coffmagic; // NEW: Stefan Widmann byte ___[2]; // linkerversion diff --git a/src/util/membuffer.cpp b/src/util/membuffer.cpp index c198377e..933d0616 100644 --- a/src/util/membuffer.cpp +++ b/src/util/membuffer.cpp @@ -69,7 +69,7 @@ static forceinline constexpr bool use_simple_mcheck() { return true; } // **************************************************************************/ -MemBuffer::MemBuffer(upx_uint64_t bytes) { +MemBuffer::MemBuffer(upx_uint64_t bytes) : MemBufferBase() { alloc(bytes); debug_set(debug.last_return_address_alloc, upx_return_address()); } @@ -198,7 +198,7 @@ void MemBuffer::alloc(upx_uint64_t bytes) { // assert(bytes > 0); debug_set(debug.last_return_address_alloc, upx_return_address()); - size_t malloc_bytes = mem_size(1, bytes); + size_t malloc_bytes = mem_size(1, bytes); // check size if (use_simple_mcheck()) malloc_bytes += 32; byte *p = (byte *) ::malloc(malloc_bytes); @@ -216,7 +216,7 @@ void MemBuffer::alloc(upx_uint64_t bytes) { } ptr = (pointer) (void *) p; #if DEBUG - memset(ptr, 0xff, size_in_bytes); + memset(ptr, 0xfb, size_in_bytes); (void) VALGRIND_MAKE_MEM_UNDEFINED(ptr, size_in_bytes); #endif stats.global_alloc_counter += 1; diff --git a/src/util/membuffer.h b/src/util/membuffer.h index fd6c48d3..da2e6f29 100644 --- a/src/util/membuffer.h +++ b/src/util/membuffer.h @@ -46,7 +46,7 @@ protected: size_type size_in_bytes; public: - MemBufferBase() noexcept : ptr(nullptr), size_in_bytes(0) {} + inline MemBufferBase() noexcept : ptr(nullptr), size_in_bytes(0) {} inline ~MemBufferBase() noexcept {} // NOTE: implicit conversion to underlying pointer @@ -83,7 +83,7 @@ public: // raw access class MemBuffer final : public MemBufferBase { public: - MemBuffer() : MemBufferBase() {} + inline MemBuffer() noexcept : MemBufferBase() {} explicit MemBuffer(upx_uint64_t bytes); ~MemBuffer() noexcept; diff --git a/src/util/util.cpp b/src/util/util.cpp index 491fc12a..cd21c0ce 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -118,7 +118,7 @@ int ptr_diff_bytes(const void *a, const void *b) { if very_unlikely (!mem_size_valid_bytes(d)) throwCantPack("ptr_diff_bytes-1; take care"); } else { - if very_unlikely (!mem_size_valid_bytes(-d)) + if very_unlikely (!mem_size_valid_bytes(0ll - d)) throwCantPack("ptr_diff_bytes-2; take care"); } return ACC_ICONV(int, d); @@ -291,10 +291,10 @@ void upx_memswap(void *a, void *b, size_t n) { void upx_stable_sort(void *array, size_t n, size_t element_size, int (*compare)(const void *, const void *)) { for (size_t i = 1; i < n; i++) { - char *a = (char *) array + element_size * i; // a = &array[i] - if (i != 0 && compare(a - element_size, a) > 0) { - upx_memswap(a - element_size, a, element_size); // swap elements a[-1] <=> a[0] - i -= 2; + char *a = (char *) array + element_size * i; // a := &array[i] + if (i != 0 && compare(a - element_size, a) > 0) { // if a[-1] > a[0] then + upx_memswap(a - element_size, a, element_size); // swap elements a[-1] <=> a[0] + i -= 2; // and decrease i } } } @@ -312,8 +312,11 @@ TEST_CASE("upx_stable_sort") { CHECK((a[0] == 0 && a[1] == 1)); } { - unsigned a[] = {2, 1, 0}; - upx_stable_sort(a, 3, sizeof(*a), ne32_compare); + LE64 a[3]; + a[0] = 2; + a[1] = 1; + a[2] = 0; + upx_stable_sort(a, 3, sizeof(*a), le64_compare); CHECK((a[0] == 0 && a[1] == 1 && a[2] == 2)); } #if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations diff --git a/src/util/util.h b/src/util/util.h index ef9a484e..e1511e6b 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -81,14 +81,14 @@ T *NewArray(upx_uint64_t n) { size_t bytes = mem_size(sizeof(T), n); // assert size T *array = new T[size_t(n)]; if (array) { - memset(array, 0xff, bytes); + memset(array, 0xfb, bytes); (void) VALGRIND_MAKE_MEM_UNDEFINED(array, bytes); } return array; } #define New(type, n) (NewArray(n)) #else -#define New(type, n) new type[mem_size_get_n(sizeof(type), n)] +#define New(type, n) new type[mem_size_get_n(sizeof(type), (n))] #endif /*************************************************************************