all: yet more cleanups

Changes include:
  - use standard names for PE constants
  - add some more "noexcept"
  - improve upx_is_integral type-trait
  - introduce is_same_all and is_same_any type-traits
  - prepare TE-size checks in packer.h
  - CI updates
This commit is contained in:
Markus F.X.J. Oberhumer 2023-04-18 17:02:13 +02:00
parent 15484aa296
commit 320e5b850f
33 changed files with 493 additions and 362 deletions

View File

@ -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'

View File

@ -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 }}

View File

@ -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.'

View File

@ -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 }}

1
.gitignore vendored
View File

@ -22,6 +22,7 @@ tmp*
*.py[cdo]
*.so
*.swp
*.tmp
*.ttp
doc/*.man

View File

@ -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 $<$<CONFIG:Debug>:-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})

View File

@ -49,7 +49,9 @@ release: build/release
.SECONDEXPANSION:
.SUFFIXES:
#
# END of Makefile; extra stuff follows
#
#***********************************************************************
# extra builds: some pre-defined build configurations

View File

@ -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/ \

View File

@ -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:

View File

@ -129,50 +129,50 @@ 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_le26(const void *p) noexcept { return get_le32(p) & 0x03ffffff; }
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
@ -198,42 +198,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);
}
@ -249,11 +249,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;
}
@ -294,16 +296,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;
}
@ -344,16 +347,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;
}
@ -394,16 +398,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;
}
@ -444,16 +449,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;
}
@ -494,16 +500,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;
}
@ -544,9 +551,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); }
};
/*************************************************************************
@ -634,39 +640,6 @@ inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN(unsigned(a),
// misc support
**************************************************************************/
template <>
struct upx_is_integral<BE16> : public std::true_type {};
template <>
struct upx_is_integral<BE32> : public std::true_type {};
template <>
struct upx_is_integral<BE64> : public std::true_type {};
template <>
struct upx_is_integral<LE16> : public std::true_type {};
template <>
struct upx_is_integral<LE32> : public std::true_type {};
template <>
struct upx_is_integral<LE64> : 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;
@ -690,6 +663,44 @@ typedef LE64 NE64;
#define ne64_compare_signed le64_compare_signed
#endif
// <type_traits> upx_is_integral
#define TT_IS_INTEGRAL(T) \
template <> \
struct upx_is_integral<T> : public std::true_type {}; \
template <> \
struct upx_is_integral<const T> : public std::true_type {}; \
template <> \
struct upx_is_integral<volatile T> : public std::true_type {}; \
template <> \
struct upx_is_integral<const volatile T> : 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.
//

View File

@ -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"

View File

