mirror of https://github.com/upx/upx.git
Merge branch 'devel4' of https://github.com/upx/upx into devel4
This commit is contained in:
commit
7f5b64c91a
|
@ -4,5 +4,6 @@ updates:
|
||||||
- package-ecosystem: 'github-actions'
|
- package-ecosystem: 'github-actions'
|
||||||
directory: '/'
|
directory: '/'
|
||||||
schedule:
|
schedule:
|
||||||
# Check for updates to GitHub Actions every weekday
|
# Check for updates to GitHub Actions every Wednesday
|
||||||
interval: 'daily'
|
interval: 'weekly'
|
||||||
|
day: 'wednesday'
|
||||||
|
|
|
@ -205,7 +205,6 @@ jobs:
|
||||||
# windows-2019 used to work but got broken with the 20220821.1 runner-image
|
# 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
|
# update; we cannot download that image for inspection, and debugging the
|
||||||
# remote image is painful, so disable for now
|
# 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-2019-amd64, os: windows-2019 }
|
||||||
- { name: windows-2022-amd64, os: windows-2022 }
|
- { name: windows-2022-amd64, os: windows-2022 }
|
||||||
steps:
|
steps:
|
||||||
|
@ -215,7 +214,7 @@ jobs:
|
||||||
- name: 'Check out test suite'
|
- name: 'Check out test suite'
|
||||||
run: 'git clone --depth=1 https://github.com/upx/upx-testsuite ../deps/upx-testsuite'
|
run: 'git clone --depth=1 https://github.com/upx/upx-testsuite ../deps/upx-testsuite'
|
||||||
- name: 'Inspect runner-image settings'
|
- 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 }}
|
if: ${{ false }}
|
||||||
run: |
|
run: |
|
||||||
Get-Command bash; Get-Command cmake; Get-Command make
|
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-macos.13-none }
|
||||||
- { zig_target: x86_64-windows-gnu }
|
- { zig_target: x86_64-windows-gnu }
|
||||||
env:
|
env:
|
||||||
# 2023-03-18
|
# 2023-04-17
|
||||||
ZIG_DIST_VERSION: 0.11.0-dev.2157+f56f3c582
|
ZIG_DIST_VERSION: 0.11.0-dev.2624+bc804eb84
|
||||||
# for zig-cc wrapper scripts (see below):
|
# for zig-cc wrapper scripts (see below):
|
||||||
ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING
|
ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING
|
||||||
ZIG_FLAGS: ${{ matrix.zig_flags }}
|
ZIG_FLAGS: ${{ matrix.zig_flags }}
|
||||||
|
|
|
@ -23,11 +23,11 @@ jobs:
|
||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v7
|
- uses: actions/stale@v8
|
||||||
with:
|
with:
|
||||||
operations-per-run: 300
|
operations-per-run: 300
|
||||||
exempt-all-milestones: true
|
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-stale: 60
|
||||||
days-before-close: 30
|
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.'
|
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:
|
job-alpine-cmake:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
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) }}
|
name: ${{ format('container {0}', matrix.container) }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: ${{ matrix.container }}
|
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: '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: 'Strip release binaries', run: 'strip -p --strip-unneeded upx/build/*/*/release/upx' }
|
||||||
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
|
- 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
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ env.artifact_name }}
|
name: ${{ env.artifact_name }}
|
||||||
|
|
|
@ -22,6 +22,7 @@ tmp*
|
||||||
*.py[cdo]
|
*.py[cdo]
|
||||||
*.so
|
*.so
|
||||||
*.swp
|
*.swp
|
||||||
|
*.tmp
|
||||||
*.ttp
|
*.ttp
|
||||||
|
|
||||||
doc/*.man
|
doc/*.man
|
||||||
|
|
|
@ -187,7 +187,7 @@ endif()
|
||||||
# compile a target with -O2 even in Debug build
|
# compile a target with -O2 even in Debug build
|
||||||
function(upx_compile_target_debug_with_O2 t)
|
function(upx_compile_target_debug_with_O2 t)
|
||||||
if(MSVC)
|
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()
|
else()
|
||||||
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-O2>)
|
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-O2>)
|
||||||
endif()
|
endif()
|
||||||
|
@ -196,7 +196,7 @@ endfunction()
|
||||||
function(upx_sanitize_target t)
|
function(upx_sanitize_target t)
|
||||||
if(NOT UPX_CONFIG_DISABLE_SANITIZE)
|
if(NOT UPX_CONFIG_DISABLE_SANITIZE)
|
||||||
if(MSVC)
|
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)
|
elseif(CMAKE_C_PLATFORM_ID MATCHES "^MinGW" OR MINGW OR CYGWIN)
|
||||||
# avoid link errors with current MinGW-w64 versions
|
# avoid link errors with current MinGW-w64 versions
|
||||||
# see https://www.mingw-w64.org/contribute/#sanitizers-asan-tsan-usan
|
# see https://www.mingw-w64.org/contribute/#sanitizers-asan-tsan-usan
|
||||||
|
@ -242,7 +242,7 @@ if(MSVC)
|
||||||
else()
|
else()
|
||||||
target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
|
target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif() # UPX_CONFIG_DISABLE_ZSTD
|
||||||
|
|
||||||
set(t upx)
|
set(t upx)
|
||||||
target_include_directories(${t} PRIVATE vendor)
|
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-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-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-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-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-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})
|
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:
|
.SECONDEXPANSION:
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
|
||||||
|
#
|
||||||
# END of Makefile; extra stuff follows
|
# END of Makefile; extra stuff follows
|
||||||
|
#
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# extra builds: some pre-defined build configurations
|
# 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
|
# manually install compat libs from Ubuntu 16.04; REQUIRED
|
||||||
RUN cd /root \
|
RUN cd /root \
|
||||||
&& aria2c --checksum=sha-256=de22baf3dd851a10e16fbf66a243e70149ca46e06b2939fdc79429196cefc090 \
|
&& 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 \
|
&& mkdir packages \
|
||||||
&& for f in ./*.deb; do dpkg -x $f ./packages; done \
|
&& 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/ \
|
&& 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/.),)
|
ifneq ($(wildcard $(top_srcdir)/.git/.),)
|
||||||
CHECK_WHITESPACE = $(top_srcdir)/misc/scripts/check_whitespace_git.sh $(top_srcdir)
|
CHECK_WHITESPACE = $(top_srcdir)/misc/scripts/check_whitespace_git.sh $(top_srcdir)
|
||||||
endif
|
endif
|
||||||
check-whitespace : PHONY ; $(CHECK_WHITESPACE)
|
check-whitespace: PHONY; $(CHECK_WHITESPACE)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# vim:set ts=8 sw=8 noet:
|
# vim:set ts=8 sw=8 noet:
|
||||||
|
|
197
src/bele.h
197
src/bele.h
|
@ -129,62 +129,62 @@ static forceinline constexpr upx_uint64_t no_bswap64(upx_uint64_t v) noexcept {
|
||||||
// get/set 16/32/64
|
// get/set 16/32/64
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
inline unsigned get_be16(const void *p) { return ne16_to_be16(get_ne16(p)); }
|
inline unsigned get_be16(const void *p) noexcept { return ne16_to_be16(get_ne16(p)); }
|
||||||
inline unsigned get_be32(const void *p) { return ne32_to_be32(get_ne32(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) { return ne64_to_be64(get_ne64(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) { return ne16_to_le16(get_ne16(p)); }
|
inline unsigned get_le16(const void *p) noexcept { return ne16_to_le16(get_ne16(p)); }
|
||||||
inline unsigned get_le32(const void *p) { return ne32_to_le32(get_ne32(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) { return ne64_to_le64(get_ne64(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) { set_ne16(p, ne16_to_be16(v)); }
|
inline void set_be16(void *p, unsigned v) noexcept { 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_be32(void *p, unsigned v) noexcept { 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_be64(void *p, upx_uint64_t v) noexcept { 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_le16(void *p, unsigned v) noexcept { 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_le32(void *p, unsigned v) noexcept { 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 void set_le64(void *p, upx_uint64_t v) noexcept { set_ne64(p, ne64_to_le64(v)); }
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// get/set 24/26
|
// 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);
|
const byte *b = ACC_CCAST(const byte *, p);
|
||||||
return (b[0] << 16) | (b[1] << 8) | (b[2] << 0);
|
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);
|
const byte *b = ACC_CCAST(const byte *, p);
|
||||||
return (b[0] << 0) | (b[1] << 8) | (b[2] << 16);
|
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);
|
byte *b = ACC_PCAST(byte *, p);
|
||||||
b[0] = ACC_ICONV(byte, (v >> 16) & 0xff);
|
b[0] = ACC_ICONV(byte, (v >> 16) & 0xff);
|
||||||
b[1] = ACC_ICONV(byte, (v >> 8) & 0xff);
|
b[1] = ACC_ICONV(byte, (v >> 8) & 0xff);
|
||||||
b[2] = ACC_ICONV(byte, (v >> 0) & 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);
|
byte *b = ACC_PCAST(byte *, p);
|
||||||
b[0] = ACC_ICONV(byte, (v >> 0) & 0xff);
|
b[0] = ACC_ICONV(byte, (v >> 0) & 0xff);
|
||||||
b[1] = ACC_ICONV(byte, (v >> 8) & 0xff);
|
b[1] = ACC_ICONV(byte, (v >> 8) & 0xff);
|
||||||
b[2] = ACC_ICONV(byte, (v >> 16) & 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 unsigned get_le19_5(const void *p) { return 0x7ffff & (get_le32(p) >> 5); }
|
inline unsigned get_le19_5(const void *p) noexcept { return 0x7ffff & (get_le32(p) >> 5); }
|
||||||
inline unsigned get_le14_5(const void *p) { return 0x03fff & (get_le32(p) >> 5); }
|
inline unsigned get_le14_5(const void *p) noexcept { return 0x03fff & (get_le32(p) >> 5); }
|
||||||
|
|
||||||
inline void set_le26(void *p, unsigned v) {
|
inline void set_le26(void *p, unsigned v) noexcept {
|
||||||
// preserve the top 6 bits
|
// preserve the top 6 bits
|
||||||
// set_le32(p, (get_le32(p) & 0xfc000000) | (v & 0x03ffffff));
|
// set_le32(p, (get_le32(p) & 0xfc000000) | (v & 0x03ffffff));
|
||||||
// optimized version, saving a runtime bswap32
|
// optimized version, saving a runtime bswap32
|
||||||
set_ne32(p, (get_ne32(p) & ne32_to_le32(0xfc000000)) |
|
set_ne32(p, (get_ne32(p) & ne32_to_le32(0xfc000000)) |
|
||||||
(ne32_to_le32(v) & ne32_to_le32(0x03ffffff)));
|
(ne32_to_le32(v) & ne32_to_le32(0x03ffffff)));
|
||||||
}
|
}
|
||||||
inline void set_le19_5(void *p, unsigned v) {
|
inline void set_le19_5(void *p, unsigned v) noexcept {
|
||||||
set_le32(p, (get_le32(p) & 0xff00001f) | ((v & 0x07ffff) << 5));
|
set_le32(p, (get_le32(p) & 0xff00001f) | ((v & 0x07ffff) << 5));
|
||||||
}
|
}
|
||||||
inline void set_le14_5(void *p, unsigned v) {
|
inline void set_le14_5(void *p, unsigned v) noexcept {
|
||||||
set_le32(p, (get_le32(p) & 0xfff8001f) | ((v & 0x003fff) << 5));
|
set_le32(p, (get_le32(p) & 0xfff8001f) | ((v & 0x003fff) << 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,42 +206,42 @@ static forceinline upx_int64_t sign_extend(upx_uint64_t v, unsigned bits) noexce
|
||||||
return ACC_ICAST(upx_int64_t, v);
|
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);
|
unsigned v = get_be16(p);
|
||||||
return sign_extend(v, 16);
|
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);
|
unsigned v = get_be24(p);
|
||||||
return sign_extend(v, 24);
|
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);
|
unsigned v = get_be32(p);
|
||||||
return sign_extend(v, 32);
|
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);
|
upx_uint64_t v = get_be64(p);
|
||||||
return sign_extend(v, 64);
|
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);
|
unsigned v = get_le16(p);
|
||||||
return sign_extend(v, 16);
|
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);
|
unsigned v = get_le24(p);
|
||||||
return sign_extend(v, 24);
|
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);
|
unsigned v = get_le32(p);
|
||||||
return sign_extend(v, 32);
|
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);
|
upx_uint64_t v = get_le64(p);
|
||||||
return sign_extend(v, 64);
|
return sign_extend(v, 64);
|
||||||
}
|
}
|
||||||
|
@ -257,11 +257,13 @@ inline upx_int64_t get_le64_signed(const void *p) {
|
||||||
// to have gcc bug 17519 fixed - see http://gcc.gnu.org/PR17519 ]
|
// 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
|
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
|
||||||
byte d[2];
|
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);
|
set_be16(d, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -302,16 +304,17 @@ struct alignas(1) BE16 {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator unsigned() const noexcept { return get_be16(d); }
|
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); }
|
||||||
bool operator<(const BE16 &v) const noexcept { return unsigned(*this) < unsigned(v); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) BE32 {
|
struct alignas(1) BE32 final {
|
||||||
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
|
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
|
||||||
byte d[4];
|
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);
|
set_be32(d, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -352,16 +355,17 @@ struct alignas(1) BE32 {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator unsigned() const noexcept { return get_be32(d); }
|
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); }
|
||||||
bool operator<(const BE32 &v) const noexcept { return unsigned(*this) < unsigned(v); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) BE64 {
|
struct alignas(1) BE64 final {
|
||||||
typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t
|
typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t
|
||||||
byte d[8];
|
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);
|
set_be64(d, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -402,16 +406,17 @@ struct alignas(1) BE64 {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator upx_uint64_t() const noexcept { return get_be64(d); }
|
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); }
|
||||||
bool operator<(const BE64 &v) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(v); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) LE16 {
|
struct alignas(1) LE16 final {
|
||||||
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
|
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
|
||||||
byte d[2];
|
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);
|
set_le16(d, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -452,16 +457,17 @@ struct alignas(1) LE16 {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator unsigned() const noexcept { return get_le16(d); }
|
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); }
|
||||||
bool operator<(const LE16 &v) const noexcept { return unsigned(*this) < unsigned(v); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) LE32 {
|
struct alignas(1) LE32 final {
|
||||||
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
|
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
|
||||||
byte d[4];
|
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);
|
set_le32(d, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -502,16 +508,17 @@ struct alignas(1) LE32 {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator unsigned() const noexcept { return get_le32(d); }
|
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); }
|
||||||
bool operator<(const LE32 &v) const noexcept { return unsigned(*this) < unsigned(v); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) LE64 {
|
struct alignas(1) LE64 final {
|
||||||
typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t
|
typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t
|
||||||
byte d[8];
|
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);
|
set_le64(d, v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -552,9 +559,8 @@ struct alignas(1) LE64 {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator upx_uint64_t() const noexcept { return get_le64(d); }
|
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); }
|
||||||
bool operator<(const LE64 &v) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(v); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
@ -642,39 +648,6 @@ inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN(unsigned(a),
|
||||||
// misc support
|
// 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
|
// native types
|
||||||
#if (ACC_ABI_BIG_ENDIAN)
|
#if (ACC_ABI_BIG_ENDIAN)
|
||||||
typedef BE16 NE16;
|
typedef BE16 NE16;
|
||||||
|
@ -698,6 +671,44 @@ typedef LE64 NE64;
|
||||||
#define ne64_compare_signed le64_compare_signed
|
#define ne64_compare_signed le64_compare_signed
|
||||||
#endif
|
#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.
|
// Provide namespaces and classes to abstract endianness policies.
|
||||||
//
|
//
|
||||||
|
|
|
@ -216,10 +216,12 @@ private:
|
||||||
ACC_CXX_DISABLE_NEW_DELETE
|
ACC_CXX_DISABLE_NEW_DELETE
|
||||||
};
|
};
|
||||||
|
|
||||||
// native policy (aka host policy)
|
// Native Endianness policy (aka host policy)
|
||||||
#if (ACC_ABI_BIG_ENDIAN)
|
#if (ACC_ABI_BIG_ENDIAN)
|
||||||
|
typedef BEPolicy NEPolicy;
|
||||||
typedef BEPolicy HostPolicy;
|
typedef BEPolicy HostPolicy;
|
||||||
#elif (ACC_ABI_LITTLE_ENDIAN)
|
#elif (ACC_ABI_LITTLE_ENDIAN)
|
||||||
|
typedef LEPolicy NEPolicy;
|
||||||
typedef LEPolicy HostPolicy;
|
typedef LEPolicy HostPolicy;
|
||||||
#else
|
#else
|
||||||
#error "ACC_ABI_ENDIAN"
|
#error "ACC_ABI_ENDIAN"
|
||||||
|
|
|
@ -83,6 +83,7 @@ int upx_doctest_check() { return upx_doctest_check(0, nullptr); }
|
||||||
// compile-time checks
|
// 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<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<unsigned short, upx_uint16_t>::value))
|
||||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<int, upx_int32_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<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((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_bswap16(0x04030201) == 0x0201)
|
||||||
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap32(0x04030201) == 0x04030201)
|
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap32(0x04030201) == 0x04030201)
|
||||||
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap64(0x0807060504030201ull) == 0x0807060504030201ull)
|
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(bswap16(0x04030201) == 0x0102)
|
||||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(0x04030201) == 0x01020304)
|
ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(0x04030201) == 0x01020304)
|
||||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(0x0807060504030201ull) == 0x0102030405060708ull)
|
ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(0x0807060504030201ull) == 0x0102030405060708ull)
|
||||||
|
@ -145,83 +161,100 @@ ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 > 0)
|
||||||
|
|
||||||
namespace {
|
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>
|
template <class T>
|
||||||
struct TestBELE {
|
struct TestBELE {
|
||||||
static noinline bool test(void) {
|
static noinline bool test(void) {
|
||||||
// POD checks
|
CheckIntegral<T>::check();
|
||||||
{
|
CheckAlignment<T>::check();
|
||||||
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);
|
|
||||||
}
|
|
||||||
// arithmetic checks (modern compilers will optimize this away)
|
// arithmetic checks (modern compilers will optimize this away)
|
||||||
{
|
T allbits;
|
||||||
T allbits;
|
allbits = 0;
|
||||||
allbits = 0;
|
allbits += 1;
|
||||||
allbits += 1;
|
allbits -= 2;
|
||||||
allbits -= 2;
|
T v1;
|
||||||
T v1;
|
v1 = 1;
|
||||||
v1 = 1;
|
v1 *= 2;
|
||||||
v1 *= 2;
|
v1 /= 1;
|
||||||
v1 /= 1;
|
v1 -= 1;
|
||||||
v1 -= 1;
|
T v2;
|
||||||
T v2;
|
v2 = 1;
|
||||||
v2 = 1;
|
assert((v1 == v2));
|
||||||
assert((v1 == v2));
|
assert(!(v1 != v2));
|
||||||
assert(!(v1 != v2));
|
assert((v1 <= v2));
|
||||||
assert((v1 <= v2));
|
assert((v1 >= v2));
|
||||||
assert((v1 >= v2));
|
assert(!(v1 < v2));
|
||||||
assert(!(v1 < v2));
|
assert(!(v1 > v2));
|
||||||
assert(!(v1 > v2));
|
v2 ^= allbits;
|
||||||
v2 ^= allbits;
|
assert(!(v1 == v2));
|
||||||
assert(!(v1 == v2));
|
assert((v1 != v2));
|
||||||
assert((v1 != v2));
|
assert((v1 <= v2));
|
||||||
assert((v1 <= v2));
|
assert(!(v1 >= v2));
|
||||||
assert(!(v1 >= v2));
|
assert((v1 < v2));
|
||||||
assert((v1 < v2));
|
assert(!(v1 > v2));
|
||||||
assert(!(v1 > v2));
|
v2 += 2;
|
||||||
v2 += 2;
|
assert(v1 == 1);
|
||||||
assert(v1 == 1);
|
assert(v2 == 0);
|
||||||
assert(v2 == 0);
|
v1 <<= 1;
|
||||||
v1 <<= 1;
|
v1 |= v2;
|
||||||
v1 |= v2;
|
v1 >>= 1;
|
||||||
v1 >>= 1;
|
v2 &= v1;
|
||||||
v2 &= v1;
|
v2 /= v1;
|
||||||
v2 /= v1;
|
v2 *= v1;
|
||||||
v2 *= v1;
|
assert(v1 == 1);
|
||||||
assert(v1 == 1);
|
assert(v2 == 0);
|
||||||
assert(v2 == 0);
|
if ((v1 ^ v2) != 1)
|
||||||
if ((v1 ^ v2) != 1)
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -278,6 +311,18 @@ void upx_compiler_sanity_check(void) {
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(LE32)
|
COMPILE_TIME_ASSERT_ALIGNED1(LE32)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(LE64)
|
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(sizeof(upx_charptr_unit_type) == 1)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(upx_charptr_unit_type)
|
COMPILE_TIME_ASSERT_ALIGNED1(upx_charptr_unit_type)
|
||||||
COMPILE_TIME_ASSERT(sizeof(*((charptr) nullptr)) == 1)
|
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);
|
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));
|
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,
|
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);
|
res->lit_context_bits, res->dict_size, res->num_probs);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error:
|
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
|
// UPX extra stuff in first byte: 5 high bits convenience for stub decompressor
|
||||||
unsigned t = res->lit_context_bits + res->lit_pos_bits;
|
unsigned t = res->lit_context_bits + res->lit_pos_bits;
|
||||||
os.WriteByte(Byte((t << 3) | res->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
|
// compress
|
||||||
rh = enc.Code(&is, &os, nullptr, nullptr, &progress);
|
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:
|
error:
|
||||||
*dst_len = (unsigned) os.b_pos;
|
*dst_len = (unsigned) os.b_pos;
|
||||||
// printf("\nlzma_compress: %d: %u %u %u %u %u, %u - > %u\n", r, res->pos_bits,
|
NO_printf("\nlzma_compress: %d: %u %u %u %u %u, %u - > %u\n", r, res->pos_bits,
|
||||||
// res->lit_pos_bits,
|
res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs, src_len,
|
||||||
// res->lit_context_bits, res->dict_size, res->num_probs, src_len, *dst_len);
|
*dst_len);
|
||||||
// printf("%u %u %u\n", is.__m_RefCount, os.__m_RefCount, progress.__m_RefCount);
|
NO_printf("%u %u %u\n", is.__m_RefCount, os.__m_RefCount, progress.__m_RefCount);
|
||||||
return r;
|
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.lit_context_bits == (unsigned) s.Properties.lc);
|
||||||
assert(cresult->result_lzma.num_probs == (unsigned) LzmaGetNumProbs(&s.Properties));
|
assert(cresult->result_lzma.num_probs == (unsigned) LzmaGetNumProbs(&s.Properties));
|
||||||
const lzma_compress_result_t *res = &cresult->result_lzma;
|
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,
|
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);
|
res->lit_context_bits, res->dict_size, res->num_probs);
|
||||||
UNUSED(res);
|
UNUSED(res);
|
||||||
}
|
}
|
||||||
s.Probs = (CProb *) malloc(sizeof(CProb) * LzmaGetNumProbs(&s.Properties));
|
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>
|
template <class T>
|
||||||
inline constexpr bool upx_std_is_bounded_array_v = upx_std_is_bounded_array<T>::value;
|
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>
|
template <class T>
|
||||||
struct upx_is_integral : public std::is_integral<T> {};
|
struct upx_is_integral : public std::is_integral<T> {};
|
||||||
template <class 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;
|
typedef upx_int64_t upx_off_t;
|
||||||
#undef off_t
|
#undef off_t
|
||||||
#if 0
|
#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
|
#define off_t DO_NOT_USE_off_t
|
||||||
#else
|
#else
|
||||||
#define off_t upx_off_t
|
#define off_t upx_off_t
|
||||||
|
@ -593,9 +603,9 @@ template <class T, T default_value_, T min_value_, T max_value_>
|
||||||
struct OptVar
|
struct OptVar
|
||||||
{
|
{
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
static const T default_value = default_value_;
|
static constexpr T default_value = default_value_;
|
||||||
static const T min_value = min_value_;
|
static constexpr T min_value = min_value_;
|
||||||
static const T max_value = max_value_;
|
static constexpr T max_value = max_value_;
|
||||||
|
|
||||||
static void assertValue(const T &v) {
|
static void assertValue(const T &v) {
|
||||||
// info: this generates annoying warnings "unsigned >= 0 is always true"
|
// info: this generates annoying warnings "unsigned >= 0 is always true"
|
||||||
|
|
|
@ -49,9 +49,10 @@
|
||||||
|
|
||||||
// disable some pedantic warnings
|
// disable some pedantic warnings
|
||||||
#if (ACC_CC_MSC)
|
#if (ACC_CC_MSC)
|
||||||
#pragma warning(disable : 4244) // -Wconversion
|
#pragma warning(disable : 4127) // W4: conditional expression is constant
|
||||||
#pragma warning(disable : 4267) // -Wconversion
|
#pragma warning(disable : 4244) // W3: conversion from 'type1' to 'type2', possible loss of data
|
||||||
#pragma warning(disable : 4820) // padding added after data member
|
#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
|
#endif
|
||||||
|
|
||||||
#undef snprintf
|
#undef snprintf
|
||||||
|
@ -83,7 +84,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// C++ submodule headers
|
// UPX vendor git submodule headers
|
||||||
#include <doctest/doctest/parts/doctest_fwd.h>
|
#include <doctest/doctest/parts/doctest_fwd.h>
|
||||||
#if WITH_BOOST_PFR
|
#if WITH_BOOST_PFR
|
||||||
#include <sstream>
|
#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);
|
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) {
|
static void e_method(int m, int l) {
|
||||||
fflush(con_term);
|
fflush(con_term);
|
||||||
fprintf(stderr, "%s: illegal method option -- %d/%d\n", argv0, m, l);
|
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) */
|
#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
|
// check options
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
static void check_not_both(bool e1, bool e2, const char *c1, const char *c2) {
|
static void check_not_both(bool e1, bool e2, const char *c1, const char *c2) {
|
||||||
if (e1 && e2) {
|
if (e1 && e2) {
|
||||||
fprintf(stderr, "%s: ", argv0);
|
fprintf(stderr, "%s: cannot use both '%s' and '%s'\n", argv0, c1, c2);
|
||||||
fprintf(stderr, "cannot use both '%s' and '%s'\n", c1, c2);
|
|
||||||
e_usage();
|
e_usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/msg.cpp
13
src/msg.cpp
|
@ -26,12 +26,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "headers.h"
|
#include "headers.h"
|
||||||
#include <typeinfo>
|
#include <typeinfo> // typeid()
|
||||||
#include "conf.h"
|
#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;
|
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()));
|
snprintf(buf + l, sizeof(buf) - l, ": %s", strerror(e->getErrno()));
|
||||||
#if 1
|
#if 1
|
||||||
// some compilers (e.g. Borland C++) put a trailing '\n'
|
// some compilers (e.g. Borland C++) put a trailing '\n'
|
||||||
// into strerror() result
|
// into the strerror() result
|
||||||
l = strlen(buf);
|
l = strlen(buf);
|
||||||
while (l-- > 0 && (buf[l] == '\n' || buf[l] == ' '))
|
while (l-- > 0 && (buf[l] == '\n' || buf[l] == ' '))
|
||||||
buf[l] = 0;
|
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;
|
static int info_header = 0;
|
||||||
|
@ -202,10 +201,8 @@ void info(const char *format, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void infoWarning(const char *format, ...) {
|
void infoWarning(const char *format, ...) {
|
||||||
if (opt->info_mode <= 0) {
|
if (opt->info_mode <= 0)
|
||||||
// FIXME - should still print something here
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
va_list args;
|
va_list args;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
va_start(args, format);
|
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>
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#ifndef __UPX_P_ELF_H
|
|
||||||
#define __UPX_P_ELF_H 1
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// N_Elf
|
// N_Elf
|
||||||
|
@ -315,6 +311,7 @@ struct ElfClass_32
|
||||||
COMPILE_TIME_ASSERT(sizeof(Rel) == 8)
|
COMPILE_TIME_ASSERT(sizeof(Rel) == 8)
|
||||||
COMPILE_TIME_ASSERT(sizeof(Rela) == 12)
|
COMPILE_TIME_ASSERT(sizeof(Rela) == 12)
|
||||||
COMPILE_TIME_ASSERT(sizeof(Sym) == 16)
|
COMPILE_TIME_ASSERT(sizeof(Sym) == 16)
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(External_Note) == 12)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Ehdr)
|
COMPILE_TIME_ASSERT_ALIGNED1(Ehdr)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Phdr)
|
COMPILE_TIME_ASSERT_ALIGNED1(Phdr)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Shdr)
|
COMPILE_TIME_ASSERT_ALIGNED1(Shdr)
|
||||||
|
@ -322,6 +319,7 @@ struct ElfClass_32
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Rel)
|
COMPILE_TIME_ASSERT_ALIGNED1(Rel)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Rela)
|
COMPILE_TIME_ASSERT_ALIGNED1(Rela)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Sym)
|
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(Rel) == 16)
|
||||||
COMPILE_TIME_ASSERT(sizeof(Rela) == 24)
|
COMPILE_TIME_ASSERT(sizeof(Rela) == 24)
|
||||||
COMPILE_TIME_ASSERT(sizeof(Sym) == 24)
|
COMPILE_TIME_ASSERT(sizeof(Sym) == 24)
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(External_Note) == 12)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Ehdr)
|
COMPILE_TIME_ASSERT_ALIGNED1(Ehdr)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Phdr)
|
COMPILE_TIME_ASSERT_ALIGNED1(Phdr)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Shdr)
|
COMPILE_TIME_ASSERT_ALIGNED1(Shdr)
|
||||||
|
@ -363,6 +362,7 @@ struct ElfClass_64
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Rel)
|
COMPILE_TIME_ASSERT_ALIGNED1(Rel)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Rela)
|
COMPILE_TIME_ASSERT_ALIGNED1(Rela)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(Sym)
|
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::Sym Elf_LE64_Sym;
|
||||||
typedef ElfClass_LE64::External_Note Elf_LE64_External_Note;
|
typedef ElfClass_LE64::External_Note Elf_LE64_External_Note;
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
#ifdef WANT_EHDR_ENUM
|
#ifdef WANT_EHDR_ENUM
|
||||||
#undef WANT_EHDR_ENUM
|
#undef WANT_EHDR_ENUM
|
||||||
enum { // e_ident[]
|
enum { // indices for e_ident[16]
|
||||||
EI_CLASS = 4,
|
EI_CLASS = 4,
|
||||||
EI_DATA = 5, /* Data encoding */
|
EI_DATA = 5, /* Data encoding */
|
||||||
EI_VERSION = 6,
|
EI_VERSION = 6,
|
||||||
|
@ -52,12 +52,15 @@
|
||||||
ELFDATA2MSB = 2, /* 2's complement, big endian */
|
ELFDATA2MSB = 2, /* 2's complement, big endian */
|
||||||
};
|
};
|
||||||
enum { // e_ident[EI_OSABI]
|
enum { // e_ident[EI_OSABI]
|
||||||
ELFOSABI_NONE = 0, // == ELFOSABI_SYSV
|
ELFOSABI_NONE = 0, // == ELFOSABI_SYSV
|
||||||
ELFOSABI_NETBSD = 2,
|
ELFOSABI_NETBSD = 2,
|
||||||
ELFOSABI_LINUX = 3,
|
ELFOSABI_LINUX = 3,
|
||||||
|
ELFOSABI_SOLARIS = 6,
|
||||||
|
ELFOSABI_AIX = 7,
|
||||||
ELFOSABI_FREEBSD = 9,
|
ELFOSABI_FREEBSD = 9,
|
||||||
ELFOSABI_OPENBSD = 12,
|
ELFOSABI_OPENBSD = 12,
|
||||||
ELFOSABI_ARM = 97,
|
ELFOSABI_ARM = 97,
|
||||||
|
ELFOSABI_STANDALONE = 255 // Standalone (embedded) application
|
||||||
};
|
};
|
||||||
enum { // e_type
|
enum { // e_type
|
||||||
ET_NONE = 0, /* No file type */
|
ET_NONE = 0, /* No file type */
|
||||||
|
@ -67,17 +70,18 @@
|
||||||
ET_CORE = 4, /* Core file */
|
ET_CORE = 4, /* Core file */
|
||||||
};
|
};
|
||||||
enum { // e_machine
|
enum { // e_machine
|
||||||
EM_386 = 3,
|
EM_386 = 3, // i386
|
||||||
EM_MIPS = 8,
|
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_PPC = 20,
|
||||||
EM_PPC64 = 21,
|
EM_PPC64 = 21,
|
||||||
EM_ARM = 40,
|
EM_ARM = 40,
|
||||||
EM_X86_64 = 62,
|
EM_X86_64 = 62, // amd64
|
||||||
EM_AMD64 = EM_X86_64,
|
EM_AMD64 = EM_X86_64,
|
||||||
EM_AARCH64 = 183,
|
EM_AARCH64 = 183, // arm64
|
||||||
EM_ARM64 = EM_AARCH64,
|
EM_ARM64 = EM_AARCH64,
|
||||||
|
EM_RISCV = 243, // risc-v
|
||||||
|
EM_LOONGARCH = 258,
|
||||||
};
|
};
|
||||||
enum { // e_version
|
enum { // e_version
|
||||||
EV_CURRENT = 1,
|
EV_CURRENT = 1,
|
||||||
|
@ -88,7 +92,7 @@
|
||||||
#ifdef WANT_PHDR_ENUM
|
#ifdef WANT_PHDR_ENUM
|
||||||
#undef WANT_PHDR_ENUM
|
#undef WANT_PHDR_ENUM
|
||||||
enum { // p_type
|
enum { // p_type
|
||||||
PT_NULL = 0, /* Ingore: a "comment" */
|
PT_NULL = 0, /* Ignore: a "comment" */
|
||||||
PT_LOAD = 1, /* Loadable program segment */
|
PT_LOAD = 1, /* Loadable program segment */
|
||||||
PT_DYNAMIC = 2, /* Dynamic linking information */
|
PT_DYNAMIC = 2, /* Dynamic linking information */
|
||||||
PT_INTERP = 3, /* Name of program interpreter */
|
PT_INTERP = 3, /* Name of program interpreter */
|
||||||
|
|
10
src/p_mach.h
10
src/p_mach.h
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef __UPX_P_MACHO_H
|
#ifndef __UPX_P_MACHO_H
|
||||||
#define __UPX_P_MACHO_H 1
|
#define __UPX_P_MACHO_H 1
|
||||||
|
|
||||||
|
@ -33,15 +34,10 @@
|
||||||
|
|
||||||
__packed_struct(Mach_fat_header)
|
__packed_struct(Mach_fat_header)
|
||||||
BE32 magic;
|
BE32 magic;
|
||||||
# if 0
|
enum : unsigned { // note conflict with java bytecode PackLinuxI386
|
||||||
enum { // note conflict with java bytecode PackLinuxI386
|
|
||||||
FAT_MAGIC = 0xcafebabe,
|
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.
|
BE32 nfat_arch; // Number of Mach_fat_arch which follow.
|
||||||
__packed_struct_end()
|
__packed_struct_end()
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef __UPX_P_UNIX_H
|
#ifndef __UPX_P_UNIX_H
|
||||||
#define __UPX_P_UNIX_H 1
|
#define __UPX_P_UNIX_H 1
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef __UPX_P_VMLINX_H
|
#ifndef __UPX_P_VMLINX_H
|
||||||
#define __UPX_P_VMLINX_H 1
|
#define __UPX_P_VMLINX_H 1
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef __UPX_P_VMLINZ_H
|
#ifndef __UPX_P_VMLINZ_H
|
||||||
#define __UPX_P_VMLINZ_H 1
|
#define __UPX_P_VMLINZ_H 1
|
||||||
|
|
||||||
|
|
|
@ -145,9 +145,9 @@ bool PackW32PeI386::needForceOption() const {
|
||||||
// return true if we need `--force` to pack this file
|
// return true if we need `--force` to pack this file
|
||||||
bool r = false;
|
bool r = false;
|
||||||
r |= (ih.opthdrsize != 0xe0);
|
r |= (ih.opthdrsize != 0xe0);
|
||||||
r |= ((ih.flags & EXECUTABLE) == 0);
|
r |= ((ih.flags & IMAGE_FILE_EXECUTABLE_IMAGE) == 0);
|
||||||
r |= ((ih.flags & BITS_32_MACHINE) == 0); // 32 bit machine flag must be set
|
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.coffmagic != 0x10b); // COFF magic is 0x10B in PE files
|
||||||
r |= (ih.entry == 0 && !isdll);
|
r |= (ih.entry == 0 && !isdll);
|
||||||
r |= (ih.ddirsentries != 16);
|
r |= (ih.ddirsentries != 16);
|
||||||
r |= (IDSIZE(PEDIR_EXCEPTION) != 0); // is this used on i386?
|
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
|
// 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
|
// 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
|
// 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"
|
// rva of the most significant byte of member "flags" in section "UPX0"
|
||||||
const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1;
|
const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1;
|
||||||
|
|
|
@ -114,7 +114,7 @@ void PackW64PeAmd64::buildLoader(const Filter *ft) {
|
||||||
if (sorelocs) {
|
if (sorelocs) {
|
||||||
addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2",
|
addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2",
|
||||||
"PERELOC3", big_relocs ? "REL64BIG" : "", "RELOC64J");
|
"PERELOC3", big_relocs ? "REL64BIG" : "", "RELOC64J");
|
||||||
if __acc_cte (0) {
|
if (0) {
|
||||||
addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "",
|
addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "",
|
||||||
big_relocs & 2 ? "PERELHI0" : "");
|
big_relocs & 2 ? "PERELHI0" : "");
|
||||||
}
|
}
|
||||||
|
@ -148,9 +148,9 @@ bool PackW64PeAmd64::needForceOption() const {
|
||||||
// return true if we need `--force` to pack this file
|
// return true if we need `--force` to pack this file
|
||||||
bool r = false;
|
bool r = false;
|
||||||
r |= (ih.opthdrsize != 0xf0); // optional header size is 0xF0 in PE32+ files
|
r |= (ih.opthdrsize != 0xf0); // optional header size is 0xF0 in PE32+ files
|
||||||
r |= ((ih.flags & EXECUTABLE) == 0);
|
r |= ((ih.flags & IMAGE_FILE_EXECUTABLE_IMAGE) == 0);
|
||||||
r |= ((ih.flags & BITS_32_MACHINE) != 0); // 32 bit machine flag may not be set
|
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.coffmagic != 0x20b); // COFF magic is 0x20B in PE32+ files
|
||||||
r |= (ih.entry == 0 && !isdll);
|
r |= (ih.entry == 0 && !isdll);
|
||||||
r |= (ih.ddirsentries != 16);
|
r |= (ih.ddirsentries != 16);
|
||||||
return r;
|
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
|
// 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
|
// 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
|
// 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"
|
// rva of the most significant byte of member "flags" in section "UPX0"
|
||||||
const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1;
|
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
|
// return true if we need `--force` to pack this file
|
||||||
bool r = false;
|
bool r = false;
|
||||||
r |= (ih.opthdrsize != 0xe0);
|
r |= (ih.opthdrsize != 0xe0);
|
||||||
r |= ((ih.flags & EXECUTABLE) == 0);
|
r |= ((ih.flags & IMAGE_FILE_EXECUTABLE_IMAGE) == 0);
|
||||||
r |= (ih.entry == 0 /*&& !isdll*/);
|
r |= (ih.entry == 0 /*&& !isdll*/);
|
||||||
r |= (ih.ddirsentries != 16);
|
r |= (ih.ddirsentries != 16);
|
||||||
//// r |= (IDSIZE(PEDIR_EXCEPTION) != 0); // is this used on arm?
|
//// 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);
|
unsigned image_size, int bits, bool bswap);
|
||||||
|
|
||||||
// Target Endianness abstraction
|
// Target Endianness abstraction
|
||||||
unsigned get_te16(const void *p) const { return bele->get16(p); }
|
#if 1
|
||||||
unsigned get_te32(const void *p) const { return bele->get32(p); }
|
// try to detect TE16 vs TE32 vs TE64 size mismatches; note that "byte" is explicitly allowed
|
||||||
upx_uint64_t get_te64(const void *p) const { return bele->get64(p); }
|
template <class T>
|
||||||
void set_te16(void *p, unsigned v) { bele->set16(p, v); }
|
static inline constexpr bool is_te16_type = is_same_any_v<T, byte, upx_uint16_t, BE16, LE16>;
|
||||||
void set_te32(void *p, unsigned v) { bele->set32(p, v); }
|
template <class T>
|
||||||
void set_te64(void *p, upx_uint64_t v) { bele->set64(p, v); }
|
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:
|
protected:
|
||||||
const N_BELE_RTP::AbstractPolicy *bele = nullptr; // target endianness
|
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?
|
// CHPE Compiled Hybrid PE: Microsoft internal only?
|
||||||
// CHPEV2 Compiled Hybrid PE: ARM64EC, ARM64X
|
// CHPEV2 Compiled Hybrid PE: ARM64EC, ARM64X
|
||||||
/*static*/ int PeFile::checkMachine(unsigned cpu) {
|
/*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)
|
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)
|
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 ???
|
// FIXME: it seems that arm64ec actually uses MACHINE_AMD64 ???
|
||||||
if (cpu == IMAGE_FILE_MACHINE_ARM64EC)
|
if (cpu == IMAGE_FILE_MACHINE_ARM64EC)
|
||||||
throwCantPack("win64/arm64ec is not supported");
|
throwCantPack("win64/arm64ec is not yet supported");
|
||||||
|
|
||||||
// supported
|
// supported
|
||||||
if (cpu == IMAGE_FILE_MACHINE_AMD64)
|
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 ???
|
if (cpu >= IMAGE_FILE_MACHINE_I386 && cpu <= 0x150) // what is this 0x150 ???
|
||||||
return UPX_F_W32PE_I386;
|
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);
|
throwCantPack("pefile: unsupported machine %#x", cpu);
|
||||||
return 0; // pacify msvc
|
return 0; // pacify msvc
|
||||||
}
|
}
|
||||||
|
@ -1339,7 +1347,7 @@ void PeFile::processTls2(Reloc *rel, const Interval *iv, unsigned newaddr,
|
||||||
return;
|
return;
|
||||||
// add new relocation entries
|
// 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);
|
rel->add(tls_handler_offset + tls_handler_offset_reloc, reloc_type);
|
||||||
|
|
||||||
unsigned ic;
|
unsigned ic;
|
||||||
|
@ -1388,10 +1396,10 @@ void PeFile::processTls2(Reloc *rel, const Interval *iv, unsigned newaddr,
|
||||||
|
|
||||||
void PeFile::processLoadConf(Interval *iv) // pass 1
|
void PeFile::processLoadConf(Interval *iv) // pass 1
|
||||||
{
|
{
|
||||||
if (IDSIZE(PEDIR_LOADCONF) == 0)
|
if (IDSIZE(PEDIR_LOAD_CONFIG) == 0)
|
||||||
return;
|
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);
|
const byte *const loadconf = ibuf.subref("bad loadconf %#x", lcaddr, 4);
|
||||||
soloadconf = get_le32(loadconf);
|
soloadconf = get_le32(loadconf);
|
||||||
if (soloadconf == 0)
|
if (soloadconf == 0)
|
||||||
|
@ -2008,7 +2016,7 @@ void PeFile::checkHeaderValues(unsigned subsystem, unsigned mask, unsigned ih_en
|
||||||
throwCantPack(buf);
|
throwCantPack(buf);
|
||||||
}
|
}
|
||||||
// check CLR Runtime Header directory entry
|
// check CLR Runtime Header directory entry
|
||||||
if (IDSIZE(PEDIR_COMRT))
|
if (IDSIZE(PEDIR_COM_DESCRIPTOR))
|
||||||
throwCantPack(".NET files are not yet supported");
|
throwCantPack(".NET files are not yet supported");
|
||||||
|
|
||||||
if (isection == nullptr)
|
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)
|
if (!opt->force && ih_imagebase < default_imagebase)
|
||||||
throwCantPack("--strip-relocs may not support this imagebase (try "
|
throwCantPack("--strip-relocs may not support this imagebase (try "
|
||||||
"with --force)");
|
"with --force)");
|
||||||
return RELOCS_STRIPPED;
|
return IMAGE_FILE_RELOCS_STRIPPED;
|
||||||
} else
|
} else
|
||||||
info("Base relocations stripping is disabled for this image");
|
info("Base relocations stripping is disabled for this image");
|
||||||
return 0;
|
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 PeFile::readSections(unsigned objs, unsigned usize, unsigned ih_filealign,
|
||||||
unsigned ih_datasize) {
|
unsigned ih_datasize) {
|
||||||
const unsigned xtrasize = UPX_MAX(ih_datasize, 65536u) + IDSIZE(PEDIR_IMPORT) +
|
const unsigned xtrasize = UPX_MAX(ih_datasize, 65536u) + IDSIZE(PEDIR_IMPORT) +
|
||||||
IDSIZE(PEDIR_BOUNDIM) + IDSIZE(PEDIR_IAT) + IDSIZE(PEDIR_DELAYIMP) +
|
IDSIZE(PEDIR_BOUND_IMPORT) + IDSIZE(PEDIR_IAT) +
|
||||||
IDSIZE(PEDIR_RELOC);
|
IDSIZE(PEDIR_DELAY_IMPORT) + IDSIZE(PEDIR_RELOC);
|
||||||
ibuf.alloc(usize + xtrasize);
|
ibuf.alloc(usize + xtrasize);
|
||||||
|
|
||||||
// BOUND IMPORT support. FIXME: is this ok?
|
// 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);
|
overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size, ih_filealign);
|
||||||
if (isection[ic].vsize == 0)
|
if (isection[ic].vsize == 0)
|
||||||
isection[ic].vsize = isection[ic].size;
|
isection[ic].vsize = isection[ic].size;
|
||||||
if ((isection[ic].flags & PEFL_BSS) || isection[ic].rawdataptr == 0 ||
|
if ((isection[ic].flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) ||
|
||||||
(isection[ic].flags & PEFL_INFO)) {
|
isection[ic].rawdataptr == 0 || (isection[ic].flags & IMAGE_SCN_LNK_INFO)) {
|
||||||
// holes.add(isection[ic].vaddr,isection[ic].vsize);
|
// holes.add(isection[ic].vaddr,isection[ic].vsize);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isection[ic].vaddr + isection[ic].size > usize)
|
if (isection[ic].vaddr + isection[ic].size > usize)
|
||||||
throwCantPack("section size problem");
|
throwCantPack("section size problem");
|
||||||
if (!isrtm &&
|
if (!isrtm && ((isection[ic].flags & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED)) ==
|
||||||
((isection[ic].flags & (PEFL_WRITE | PEFL_SHARED)) == (PEFL_WRITE | PEFL_SHARED)))
|
(IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED)))
|
||||||
if (!opt->force)
|
if (!opt->force)
|
||||||
throwCantPack("writable shared sections not supported (try --force)");
|
throwCantPack("writable shared sections not supported (try --force)");
|
||||||
if (jc && isection[ic].rawdataptr - jc > ih_filealign && !opt->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);
|
checkHeaderValues(ih.subsystem, subsystem_mask, ih.entry, ih.filealign);
|
||||||
|
|
||||||
// remove certificate directory entry
|
// remove certificate directory entry
|
||||||
if (IDSIZE(PEDIR_SEC))
|
if (IDSIZE(PEDIR_SECURITY))
|
||||||
IDSIZE(PEDIR_SEC) = IDADDR(PEDIR_SEC) = 0;
|
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;
|
opt->win32_pe.strip_relocs = true;
|
||||||
else
|
else
|
||||||
ih.flags |= handleStripRelocs(ih.imagebase, default_imagebase, ih.dllflags);
|
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 (ih.dllflags & IMAGE_DLLCHARACTERISTICS_GUARD_CF) {
|
||||||
if (opt->force) {
|
if (opt->force) {
|
||||||
const unsigned lcsize = IDSIZE(PEDIR_LOADCONF);
|
const unsigned lcsize = IDSIZE(PEDIR_LOAD_CONFIG);
|
||||||
const unsigned lcaddr = IDADDR(PEDIR_LOADCONF);
|
const unsigned lcaddr = IDADDR(PEDIR_LOAD_CONFIG);
|
||||||
const unsigned gfpos = 14 * sizeof(ih.imagebase) + 6 * sizeof(LE32) + 4 * sizeof(LE16);
|
const unsigned gfpos = 14 * sizeof(ih.imagebase) + 6 * sizeof(LE32) + 4 * sizeof(LE16);
|
||||||
if (lcaddr && lcsize >= gfpos + sizeof(LE32))
|
if (lcaddr && lcsize >= gfpos + sizeof(LE32))
|
||||||
// GuardFlags: Set IMAGE_GUARD_SECURITY_COOKIE_UNUSED
|
// 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;
|
bool allow_filter = true;
|
||||||
if (/*FIXME ih.codebase == ih.database
|
if (/*FIXME ih.codebase == ih.database
|
||||||
||*/ ih.codebase + ih.codesize > ih.imagesize ||
|
||*/ 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;
|
allow_filter = false;
|
||||||
|
|
||||||
const unsigned oam1 = ih.objectalign - 1;
|
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;
|
ODSIZE(PEDIR_DEBUG) = 0;
|
||||||
ODADDR(PEDIR_IAT) = 0;
|
ODADDR(PEDIR_IAT) = 0;
|
||||||
ODSIZE(PEDIR_IAT) = 0;
|
ODSIZE(PEDIR_IAT) = 0;
|
||||||
ODADDR(PEDIR_BOUNDIM) = 0;
|
ODADDR(PEDIR_BOUND_IMPORT) = 0;
|
||||||
ODSIZE(PEDIR_BOUNDIM) = 0;
|
ODSIZE(PEDIR_BOUND_IMPORT) = 0;
|
||||||
|
|
||||||
// tls & loadconf are put into section 1
|
// tls & loadconf are put into section 1
|
||||||
ic = s1addr + s1size - aligned_sotls - soloadconf;
|
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;
|
ic += aligned_sotls;
|
||||||
|
|
||||||
processLoadConf(&rel, &loadconfiv, ic);
|
processLoadConf(&rel, &loadconfiv, ic);
|
||||||
ODADDR(PEDIR_LOADCONF) = soloadconf ? ic : 0;
|
ODADDR(PEDIR_LOAD_CONFIG) = soloadconf ? ic : 0;
|
||||||
ODSIZE(PEDIR_LOADCONF) = soloadconf;
|
ODSIZE(PEDIR_LOAD_CONFIG) = soloadconf;
|
||||||
ic += soloadconf;
|
ic += soloadconf;
|
||||||
|
|
||||||
const bool rel_at_sections_start = last_section_rsrc_only;
|
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[2].rawdataptr = osection[1].rawdataptr + osection[1].size;
|
||||||
|
|
||||||
osection[0].flags = (unsigned) (PEFL_BSS | PEFL_EXEC | PEFL_WRITE | PEFL_READ);
|
osection[0].flags = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ |
|
||||||
osection[1].flags = (unsigned) (PEFL_DATA | PEFL_EXEC | PEFL_WRITE | PEFL_READ);
|
IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE;
|
||||||
osection[2].flags = (unsigned) (PEFL_DATA | PEFL_WRITE | PEFL_READ);
|
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) {
|
if (last_section_rsrc_only) {
|
||||||
strcpy(osection[3].name, ".rsrc");
|
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].size = (soresources + fam1) & ~fam1;
|
||||||
osection[3].vsize = osection[3].size;
|
osection[3].vsize = osection[3].size;
|
||||||
osection[3].rawdataptr = osection[2].rawdataptr + osection[2].size;
|
osection[3].rawdataptr = osection[2].rawdataptr + osection[2].size;
|
||||||
osection[2].flags = (unsigned) (PEFL_DATA | PEFL_READ);
|
osection[2].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
|
||||||
osection[3].flags = (unsigned) (PEFL_DATA | PEFL_READ);
|
osection[3].flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
|
||||||
oh.imagesize = (osection[3].vaddr + osection[3].vsize + oam1) & ~oam1;
|
oh.imagesize = (osection[3].vaddr + osection[3].vsize + oam1) & ~oam1;
|
||||||
if (soresources == 0) {
|
if (soresources == 0) {
|
||||||
oh.objects = 3;
|
oh.objects = 3;
|
||||||
|
@ -2496,10 +2506,8 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
|
||||||
throwCantPack("object alignment too small");
|
throwCantPack("object alignment too small");
|
||||||
|
|
||||||
if (opt->win32_pe.strip_relocs)
|
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);
|
ibuf.clear(0, oh.filealign);
|
||||||
|
|
||||||
info("Image size change: %u -> %u KiB", ih.imagesize / 1024, oh.imagesize / 1024);
|
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,
|
void PeFile::rebuildRelocs(SPAN_S(byte) & extra_info, unsigned bits, unsigned flags,
|
||||||
upx_uint64_t imagebase) {
|
upx_uint64_t imagebase) {
|
||||||
assert(bits == 32 || bits == 64);
|
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;
|
return;
|
||||||
|
|
||||||
if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this
|
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
|
// FIXME: ih.flags is checked here because of a bug in UPX 0.92
|
||||||
if (ih.flags & RELOCS_STRIPPED) {
|
if (ih.flags & IMAGE_FILE_RELOCS_STRIPPED) {
|
||||||
oh.flags |= RELOCS_STRIPPED;
|
oh.flags |= IMAGE_FILE_RELOCS_STRIPPED;
|
||||||
ODADDR(PEDIR_RELOC) = 0;
|
ODADDR(PEDIR_RELOC) = 0;
|
||||||
ODSIZE(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;
|
ODSIZE(PEDIR_DEBUG) = 0;
|
||||||
ODADDR(PEDIR_IAT) = 0;
|
ODADDR(PEDIR_IAT) = 0;
|
||||||
ODSIZE(PEDIR_IAT) = 0;
|
ODSIZE(PEDIR_IAT) = 0;
|
||||||
ODADDR(PEDIR_BOUNDIM) = 0;
|
ODADDR(PEDIR_BOUND_IMPORT) = 0;
|
||||||
ODSIZE(PEDIR_BOUNDIM) = 0;
|
ODSIZE(PEDIR_BOUND_IMPORT) = 0;
|
||||||
|
|
||||||
setOhHeaderSize(osection);
|
setOhHeaderSize(osection);
|
||||||
oh.chksum = 0;
|
oh.chksum = 0;
|
||||||
|
@ -2996,7 +3004,7 @@ void PeFile32::readPeHeader() {
|
||||||
((1u << IMAGE_SUBSYSTEM_EFI_APPLICATION) |
|
((1u << IMAGE_SUBSYSTEM_EFI_APPLICATION) |
|
||||||
(1u << IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) |
|
(1u << IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) |
|
||||||
(1u << IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) | (1u << IMAGE_SUBSYSTEM_EFI_ROM))) != 0;
|
(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_dep_hack &= !isefi;
|
||||||
use_clear_dirty_stack &= !isefi;
|
use_clear_dirty_stack &= !isefi;
|
||||||
}
|
}
|
||||||
|
@ -3049,7 +3057,7 @@ void PeFile64::readPeHeader() {
|
||||||
((1u << IMAGE_SUBSYSTEM_EFI_APPLICATION) |
|
((1u << IMAGE_SUBSYSTEM_EFI_APPLICATION) |
|
||||||
(1u << IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) |
|
(1u << IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) |
|
||||||
(1u << IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) | (1u << IMAGE_SUBSYSTEM_EFI_ROM))) != 0;
|
(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_dep_hack &= !isefi;
|
||||||
use_clear_dirty_stack &= !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_UNKNOWN = 0,
|
||||||
IMAGE_FILE_MACHINE_AMD64 = 0x8664, // win64/pe (amd64)
|
IMAGE_FILE_MACHINE_AMD64 = 0x8664, // win64/pe (amd64)
|
||||||
IMAGE_FILE_MACHINE_ARM = 0x01c0, // wince/arm (Windows CE)
|
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_ARM64 = 0xaa64, // win64/arm64
|
||||||
IMAGE_FILE_MACHINE_ARM64EC = 0xa641, // win64/arm64ec
|
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_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 {
|
enum {
|
||||||
|
@ -227,48 +233,74 @@ protected:
|
||||||
PEDIR_IMPORT = 1,
|
PEDIR_IMPORT = 1,
|
||||||
PEDIR_RESOURCE = 2,
|
PEDIR_RESOURCE = 2,
|
||||||
PEDIR_EXCEPTION = 3, // Exception table
|
PEDIR_EXCEPTION = 3, // Exception table
|
||||||
PEDIR_SEC = 4, // Certificate table (file pointer)
|
PEDIR_SECURITY = 4, // Certificate table (file pointer)
|
||||||
PEDIR_RELOC = 5,
|
PEDIR_BASERELOC = 5,
|
||||||
PEDIR_DEBUG = 6,
|
PEDIR_DEBUG = 6,
|
||||||
PEDIR_COPYRIGHT = 7, // Architecture-specific data
|
PEDIR_ARCHITECTURE = 7, // Architecture-specific data
|
||||||
PEDIR_GLOBALPTR = 8, // Global pointer
|
PEDIR_GLOBALPTR = 8, // Global pointer
|
||||||
PEDIR_TLS = 9,
|
PEDIR_TLS = 9,
|
||||||
PEDIR_LOADCONF = 10, // Load Config Table
|
PEDIR_LOAD_CONFIG = 10, // Load Config Table
|
||||||
PEDIR_BOUNDIM = 11,
|
PEDIR_BOUND_IMPORT = 11,
|
||||||
PEDIR_IAT = 12,
|
PEDIR_IAT = 12,
|
||||||
PEDIR_DELAYIMP = 13, // Delay Import Descriptor
|
PEDIR_DELAY_IMPORT = 13, // Delay Import Descriptor
|
||||||
PEDIR_COMRT = 14, // Com+ Runtime Header
|
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 {
|
enum {
|
||||||
PEFL_CODE = 0x20,
|
IMAGE_FILE_RELOCS_STRIPPED = 0x0001,
|
||||||
PEFL_DATA = 0x40,
|
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
|
||||||
PEFL_BSS = 0x80,
|
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004,
|
||||||
PEFL_INFO = 0x200,
|
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008,
|
||||||
PEFL_EXTRELS = 0x01000000, // extended relocations
|
IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010,
|
||||||
PEFL_DISCARD = 0x02000000,
|
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
|
||||||
PEFL_NOCACHE = 0x04000000,
|
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080,
|
||||||
PEFL_NOPAGE = 0x08000000,
|
IMAGE_FILE_32BIT_MACHINE = 0x0100,
|
||||||
PEFL_SHARED = 0x10000000,
|
IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
|
||||||
PEFL_EXEC = 0x20000000,
|
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400,
|
||||||
PEFL_READ = 0x40000000,
|
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800,
|
||||||
PEFL_WRITE = 0x80000000,
|
IMAGE_FILE_SYSTEM = 0x1000,
|
||||||
};
|
IMAGE_FILE_DLL = 0x2000,
|
||||||
|
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000,
|
||||||
enum {
|
IMAGE_FILE_BYTES_REVERSE_HI = 0x8000,
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -288,10 +320,11 @@ protected:
|
||||||
enum {
|
enum {
|
||||||
IMAGE_SUBSYSTEM_UNKNOWN = 0,
|
IMAGE_SUBSYSTEM_UNKNOWN = 0,
|
||||||
IMAGE_SUBSYSTEM_NATIVE = 1,
|
IMAGE_SUBSYSTEM_NATIVE = 1,
|
||||||
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Graphical
|
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Graphical User Interface
|
||||||
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Character-mode
|
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Character User Interface
|
||||||
IMAGE_SUBSYSTEM_WINDOWS_OS2_CUI = 5,
|
IMAGE_SUBSYSTEM_WINDOWS_OS2_CUI = 5,
|
||||||
IMAGE_SUBSYSTEM_WINDOWS_POSIX_CUI = 7,
|
IMAGE_SUBSYSTEM_WINDOWS_POSIX_CUI = 7,
|
||||||
|
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8,
|
||||||
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
|
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
|
||||||
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
|
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
|
||||||
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
|
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
|
||||||
|
@ -489,7 +522,7 @@ protected:
|
||||||
LE16 objects; // NumberOfSections
|
LE16 objects; // NumberOfSections
|
||||||
byte __[12]; // timestamp + reserved
|
byte __[12]; // timestamp + reserved
|
||||||
LE16 opthdrsize; // SizeOfOptionalHeader
|
LE16 opthdrsize; // SizeOfOptionalHeader
|
||||||
LE16 flags; // Characteristics
|
LE16 flags; // IMAGE_FILE_xxx Characteristics
|
||||||
// 0x18 IMAGE_OPTIONAL_HEADER32
|
// 0x18 IMAGE_OPTIONAL_HEADER32
|
||||||
LE16 coffmagic; // NEW: Stefan Widmann
|
LE16 coffmagic; // NEW: Stefan Widmann
|
||||||
byte ___[2]; // linkerversion
|
byte ___[2]; // linkerversion
|
||||||
|
@ -550,7 +583,7 @@ protected:
|
||||||
LE16 objects; // NumberOfSections
|
LE16 objects; // NumberOfSections
|
||||||
byte __[12]; // timestamp + reserved
|
byte __[12]; // timestamp + reserved
|
||||||
LE16 opthdrsize; // SizeOfOptionalHeader
|
LE16 opthdrsize; // SizeOfOptionalHeader
|
||||||
LE16 flags; // Characteristics
|
LE16 flags; // IMAGE_FILE_xxx Characteristics
|
||||||
// 0x18 IMAGE_OPTIONAL_HEADER64
|
// 0x18 IMAGE_OPTIONAL_HEADER64
|
||||||
LE16 coffmagic; // NEW: Stefan Widmann
|
LE16 coffmagic; // NEW: Stefan Widmann
|
||||||
byte ___[2]; // linkerversion
|
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);
|
alloc(bytes);
|
||||||
debug_set(debug.last_return_address_alloc, upx_return_address());
|
debug_set(debug.last_return_address_alloc, upx_return_address());
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ void MemBuffer::alloc(upx_uint64_t bytes) {
|
||||||
//
|
//
|
||||||
assert(bytes > 0);
|
assert(bytes > 0);
|
||||||
debug_set(debug.last_return_address_alloc, upx_return_address());
|
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())
|
if (use_simple_mcheck())
|
||||||
malloc_bytes += 32;
|
malloc_bytes += 32;
|
||||||
byte *p = (byte *) ::malloc(malloc_bytes);
|
byte *p = (byte *) ::malloc(malloc_bytes);
|
||||||
|
@ -216,7 +216,7 @@ void MemBuffer::alloc(upx_uint64_t bytes) {
|
||||||
}
|
}
|
||||||
ptr = (pointer) (void *) p;
|
ptr = (pointer) (void *) p;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
memset(ptr, 0xff, size_in_bytes);
|
memset(ptr, 0xfb, size_in_bytes);
|
||||||
(void) VALGRIND_MAKE_MEM_UNDEFINED(ptr, size_in_bytes);
|
(void) VALGRIND_MAKE_MEM_UNDEFINED(ptr, size_in_bytes);
|
||||||
#endif
|
#endif
|
||||||
stats.global_alloc_counter += 1;
|
stats.global_alloc_counter += 1;
|
||||||
|
|
|
@ -46,7 +46,7 @@ protected:
|
||||||
size_type size_in_bytes;
|
size_type size_in_bytes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemBufferBase() noexcept : ptr(nullptr), size_in_bytes(0) {}
|
inline MemBufferBase() noexcept : ptr(nullptr), size_in_bytes(0) {}
|
||||||
inline ~MemBufferBase() noexcept {}
|
inline ~MemBufferBase() noexcept {}
|
||||||
|
|
||||||
// NOTE: implicit conversion to underlying pointer
|
// NOTE: implicit conversion to underlying pointer
|
||||||
|
@ -83,7 +83,7 @@ public: // raw access
|
||||||
|
|
||||||
class MemBuffer final : public MemBufferBase<byte> {
|
class MemBuffer final : public MemBufferBase<byte> {
|
||||||
public:
|
public:
|
||||||
MemBuffer() : MemBufferBase<byte>() {}
|
inline MemBuffer() noexcept : MemBufferBase<byte>() {}
|
||||||
explicit MemBuffer(upx_uint64_t bytes);
|
explicit MemBuffer(upx_uint64_t bytes);
|
||||||
~MemBuffer() noexcept;
|
~MemBuffer() noexcept;
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ int ptr_diff_bytes(const void *a, const void *b) {
|
||||||
if very_unlikely (!mem_size_valid_bytes(d))
|
if very_unlikely (!mem_size_valid_bytes(d))
|
||||||
throwCantPack("ptr_diff_bytes-1; take care");
|
throwCantPack("ptr_diff_bytes-1; take care");
|
||||||
} else {
|
} 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");
|
throwCantPack("ptr_diff_bytes-2; take care");
|
||||||
}
|
}
|
||||||
return ACC_ICONV(int, d);
|
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,
|
void upx_stable_sort(void *array, size_t n, size_t element_size,
|
||||||
int (*compare)(const void *, const void *)) {
|
int (*compare)(const void *, const void *)) {
|
||||||
for (size_t i = 1; i < n; i++) {
|
for (size_t i = 1; i < n; i++) {
|
||||||
char *a = (char *) array + element_size * i; // a = &array[i]
|
char *a = (char *) array + element_size * i; // a := &array[i]
|
||||||
if (i != 0 && compare(a - element_size, a) > 0) {
|
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]
|
upx_memswap(a - element_size, a, element_size); // swap elements a[-1] <=> a[0]
|
||||||
i -= 2;
|
i -= 2; // and decrease i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,8 +312,11 @@ TEST_CASE("upx_stable_sort") {
|
||||||
CHECK((a[0] == 0 && a[1] == 1));
|
CHECK((a[0] == 0 && a[1] == 1));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
unsigned a[] = {2, 1, 0};
|
LE64 a[3];
|
||||||
upx_stable_sort(a, 3, sizeof(*a), ne32_compare);
|
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));
|
CHECK((a[0] == 0 && a[1] == 1 && a[2] == 2));
|
||||||
}
|
}
|
||||||
#if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations
|
#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
|
size_t bytes = mem_size(sizeof(T), n); // assert size
|
||||||
T *array = new T[size_t(n)];
|
T *array = new T[size_t(n)];
|
||||||
if (array) {
|
if (array) {
|
||||||
memset(array, 0xff, bytes);
|
memset(array, 0xfb, bytes);
|
||||||
(void) VALGRIND_MAKE_MEM_UNDEFINED(array, bytes);
|
(void) VALGRIND_MAKE_MEM_UNDEFINED(array, bytes);
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
#define New(type, n) (NewArray<type>(n))
|
#define New(type, n) (NewArray<type>(n))
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
Loading…
Reference in New Issue