mirror of https://github.com/upx/upx.git
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:
parent
15484aa296
commit
320e5b850f
|
@ -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'
|
||||
|
|
|
@ -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 }}
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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 }}
|
||||
|
|
|
@ -22,6 +22,7 @@ tmp*
|
|||
*.py[cdo]
|
||||
*.so
|
||||
*.swp
|
||||
*.tmp
|
||||
*.ttp
|
||||
|
||||
doc/*.man
|
||||
|
|
|
@ -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})
|
||||
|
|
2
Makefile
2
Makefile
|
@ -49,7 +49,9 @@ release: build/release
|
|||
.SECONDEXPANSION:
|
||||
.SUFFIXES:
|
||||
|
||||
#
|
||||
# END of Makefile; extra stuff follows
|
||||
#
|
||||
|
||||
#***********************************************************************
|
||||
# extra builds: some pre-defined build configurations
|
||||
|
|
|
@ -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/ \
|
||||
|
|
|
@ -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:
|
||||
|
|
189
src/bele.h
189
src/bele.h
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
20
src/conf.h
20
src/conf.h
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
21
src/main.cpp
21
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();
|
||||
}
|
||||
}
|
||||
|
|
13
src/msg.cpp
13
src/msg.cpp
|
@ -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);
|
||||
|
|
11
src/p_elf.h
11
src/p_elf.h
|
@ -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: */
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
10
src/p_mach.h
10
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()
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
#ifndef __UPX_P_UNIX_H
|
||||
#define __UPX_P_UNIX_H 1
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
#ifndef __UPX_P_VMLINX_H
|
||||
#define __UPX_P_VMLINX_H 1
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
#ifndef __UPX_P_VMLINZ_H
|
||||
#define __UPX_P_VMLINZ_H 1
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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?
|
||||
|
|
49
src/packer.h
49
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 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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
117
src/pefile.h
117
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/*************************************************************************
|
||||
|
|
Loading…
Reference in New Issue