@ -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<short, upx_int16_t>::value))
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned short, upx_uint16_t>::value))
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<int, upx_int32_t>::value))
@ -90,10 +91,25 @@ ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned, upx_uint32_t>::value))
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<long long, upx_int64_t>::value))
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned long long, upx_uint64_t>::value))
ACC_COMPILE_TIME_ASSERT_HEADER((is_same_all_v<int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((is_same_all_v<int, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((is_same_all_v<int, int, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_all_v<int, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_all_v<int, char, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_all_v<int, int, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_any_v<int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((is_same_any_v<int, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((is_same_any_v<int, char, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((is_same_any_v<int, int, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_any_v<int, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_any_v<int, char, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!is_same_any_v<int, char, long>) )
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 <class T>
struct CheckIntegral {
template <class U>
static void checkU(void) {
#if __cplusplus < 202002L
COMPILE_TIME_ASSERT(std::is_pod<U>::value) // deprecated in C++20
#endif
COMPILE_TIME_ASSERT(std::is_standard_layout<U>::value)
COMPILE_TIME_ASSERT(std::is_trivial<U>::value)
// extra checks, these are probably implied by std::is_trivial
COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible<U>::value)
COMPILE_TIME_ASSERT(std::is_trivially_copyable<U>::value)
COMPILE_TIME_ASSERT(std::is_trivially_default_constructible<U>::value)
// UPX
COMPILE_TIME_ASSERT(upx_is_integral<U>::value)
COMPILE_TIME_ASSERT(upx_is_integral_v<U>)
}
static void check(void) {
checkU<T>();
checkU<typename std::add_const<T>::type>();
#if !defined(__GNUC__)
// TODO later: "volatile" seems to be broken with some older g++/libstdc++ versions??
checkU<typename std::add_volatile<T>::type>();
checkU<typename std::add_cv<T>::type>();
#endif
}
};
template <class T>
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 <class T>
struct TestBELE {
static noinline bool test(void) {
// POD checks
{
COMPILE_TIME_ASSERT(std::is_standard_layout<T>::value)
COMPILE_TIME_ASSERT(std::is_trivial<T>::value)
// extra checks, these are probably implied by std::is_trivial
COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible<T>::value)
COMPILE_TIME_ASSERT(std::is_trivially_copyable<T>::value)
COMPILE_TIME_ASSERT(std::is_trivially_default_constructible<T>::value)
// UPX
COMPILE_TIME_ASSERT(upx_is_integral<T>::value)
COMPILE_TIME_ASSERT(upx_is_integral_v<T>)
}
// 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<T>::check();
CheckAlignment<T>::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<char>::check();
CheckIntegral<signed char>::check();
CheckIntegral<unsigned char>::check();
CheckIntegral<short>::check();
CheckIntegral<int>::check();
CheckIntegral<long>::check();
CheckIntegral<long long>::check();
CheckIntegral<ptrdiff_t>::check();
CheckIntegral<size_t>::check();
CheckIntegral<upx_off_t>::check();
CheckIntegral<upx_uintptr_t>::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)

View File

@ -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));

View File

@ -96,7 +96,17 @@ struct upx_std_is_bounded_array<T[N]> : public std::true_type {};
template <class T>
inline constexpr bool upx_std_is_bounded_array_v = upx_std_is_bounded_array<T>::value;
// see bele.h
// <type_traits> is_same_all and is_same_any: std::is_same for multiple types
template <class T, class... Ts>
struct is_same_all : public std::conjunction<std::is_same<T, Ts>...> {};
template <class T, class... Ts>
inline constexpr bool is_same_all_v = is_same_all<T, Ts...>::value;
template <class T, class... Ts>
struct is_same_any : public std::disjunction<std::is_same<T, Ts>...> {};
template <class T, class... Ts>
inline constexpr bool is_same_any_v = is_same_any<T, Ts...>::value;
// upx_is_integral is overloaded for BE16 & friends; see bele.h
template <class T>
struct upx_is_integral : public std::is_integral<T> {};
template <class T>
@ -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 <class T, T default_value_, T min_value_, T max_value_>
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"

View File

@ -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 <mutex>
#endif
// C++ submodule headers
// UPX vendor git submodule headers
#include <doctest/doctest/parts/doctest_fwd.h>
#if WITH_BOOST_PFR
#include <sstream>

View File

@ -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();
}
}

View File

@ -26,12 +26,11 @@
*/
#include "headers.h"
#include <typeinfo>
#include <typeinfo> // 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);

View File

@ -25,11 +25,7 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
#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: */

View File

@ -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,15 +70,16 @@
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_AARCH64 = 183,
EM_X86_64 = 62, // amd64
EM_AARCH64 = 183, // arm64
EM_RISCV = 243, // risc-v
EM_LOONGARCH = 258,
};
enum { // e_version
EV_CURRENT = 1,
@ -86,7 +90,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 */
@ -125,7 +129,7 @@
SHT_FINI_ARRAY = 15, /* Array of destructors */
SHT_PREINIT_ARRAY = 16, /* Array of pre-constructors */
SHT_GROUP = 17, /* Section group */
SHT_SYMTAB_SHNDX = 18, /* Extended section indeces */
SHT_SYMTAB_SHNDX = 18, /* Extended section indices */
SHT_GNU_LIBLIST = 0x6ffffff7, /* Prelink library list */
SHT_GNU_HASH = 0x6ffffff6, /* GNU-style hash table. */

View File

@ -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()

View File

@ -30,6 +30,7 @@
*/
#pragma once
#ifndef __UPX_P_UNIX_H
#define __UPX_P_UNIX_H 1

View File

@ -26,6 +26,7 @@
*/
#pragma once
#ifndef __UPX_P_VMLINX_H
#define __UPX_P_VMLINX_H 1

View File

@ -26,6 +26,7 @@
*/
#pragma once
#ifndef __UPX_P_VMLINZ_H
#define __UPX_P_VMLINZ_H 1

View File

@ -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;

View File

@ -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;

View File

@ -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?

View File

@ -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 0
// try to detect TE16 vs TE32 vs TE64 size mismatches; note that "byte" is explicitly allowed
template <class T>
static inline constexpr bool is_te16_type = is_same_any_v<T, byte, upx_uint16_t, BE16, LE16>;
template <class T>
static inline constexpr bool is_te32_type = is_same_any_v<T, byte, unsigned, BE32, LE32>;
template <class T>
static inline constexpr bool is_te64_type = is_same_any_v<T, byte, upx_uint64_t, BE64, LE64>;
template <class T, class = std::enable_if_t<is_te16_type<T>, T> >
inline unsigned get_te16(const T *p) const noexcept {
return bele->get16(p);
}
template <class T, class = std::enable_if_t<is_te32_type<T>, T> >
inline unsigned get_te32(const T *p) const noexcept {
return bele->get32(p);
}
template <class T, class = std::enable_if_t<is_te64_type<T>, T> >
inline upx_uint64_t get_te64(const T *p) const noexcept {
return bele->get64(p);
}
template <class T, class = std::enable_if_t<is_te16_type<T>, T> >
inline void set_te16(T *p, unsigned v) noexcept {
bele->set16(p, v);
}
template <class T, class = std::enable_if_t<is_te32_type<T>, T> >
inline void set_te32(T *p, unsigned v) noexcept {
bele->set32(p, v);
}
template <class T, class = std::enable_if_t<is_te64_type<T>, 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

View File

@ -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;
}

View File

@ -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

View File

@ -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<byte>() {
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;

View File

@ -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<byte> {
public:
MemBuffer() : MemBufferBase<byte>() {}
inline MemBuffer() noexcept : MemBufferBase<byte>() {}
explicit MemBuffer(upx_uint64_t bytes);
~MemBuffer() noexcept;

View File

@ -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

View File

@ -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<type>(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
/*************************************************************************