all: assorted updates and cleanups

This commit is contained in:
Markus F.X.J. Oberhumer 2023-02-05 17:20:32 +01:00
parent 163377d1a0
commit b8d9c2b755
56 changed files with 691 additions and 853 deletions

View File

@ -18,6 +18,8 @@ AttributeMacros:
- __acc_noinline - __acc_noinline
- __acc_static_noinline - __acc_static_noinline
- __acc_static_forceinline - __acc_static_forceinline
- DELETED_FUNCTION
- XSPAN_DELETED_FUNCTION
- forceinline - forceinline
- noinline - noinline
EmptyLineBeforeAccessModifier: Leave EmptyLineBeforeAccessModifier: Leave

View File

@ -101,6 +101,10 @@ jobs:
with: with:
name: ${{ env.artifact_name }} name: ${{ env.artifact_name }}
path: tmp/artifact path: tmp/artifact
- name: 'Run install tests'
run: |
(cd build/extra/gcc/release && DESTDIR=$PWD/Install-with-cmake cmake --install .)
(cd build/extra/gcc/release && DESTDIR=$PWD/Install-with-make make install)
- name: 'Run basic tests' - name: 'Run basic tests'
run: | run: |
make -C build/extra/gcc/debug test make -C build/extra/gcc/debug test
@ -171,6 +175,10 @@ jobs:
with: with:
name: ${{ env.artifact_name }} name: ${{ env.artifact_name }}
path: tmp/artifact path: tmp/artifact
- name: 'Run install tests'
run: |
(cd build/extra/clang/release && DESTDIR=$PWD/Install-with-cmake cmake --install .)
(cd build/extra/clang/release && DESTDIR=$PWD/Install-with-make make install)
- name: 'Run basic tests' - name: 'Run basic tests'
run: | run: |
make -C build/extra/clang/debug test make -C build/extra/clang/debug test
@ -250,12 +258,12 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- { name: amd64-win64-vs2019, os: windows-2019, C: msvc-14.2-x64, arch: amd64 } - { name: amd64-win64-vs2019, os: windows-2019, C: msvc-14.2-x64, arch: amd64 }
- { name: amd64-win64-vs2022, os: windows-2022, C: msvc-14.3-x64, arch: amd64 } - { name: amd64-win64-vs2022, os: windows-2022, C: msvc-14.3-x64, arch: amd64 }
- { name: arm64-win64-vs2019, os: windows-2019, C: msvc-14.2-x64, arch: amd64_arm64 } - { name: arm64-win64-vs2019, os: windows-2019, C: msvc-14.2-arm64, arch: amd64_arm64 }
- { name: arm64-win64-vs2022, os: windows-2022, C: msvc-14.3-x64, arch: amd64_arm64 } - { name: arm64-win64-vs2022, os: windows-2022, C: msvc-14.3-arm64, arch: amd64_arm64 }
- { name: i386-win32-vs2019, os: windows-2019, C: msvc-14.2-x86, arch: amd64_x86 } - { name: i386-win32-vs2019, os: windows-2019, C: msvc-14.2-x86, arch: amd64_x86 }
- { name: i386-win32-vs2022, os: windows-2022, C: msvc-14.3-x86, arch: amd64_x86 } - { name: i386-win32-vs2022, os: windows-2022, C: msvc-14.3-x86, arch: amd64_x86 }
steps: steps:
- name: 'Check out code' - name: 'Check out code'
uses: actions/checkout@v3 uses: actions/checkout@v3
@ -358,8 +366,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-01-30 # 2023-02-05
ZIG_DIST_VERSION: 0.11.0-dev.1491+2b27bc2c6 ZIG_DIST_VERSION: 0.11.0-dev.1575+289e8fab7
# 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 }}
@ -391,7 +399,7 @@ jobs:
mkdir -p -v ~/.local/bin mkdir -p -v ~/.local/bin
cd ~/.local/bin cd ~/.local/bin
ZIG_DIST_NAME=zig-linux-x86_64-${ZIG_DIST_VERSION} ZIG_DIST_NAME=zig-linux-x86_64-${ZIG_DIST_VERSION}
wget -q 'https://ziglang.org/builds/'${ZIG_DIST_NAME}.tar.xz wget -q https://ziglang.org/builds/${ZIG_DIST_NAME}.tar.xz
ls -l ${ZIG_DIST_NAME}.tar.xz ls -l ${ZIG_DIST_NAME}.tar.xz
tar -xoJf ${ZIG_DIST_NAME}.tar.xz tar -xoJf ${ZIG_DIST_NAME}.tar.xz
rm ${ZIG_DIST_NAME}.tar.xz rm ${ZIG_DIST_NAME}.tar.xz

View File

@ -13,7 +13,7 @@
name: 'GitHub - Close inactive issues' name: 'GitHub - Close inactive issues'
on: on:
schedule: schedule:
- cron: '30 6 * * 4' - cron: '10 4 * * 3'
workflow_dispatch: workflow_dispatch:
jobs: jobs:
close-issues: close-issues:

View File

@ -7,7 +7,7 @@ on:
# # The branches below must be a subset of the branches above # # The branches below must be a subset of the branches above
# branches: [ 'devel', 'devel4', 'devel5' ] # branches: [ 'devel', 'devel4', 'devel5' ]
schedule: schedule:
- cron: '20 1 * * 3' - cron: '20 4 * * 3'
workflow_dispatch: workflow_dispatch:
jobs: jobs:

View File

@ -2,7 +2,7 @@
name: 'CI - Minimal CI with Alpine Linux' name: 'CI - Minimal CI with Alpine Linux'
on: { workflow_dispatch: } on: [workflow_dispatch]
jobs: jobs:
job-alpine-cmake: job-alpine-cmake:
strategy: {matrix: {container: ['alpine:3.12','alpine:3.17','alpine:edge']}} strategy: {matrix: {container: ['alpine:3.12','alpine:3.17','alpine:edge']}}

View File

@ -2,7 +2,7 @@ name: 'Static Analyzer - scan-build'
on: on:
schedule: schedule:
- cron: '40 1 * * 3' - cron: '40 4 * * 3'
workflow_dispatch: workflow_dispatch:
jobs: jobs:

View File

@ -5,12 +5,14 @@ if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")
# permissive config defaults when building from source code tarball # permissive config defaults when building from source code tarball
option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." ON) option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." ON)
option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." ON) option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." ON)
option(UPX_CONFIG_DISABLE_WSTRICT "Do not compile with strict compiler warnings." ON)
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." ON) option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." ON)
else() else()
# strict config defaults for devel builds # strict config defaults for Git developer builds
message(STATUS "===== UPX info: strict config defaults enabled") message(STATUS "===== UPX info: strict config defaults enabled")
option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." OFF) option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." OFF)
option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." OFF) option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." OFF)
option(UPX_CONFIG_DISABLE_WSTRICT "Do not compile with strict compiler warnings." OFF)
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." OFF) option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." OFF)
endif() endif()
@ -24,7 +26,7 @@ option(UPX_CONFIG_DISABLE_SELF_PACK_TEST "Do not test packing UPX with itself" O
# Disallow in-source builds. Note that you will still have to manually # Disallow in-source builds. Note that you will still have to manually
# clean up a few files if you accidentally try an in-source build. # clean up a few files if you accidentally try an in-source build.
if(NOT MSVC_IDE) if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git" AND NOT MSVC_IDE)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES ON) set(CMAKE_DISABLE_SOURCE_CHANGES ON)
if(",${CMAKE_CURRENT_SOURCE_DIR}," STREQUAL ",${CMAKE_CURRENT_BINARY_DIR},") if(",${CMAKE_CURRENT_SOURCE_DIR}," STREQUAL ",${CMAKE_CURRENT_BINARY_DIR},")
@ -35,37 +37,36 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# determine git revision # determine Git revision
set(GITREV_SHORT "") set(GITREV_SHORT "")
set(GITREV_PLUS "") set(GITREV_PLUS "")
set(GIT_DESCRIBE "") set(GIT_DESCRIBE "")
find_package(Git) if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git" AND NOT UPX_CONFIG_DISABLE_GITREV)
if(Git_FOUND AND NOT UPX_CONFIG_DISABLE_GITREV) find_package(Git)
execute_process( if(Git_FOUND)
COMMAND "${GIT_EXECUTABLE}" rev-parse --short=12 HEAD execute_process(
RESULT_VARIABLE result ERROR_QUIET COMMAND "${GIT_EXECUTABLE}" rev-parse --short=12 HEAD
OUTPUT_VARIABLE GITREV_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE result ERROR_QUIET
) OUTPUT_VARIABLE GITREV_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE
string(LENGTH "${GITREV_SHORT}" l) )
if(${result} EQUAL 0 AND ${l} EQUAL 12) string(LENGTH "${GITREV_SHORT}" l)
execute_process(RESULT_VARIABLE result COMMAND "${GIT_EXECUTABLE}" diff --quiet) if(${result} EQUAL 0 AND ${l} EQUAL 12)
if(NOT ${result} EQUAL 0) execute_process(RESULT_VARIABLE result COMMAND "${GIT_EXECUTABLE}" diff --quiet)
set(GITREV_PLUS "+") if(NOT ${result} EQUAL 0)
set(GITREV_PLUS "+")
endif()
else()
set(GITREV_SHORT "")
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --match "v*.*.*" --tags --dirty
RESULT_VARIABLE result ERROR_QUIET
OUTPUT_VARIABLE GIT_DESCRIBE OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(GIT_DESCRIBE MATCHES "^v?([0-9]+\\.[0-9]+\\.[0-9]+)-([0-9]+)-g(.+)$")
set(GIT_DESCRIBE "${CMAKE_MATCH_1}-devel.${CMAKE_MATCH_2}+git-${CMAKE_MATCH_3}")
endif() endif()
else()
set(GITREV_SHORT "")
endif() endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --match "v*.*.*" --tags --dirty
RESULT_VARIABLE result ERROR_QUIET
OUTPUT_VARIABLE GIT_DESCRIBE OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(GIT_DESCRIBE MATCHES "^v?([0-9]+\\.[0-9]+\\.[0-9]+)-([0-9]+)-g(.+)$")
set(GIT_DESCRIBE "${CMAKE_MATCH_1}-devel.${CMAKE_MATCH_2}+git-${CMAKE_MATCH_3}")
endif()
endif()
if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") # extra check
set(GITREV_SHORT "")
endif() endif()
if(GITREV_SHORT) if(GITREV_SHORT)
message(STATUS "UPX_VERSION_GITREV = \"${GITREV_SHORT}${GITREV_PLUS}\"") message(STATUS "UPX_VERSION_GITREV = \"${GITREV_SHORT}${GITREV_PLUS}\"")
@ -87,7 +88,7 @@ if(is_multi_config)
set(c "${CMAKE_CONFIGURATION_TYPES}") set(c "${CMAKE_CONFIGURATION_TYPES}")
list(INSERT c 0 "Release") list(INSERT c 0 "Release")
list(INSERT c 1 "Debug") list(INSERT c 1 "Debug")
if (CMAKE_BUILD_TYPE) if(CMAKE_BUILD_TYPE)
list(INSERT c 0 "${CMAKE_BUILD_TYPE}") list(INSERT c 0 "${CMAKE_BUILD_TYPE}")
endif() endif()
list(REMOVE_DUPLICATES c) list(REMOVE_DUPLICATES c)
@ -97,7 +98,7 @@ elseif(NOT CMAKE_BUILD_TYPE)
endif() endif()
#*********************************************************************** #***********************************************************************
# targets and compilation flags # targets
#*********************************************************************** #***********************************************************************
#find_package(Threads) # multithreading is currently not used; maybe in UPX version 5 #find_package(Threads) # multithreading is currently not used; maybe in UPX version 5
@ -126,12 +127,18 @@ add_executable(upx ${upx_SOURCES})
set_property(TARGET upx PROPERTY CXX_STANDARD 17) set_property(TARGET upx PROPERTY CXX_STANDARD 17)
target_link_libraries(upx upx_vendor_ucl upx_vendor_zlib) target_link_libraries(upx upx_vendor_ucl upx_vendor_zlib)
if(NOT MSVC) #***********************************************************************
# rather strict default compilation warnings # compilation flags
set(warn_strict #***********************************************************************
-Wall -Wextra -Wcast-align -Wcast-qual -Wmissing-declarations
-Wpointer-arith -Wshadow -Wvla -Wwrite-strings if(UPX_CONFIG_DISABLE_WSTRICT)
) # enable all basic warnings
set(warn_Wall -Wall)
set(warn_WN -W3)
else()
# enable lots of strict warnings
set(warn_Wall -Wall -Wextra -Wcast-align -Wcast-qual -Wmissing-declarations -Wpointer-arith -Wshadow -Wvla -Wwrite-strings)
set(warn_WN -W4)
endif() endif()
if(UPX_CONFIG_DISABLE_WERROR) if(UPX_CONFIG_DISABLE_WERROR)
set(warn_Werror "") set(warn_Werror "")
@ -159,7 +166,7 @@ if(MSVC)
add_definitions(-Zc:__cplusplus -Zc:preprocessor) add_definitions(-Zc:__cplusplus -Zc:preprocessor)
else() else()
# protect against security threats caused by misguided compiler "optimizations" # protect against security threats caused by misguided compiler "optimizations"
if (CMAKE_C_COMPILER_ID STREQUAL "GNU") if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
add_definitions(-fno-delete-null-pointer-checks -fno-lifetime-dse) add_definitions(-fno-delete-null-pointer-checks -fno-lifetime-dse)
endif() endif()
add_definitions(-fno-strict-aliasing -fno-strict-overflow -funsigned-char) add_definitions(-fno-strict-aliasing -fno-strict-overflow -funsigned-char)
@ -167,7 +174,7 @@ else()
add_definitions(-fno-tree-vectorize) add_definitions(-fno-tree-vectorize)
endif() endif()
# compile a target with -O2 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
@ -195,9 +202,9 @@ target_include_directories(${t} PRIVATE vendor/ucl/include vendor/ucl)
upx_compile_target_debug_with_O2(${t}) upx_compile_target_debug_with_O2(${t})
upx_sanitize_target(${t}) upx_sanitize_target(${t})
if(MSVC) if(MSVC)
target_compile_options(${t} PRIVATE -J -W4 ${warn_WX}) target_compile_options(${t} PRIVATE -J ${warn_WN} ${warn_WX})
else() else()
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror}) target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
endif() endif()
set(t upx_vendor_zlib) set(t upx_vendor_zlib)
@ -208,7 +215,8 @@ if(MSVC)
else() else()
target_compile_options(${t} PRIVATE -DHAVE_STDARG_H -DHAVE_UNISTD_H -DHAVE_VSNPRINTF) target_compile_options(${t} PRIVATE -DHAVE_STDARG_H -DHAVE_UNISTD_H -DHAVE_VSNPRINTF)
# clang-15: -Wno-strict-prototypes is needed to silence the new -Wdeprecated-non-prototype warning # clang-15: -Wno-strict-prototypes is needed to silence the new -Wdeprecated-non-prototype warning
target_compile_options(${t} PRIVATE -Wall -Wextra -Wvla -Wno-strict-prototypes ${warn_Werror}) target_compile_options(${t} PRIVATE -Wall -Wno-strict-prototypes ${warn_Werror})
##target_compile_options(${t} PRIVATE ${warn_Wall} -Wno-cast-align -Wno-cast-qual -Wno-strict-prototypes ${warn_Werror})
endif() endif()
if(NOT UPX_CONFIG_DISABLE_ZSTD) if(NOT UPX_CONFIG_DISABLE_ZSTD)
@ -217,9 +225,9 @@ upx_compile_target_debug_with_O2(${t})
upx_sanitize_target(${t}) upx_sanitize_target(${t})
target_compile_options(${t} PRIVATE -DDYNAMIC_BMI2=0 -DZSTD_DISABLE_ASM) target_compile_options(${t} PRIVATE -DDYNAMIC_BMI2=0 -DZSTD_DISABLE_ASM)
if(MSVC) if(MSVC)
target_compile_options(${t} PRIVATE -J -W4 ${warn_WX}) target_compile_options(${t} PRIVATE -J ${warn_WN} ${warn_WX})
else() else()
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror}) target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
endif() endif()
endif() endif()
@ -232,12 +240,18 @@ if(GITREV_SHORT)
target_compile_definitions(${t} PRIVATE UPX_VERSION_GIT_DESCRIBE="${GIT_DESCRIBE}") target_compile_definitions(${t} PRIVATE UPX_VERSION_GIT_DESCRIBE="${GIT_DESCRIBE}")
endif() endif()
endif() endif()
if(UPX_CONFIG_DISABLE_WSTRICT)
target_compile_definitions(${t} PRIVATE UPX_CONFIG_DISABLE_WSTRICT=1)
endif()
if(UPX_CONFIG_DISABLE_WERROR)
target_compile_definitions(${t} PRIVATE UPX_CONFIG_DISABLE_WERROR=1)
endif()
#upx_compile_target_debug_with_O2(${t}) #upx_compile_target_debug_with_O2(${t})
upx_sanitize_target(${t}) upx_sanitize_target(${t})
if(MSVC) if(MSVC)
target_compile_options(${t} PRIVATE -EHsc -J -W4 ${warn_WX}) target_compile_options(${t} PRIVATE -EHsc -J ${warn_WN} ${warn_WX})
else() else()
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror}) target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
endif() endif()
if(NOT UPX_CONFIG_DISABLE_ZSTD) if(NOT UPX_CONFIG_DISABLE_ZSTD)
target_compile_definitions(${t} PRIVATE WITH_ZSTD=1) target_compile_definitions(${t} PRIVATE WITH_ZSTD=1)
@ -302,7 +316,7 @@ endif()
if(CMAKE_INSTALL_PREFIX AND DEFINED CMAKE_INSTALL_FULL_BINDIR) if(CMAKE_INSTALL_PREFIX AND DEFINED CMAKE_INSTALL_FULL_BINDIR)
install(TARGETS upx DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") install(TARGETS upx DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}")
install(FILES install(FILES
COPYING LICENSE NEWS README THANKS doc/upx-doc.html doc/upx-doc.txt COPYING LICENSE NEWS.md README THANKS doc/upx-doc.html doc/upx-doc.txt
DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}" DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}"
) )
install(FILES doc/upx.1 DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man1") install(FILES doc/upx.1 DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man1")
@ -332,7 +346,7 @@ print_var(CMAKE_C_COMPILER_ID CMAKE_C_COMPILER_VERSION CMAKE_C_COMPILER_ARCHITEC
print_var(CMAKE_CXX_COMPILER_ID CMAKE_CXX_COMPILER_VERSION CMAKE_CXX_COMPILER_ARCHITECTURE_ID CMAKE_CXX_PLATFORM_ID CMAKE_CXX_COMPILER_ABI) print_var(CMAKE_CXX_COMPILER_ID CMAKE_CXX_COMPILER_VERSION CMAKE_CXX_COMPILER_ARCHITECTURE_ID CMAKE_CXX_PLATFORM_ID CMAKE_CXX_COMPILER_ABI)
endif() # UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO endif() # UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO
print_var(CMAKE_INSTALL_PREFIX CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE) print_var(CMAKE_INSTALL_PREFIX CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE)
if (CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release)$") if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release)$")
message(WARNING "WARNING: unsupported CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}; please use \"Debug\" or \"Release\"") message(WARNING "WARNING: unsupported CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}; please use \"Debug\" or \"Release\"")
endif() endif()

View File

@ -128,14 +128,14 @@ build/extra/cross-linux-arm/%: export CXX = arm-linux-gnueabihf-g++ -Wno-psabi
# cross compiler: Windows x86 win32 MinGW # cross compiler: Windows x86 win32 MinGW
build/extra/cross-windows-mingw32/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/cross-windows-mingw32/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/cross-windows-mingw32/release: PHONY; $(call run_config_and_build,$@,Release) build/extra/cross-windows-mingw32/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/cross-windows-mingw32/%: export CC = i686-w64-mingw32-gcc build/extra/cross-windows-mingw32/%: export CC = i686-w64-mingw32-gcc -static
build/extra/cross-windows-mingw32/%: export CXX = i686-w64-mingw32-g++ build/extra/cross-windows-mingw32/%: export CXX = i686-w64-mingw32-g++ -static
# cross compiler: Windows x64 win64 MinGW # cross compiler: Windows x64 win64 MinGW
build/extra/cross-windows-mingw64/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/cross-windows-mingw64/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/cross-windows-mingw64/release: PHONY; $(call run_config_and_build,$@,Release) build/extra/cross-windows-mingw64/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/cross-windows-mingw64/%: export CC = x86_64-w64-mingw32-gcc build/extra/cross-windows-mingw64/%: export CC = x86_64-w64-mingw32-gcc -static
build/extra/cross-windows-mingw64/%: export CXX = x86_64-w64-mingw32-g++ build/extra/cross-windows-mingw64/%: export CXX = x86_64-w64-mingw32-g++ -static
# cross compiler: macOS arm64 # cross compiler: macOS arm64
build/extra/cross-darwin-arm64/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/cross-darwin-arm64/debug: PHONY; $(call run_config_and_build,$@,Debug)

View File

@ -1,5 +1,5 @@
================================================================== ==================================================================
User visible changes for UPX ### User visible changes for UPX
================================================================== ==================================================================
Changes in 4.0.3 (XX XXX 2023): Changes in 4.0.3 (XX XXX 2023):
@ -78,7 +78,7 @@ Changes in 3.08 (12 Dec 2011):
* Compress shared library on ELF i386 only [ld.so threatens even this case]. * Compress shared library on ELF i386 only [ld.so threatens even this case].
* Attempt to support ELF on QNX 6.3.0 for armel (experimental). * Attempt to support ELF on QNX 6.3.0 for armel (experimental).
* Better diagnostic when ELF -fPIC is needed. * Better diagnostic when ELF -fPIC is needed.
* PT_NOTE improvements for *BSD. * PT_NOTE improvements for BSD.
* Preserve more ELF .e_flags on ARM. * Preserve more ELF .e_flags on ARM.
* Minor code improvements for ELF stubs. * Minor code improvements for ELF stubs.
* Defend against another flavor of corrupt PE header. * Defend against another flavor of corrupt PE header.
@ -258,7 +258,7 @@ Changes in 1.11 beta (20 Dec 2000):
================================================================== ==================================================================
Changes in 1.25 (29 Jun 2004) Changes in 1.25 (29 Jun 2004)
* INFO: http://upx.sourceforge.net is the permanent UPX home page * INFO: http://upx.sourceforge.net is the new UPX home page
* watcom/le: don't crash on files without relocations * watcom/le: don't crash on files without relocations
* win32/pe: stricter checks of some PE values * win32/pe: stricter checks of some PE values
* source code: much improved portability using ACC, the * source code: much improved portability using ACC, the
@ -539,6 +539,3 @@ Changes in 0.20 (05 Jul 1998)
Changes in 0.05 (26 May 1998) Changes in 0.05 (26 May 1998)
* first public beta release * first public beta release
# vim:set syntax=off tw=0 ts=4 sw=4 et: -*- coding: utf-8 -*-

View File

@ -133,7 +133,7 @@
.\" ======================================================================== .\" ========================================================================
.\" .\"
.IX Title "UPX 1" .IX Title "UPX 1"
.TH UPX 1 "2023-01-30" "upx 4.0.3" " " .TH UPX 1 "2023-02-05" "upx 4.0.3" " "
.\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents. .\" way too many mistakes in technical documents.
.if n .ad l .if n .ad l

View File

@ -6,10 +6,10 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile # create the image from Dockerfile
# using a rootless Podman container # using a rootless Podman container
# NOTE: this image is based on rebuild-stubs-with-podman/upx-stubtools-20221212-v4, # NOTE: this image is based on rebuild-stubs-with-podman/upx-stubtools-20221212-v5,
# so you have to create that image first # so you have to create that image first
# WARNING: we install many packages, so the resulting image needs A LOT of disk space! # WARNING: we install many packages, so the resulting image needs A LOT of disk space!
image=upx-cross-compile-20230115-v2 image=upx-cross-compile-20230115-v3
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir" podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# run an interactive shell in the image # run an interactive shell in the image
# using a rootless Podman container # using a rootless Podman container
image=upx-cross-compile-20230115-v2 image=upx-cross-compile-20230115-v3
flags=( -ti --read-only --rm ) flags=( -ti --read-only --rm )
flags+=( --cap-drop=all ) # drop all capabilities flags+=( --cap-drop=all ) # drop all capabilities
@ -44,10 +44,11 @@ podman run "${flags[@]}" "$image" bash -l
# and lots of other cross-compilers are installed; see "ls /usr/bin/*g++*" # and lots of other cross-compilers are installed; see "ls /usr/bin/*g++*"
# and finally see misc/cross-compile-upx-with-podman/build-all-inside-container.sh # and finally see
# ./misc/cross-compile-upx-with-podman/build-all-inside-container.sh
# after running that script we can do cool things like: # after running that script we can do cool things like:
# cd /home/upx/src/upx/build/cross-compile-upx-with-podman/alpha-linux-gnu/debug # cd /home/upx/src/upx/build/cross-compile-upx-with-podman/alpha-linux-gnu/debug
# qemu-alpha -L /usr/alpha-linux-gnu upx --version # qemu-alpha -L /usr/alpha-linux-gnu ./upx --version
# cd /home/upx/src/upx/build/cross-compile-upx-with-podman/hppa-linux-gnu/debug # cd /home/upx/src/upx/build/cross-compile-upx-with-podman/hppa-linux-gnu/debug
# qemu-hppa -L /usr/hppa-linux-gnu upx --version # qemu-hppa -L /usr/hppa-linux-gnu ./upx --version
# (similar for many other architectures/builds) # (similar for many other architectures/builds)

View File

@ -1,8 +1,8 @@
# NOTE: this image is based on rebuild-stubs-with-podman/upx-stubtools-20221212-v4, # NOTE: this image is based on rebuild-stubs-with-podman/upx-stubtools-20221212-v5,
# so you have to create that image first # so you have to create that image first
# WARNING: we install many packages, so the resulting image needs A LOT of disk space! # WARNING: we install many packages, so the resulting image needs A LOT of disk space!
FROM localhost/upx-stubtools-20221212-v4 FROM localhost/upx-stubtools-20221212-v5
ENV UPX_CONTAINER_IMAGE_NAME=upx-cross-compile-20230115-v2 ENV UPX_CONTAINER_IMAGE_NAME=upx-cross-compile-20230115-v3
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
USER root USER root

View File

@ -27,9 +27,13 @@ function run_config_and_build {
# these old architectures do not support sanitize # these old architectures do not support sanitize
alpha-linux-gnu) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;; alpha-linux-gnu) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;;
hppa-linux-gnu) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;; hppa-linux-gnu) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;;
# avoid link errors with current MinGW-w64 versions # avoid sanitize link errors with current MinGW-w64 versions; link libstdc++ statically
i686-w64-mingw32) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;; i686-w64-mingw32)
x86_64-w64-mingw32) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;; cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON
CC="$CC -static"; CXX="$CXX -static" ;;
x86_64-w64-mingw32)
cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON
CC="$CC -static"; CXX="$CXX -static" ;;
# avoid warnings about arm libstdc++ ABI change in gcc-7 # avoid warnings about arm libstdc++ ABI change in gcc-7
arm-linux-*) CXX="$CXX -Wno-psabi" ;; arm-linux-*) CXX="$CXX -Wno-psabi" ;;
esac esac

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile # create the image from Dockerfile
# using a rootless Podman container # using a rootless Podman container
image=upx-stubtools-20221212-v4 image=upx-stubtools-20221212-v5
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir" podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# run an interactive shell in the image # run an interactive shell in the image
# using a rootless Podman container # using a rootless Podman container
image=upx-stubtools-20221212-v4 image=upx-stubtools-20221212-v5
flags=( -ti --read-only --rm ) flags=( -ti --read-only --rm )
flags+=( --cap-drop=all ) # drop all capabilities flags+=( --cap-drop=all ) # drop all capabilities

View File

@ -1,5 +1,5 @@
FROM docker.io/library/ubuntu:22.04 FROM docker.io/library/ubuntu:22.04
ENV UPX_CONTAINER_IMAGE_NAME=upx-stubtools-20221212-v4 ENV UPX_CONTAINER_IMAGE_NAME=upx-stubtools-20221212-v5
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
ENV LANG=C.UTF-8 ENV LANG=C.UTF-8
@ -7,17 +7,18 @@ ENV LANG=C.UTF-8
RUN dpkg --add-architecture i386 \ RUN dpkg --add-architecture i386 \
&& apt-get update && apt-get upgrade -y \ && apt-get update && apt-get upgrade -y \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
aria2 ca-certificates git less libmpc3 libncurses5 make \ aria2 bash ca-certificates git less libmpc3 libncurses5 make \
ncurses-term perl-base python2-minimal wget xz-utils \ ncurses-term perl-base python2-minimal wget xz-utils \
libc6:i386 zlib1g:i386 \ libc6:i386 zlib1g:i386 \
# the following packages are not required for rebuilding the stubs, but # the following packages are not required for rebuilding the stubs, but
# they do make the image much more convenient and also allow building # they do make the image much more convenient and also allow building
# the full UPX binary inside the container via CMake: # the full UPX binary inside the container via CMake:
7zip bfs bzip2 cmake curl elfutils fd-find file fzf g++ gdb gojq htop hyperfine \ 7zip bfs bzip2 chrpath cmake cpio curl elfutils fd-find file fzf g++ gdb gojq \
jq libzstd-dev lsb-release lzip lzop ninja-build p7zip patch patchelf pax-utils \ ht htop hyperfine jq libzstd-dev lsb-release lz4 lzip lzop moreutils ninja-build \
ripgrep rsync screen universal-ctags unzip vim zip zlib1g-dev zsh zstd \ p7zip patch patchelf parallel pax-utils paxctl re2c ripgrep rsync \
screen universal-ctags unzip vim zip zlib1g-dev zsh zstd \
# extra packages for compiling with "gcc -m32" and and "gcc -mx32": # extra packages for compiling with "gcc -m32" and and "gcc -mx32":
gcc-multilib g++-multilib \ g++-multilib gcc-multilib \
&& true && true
# manually install compat libs from Ubuntu 16.04; REQUIRED # manually install compat libs from Ubuntu 16.04; REQUIRED

View File

@ -80,8 +80,8 @@ endif
ifeq ($(shell uname),Linux) ifeq ($(shell uname),Linux)
# Markus loves clang-format, but John hates it; find a compromise # Markus loves clang-format, but John hates it; find a compromise
CLANG_FORMAT_EXCLUDE_FILES += conf.h miniacc.h version.h help.cpp CLANG_FORMAT_EXCLUDE_FILES += conf.h miniacc.h version.h help.cpp
CLANG_FORMAT_EXCLUDE_FILES += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmli% CLANG_FORMAT_EXCLUDE_FILES += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmlin%
CLANG_FORMAT_EXCLUDE_FILES += packer_c.cpp packer_f.cpp CLANG_FORMAT_EXCLUDE_FILES += packer_c.cpp
CLANG_FORMAT_EXCLUDE_FILES += compress/compress.h filter/filter_impl.cpp CLANG_FORMAT_EXCLUDE_FILES += compress/compress.h filter/filter_impl.cpp
CLANG_FORMAT_FILES := $(sort $(wildcard *.[ch]* ../maint/src/*.[ch]* [cu]*/*.[ch]*)) CLANG_FORMAT_FILES := $(sort $(wildcard *.[ch]* ../maint/src/*.[ch]* [cu]*/*.[ch]*))
CLANG_FORMAT_FILES := $(filter-out $(CLANG_FORMAT_EXCLUDE_FILES),$(CLANG_FORMAT_FILES)) CLANG_FORMAT_FILES := $(filter-out $(CLANG_FORMAT_EXCLUDE_FILES),$(CLANG_FORMAT_FILES))

View File

@ -76,28 +76,32 @@ ACC_COMPILE_TIME_ASSERT_HEADER((-1) >> 31 == -1) // arithmetic right shift
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255) // -funsigned-char ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255) // -funsigned-char
ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
// enable/disable some warnings // enable some more strict warnings for Git developer builds
#if !UPX_CONFIG_DISABLE_WSTRICT && !UPX_CONFIG_DISABLE_WERROR
#if (ACC_CC_CLANG >= 0x0b0000) #if (ACC_CC_CLANG >= 0x0b0000)
# pragma clang diagnostic error "-Wsuggest-override" # pragma clang diagnostic error "-Wsuggest-override"
#elif (ACC_CC_GNUC >= 0x0a0000) #elif (ACC_CC_GNUC >= 0x0a0000)
// don't enable before gcc-10 because of gcc bug #78010 // don't enable before gcc-10 because of gcc bug #78010
# pragma GCC diagnostic error "-Wsuggest-override" # pragma GCC diagnostic error "-Wsuggest-override"
#endif #endif
#if (ACC_CC_CLANG >= 0x050000)
# pragma clang diagnostic error "-Wzero-as-null-pointer-constant"
#elif (ACC_CC_GNUC >= 0x040700) && defined(__GLIBC__)
// Some non-GLIBC toolchains do not use 'nullptr' everywhere when C++: // Some non-GLIBC toolchains do not use 'nullptr' everywhere when C++:
// openwrt-sdk-x86-64_gcc-11.2.0_musl.Linux-x86_64/staging_dir/ // openwrt-sdk-x86-64_gcc-11.2.0_musl.Linux-x86_64/staging_dir/
// toolchain-x86_64_gcc-11.2.0_musl/include/fortify/stdlib.h: // toolchain-x86_64_gcc-11.2.0_musl/include/fortify/stdlib.h:
// 51:32: error: zero as null pointer constant // 51:32: error: zero as null pointer constant
#if (ACC_CC_CLANG >= 0x050000)
# pragma clang diagnostic error "-Wzero-as-null-pointer-constant"
#elif (ACC_CC_GNUC >= 0x040700) && defined(__GLIBC__)
# pragma GCC diagnostic error "-Wzero-as-null-pointer-constant" # pragma GCC diagnostic error "-Wzero-as-null-pointer-constant"
#endif #endif
#if (ACC_CC_MSC) #if (ACC_CC_MSC)
# pragma warning(error: 4127) # pragma warning(error: 4127)
# pragma warning(error: 4146) # pragma warning(error: 4146)
# pragma warning(error: 4319) # pragma warning(error: 4319)
# pragma warning(error: 4805) # pragma warning(error: 4805)
#endif
#endif // !UPX_CONFIG_DISABLE_WSTRICT && !UPX_CONFIG_DISABLE_WERROR
// disable some warnings
#if (ACC_CC_MSC)
# pragma warning(disable: 4244) // -Wconversion # pragma warning(disable: 4244) // -Wconversion
# pragma warning(disable: 4267) // -Wconversion # pragma warning(disable: 4267) // -Wconversion
# pragma warning(disable: 4820) // padding added after data member # pragma warning(disable: 4820) // padding added after data member
@ -124,9 +128,17 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
// UPX currently does not use multithreading // UPX currently does not use multithreading
#define upx_std_atomic(Type) Type #define upx_std_atomic(Type) Type
//#define upx_std_atomic(Type) typename std::add_volatile<Type>::type //#define upx_std_atomic(Type) typename std::add_volatile<Type>::type
#define upx_std_once_flag upx_std_atomic(size_t)
template <class NoexceptCallable>
inline void upx_std_call_once(upx_std_once_flag &flag, NoexceptCallable &&f) {
if (!flag) { flag = 1; f(); }
}
#else #else
#include <atomic> #include <atomic>
#define upx_std_atomic(Type) std::atomic<Type> #define upx_std_atomic(Type) std::atomic<Type>
#include <mutex>
#define upx_std_once_flag std::once_flag
#define upx_std_call_once std::call_once
#endif #endif
// C++ submodule headers // C++ submodule headers
@ -416,7 +428,7 @@ inline const T& UPX_MIN(const T& a, const T& b) { if (a < b) return a; return b;
template <size_t TypeSize> template <size_t TypeSize>
struct USizeOfTypeImpl { struct USizeOfTypeImpl {
static forceinline constexpr unsigned value() { static forceinline constexpr unsigned value() {
COMPILE_TIME_ASSERT(TypeSize >= 1 && TypeSize <= 64 * 1024); // arbitrary limit COMPILE_TIME_ASSERT(TypeSize >= 1 && TypeSize <= 64 * 1024) // arbitrary limit
return ACC_ICONV(unsigned, TypeSize); return ACC_ICONV(unsigned, TypeSize);
} }
}; };

View File

@ -31,7 +31,7 @@
// //
**************************************************************************/ **************************************************************************/
unsigned long Throwable::counter = 0; /*static*/ upx_std_atomic(size_t) Throwable::debug_counter;
Throwable::Throwable(const char *m, int e, bool w) noexcept : super(), Throwable::Throwable(const char *m, int e, bool w) noexcept : super(),
msg(nullptr), msg(nullptr),
@ -40,8 +40,8 @@ Throwable::Throwable(const char *m, int e, bool w) noexcept : super(),
if (m) if (m)
msg = strdup(m); msg = strdup(m);
#if 0 #if 0
fprintf(stderr, "construct exception: %s %lu\n", msg, counter); fprintf(stderr, "construct exception: %s %zu\n", msg, debug_counter);
counter++; debug_counter += 1;
#endif #endif
} }
@ -52,15 +52,15 @@ Throwable::Throwable(const Throwable &other) noexcept : super(other),
if (other.msg) if (other.msg)
msg = strdup(other.msg); msg = strdup(other.msg);
#if 0 #if 0
fprintf(stderr, "copy exception: %s %lu\n", msg, counter); fprintf(stderr, "copy exception: %s %zu\n", msg, debug_counter);
counter++; debug_counter += 1;
#endif #endif
} }
Throwable::~Throwable() noexcept { Throwable::~Throwable() noexcept {
#if 0 #if 0
counter--; debug_counter -= 1;
fprintf(stderr, "destruct exception: %s %lu\n", msg, counter); fprintf(stderr, "destruct exception: %s %zu\n", msg, debug_counter);
#endif #endif
if (msg) if (msg)
free(msg); free(msg);

View File

@ -29,8 +29,6 @@
#ifndef UPX_EXCEPT_H__ #ifndef UPX_EXCEPT_H__
#define UPX_EXCEPT_H__ 1 #define UPX_EXCEPT_H__ 1
#ifdef __cplusplus
const char *prettyName(const char *n) noexcept; const char *prettyName(const char *n) noexcept;
/************************************************************************* /*************************************************************************
@ -64,7 +62,7 @@ private:
ACC_CXX_DISABLE_NEW_DELETE ACC_CXX_DISABLE_NEW_DELETE
private: private:
static unsigned long counter; // for debugging static upx_std_atomic(size_t) debug_counter; // for debugging
}; };
// Exceptions can/should be caught // Exceptions can/should be caught
@ -217,8 +215,6 @@ NORET void throwEOFException(const char *msg = nullptr, int e = 0);
#undef NORET #undef NORET
#endif /* __cplusplus */
#endif /* already included */ #endif /* already included */
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -45,11 +45,11 @@ static void initFilter(Filter *f, upx_byte *buf, unsigned buf_len) {
**************************************************************************/ **************************************************************************/
const FilterImpl::FilterEntry *FilterImpl::getFilter(int id) { const FilterImpl::FilterEntry *FilterImpl::getFilter(int id) {
static bool done = false;
static unsigned char filter_map[256]; static unsigned char filter_map[256];
static upx_std_once_flag init_done;
if (!done) { upx_std_call_once(init_done, []() noexcept {
// init the filter_map[] // init the filter_map[] (using a lambda function)
assert(n_filters <= 254); // as 0xff means "empty slot" assert(n_filters <= 254); // as 0xff means "empty slot"
memset(filter_map, 0xff, sizeof(filter_map)); memset(filter_map, 0xff, sizeof(filter_map));
for (int i = 0; i < n_filters; i++) { for (int i = 0; i < n_filters; i++) {
@ -58,8 +58,7 @@ const FilterImpl::FilterEntry *FilterImpl::getFilter(int id) {
assert(filter_map[filter_id] == 0xff); assert(filter_map[filter_id] == 0xff);
filter_map[filter_id] = (unsigned char) i; filter_map[filter_id] = (unsigned char) i;
} }
done = true; });
}
if (id < 0 || id > 255) if (id < 0 || id > 255)
return nullptr; return nullptr;
@ -103,7 +102,8 @@ void Filter::init(int id_, unsigned addvalue_) {
this->n_mru = 0; this->n_mru = 0;
} }
bool Filter::filter(upx_byte *buf_, unsigned buf_len_) { bool Filter::filter(SPAN_0(upx_byte) xbuf, unsigned buf_len_) {
upx_byte *const buf_ = raw_bytes(xbuf, buf_len_);
initFilter(this, buf_, buf_len_); initFilter(this, buf_, buf_len_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id); const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
@ -134,7 +134,8 @@ bool Filter::filter(upx_byte *buf_, unsigned buf_len_) {
return false; return false;
} }
void Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum) { void Filter::unfilter(SPAN_0(upx_byte) xbuf, unsigned buf_len_, bool verify_checksum) {
upx_byte *const buf_ = raw_bytes(xbuf, buf_len_);
initFilter(this, buf_, buf_len_); initFilter(this, buf_, buf_len_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id); const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
@ -178,10 +179,11 @@ void Filter::verifyUnfilter() {
unfilter(this->buf, this->buf_len, true); unfilter(this->buf, this->buf_len, true);
} }
bool Filter::scan(const upx_byte *buf_, unsigned buf_len_) { bool Filter::scan(SPAN_0(const upx_byte) xbuf, unsigned buf_len_) {
const upx_byte *const buf_ = raw_bytes(xbuf, buf_len_);
// Note: must use const_cast here. This is fine as the scan // Note: must use const_cast here. This is fine as the scan
// implementations (fe->do_scan) actually don't change the buffer. // implementations (fe->do_scan) actually don't change the buffer.
upx_byte *b = const_cast<upx_byte *>(buf_); upx_byte *const b = const_cast<upx_byte *>(buf_);
initFilter(this, b, buf_len_); initFilter(this, b, buf_len_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id); const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);

View File

@ -54,10 +54,10 @@ public:
} }
void init(int id = 0, unsigned addvalue = 0); void init(int id = 0, unsigned addvalue = 0);
bool filter(upx_byte *buf, unsigned buf_len); bool filter(SPAN_0(upx_byte) buf, unsigned buf_len);
void unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum = false); void unfilter(SPAN_0(upx_byte) buf, unsigned buf_len, bool verify_checksum = false);
void verifyUnfilter(); void verifyUnfilter();
bool scan(const upx_byte *buf, unsigned buf_len); bool scan(SPAN_0(const upx_byte) buf, unsigned buf_len);
static bool isValidFilter(int filter_id); static bool isValidFilter(int filter_id);
static bool isValidFilter(int filter_id, const int *allowed_filters); static bool isValidFilter(int filter_id, const int *allowed_filters);

View File

@ -168,7 +168,7 @@ umin(unsigned const a, unsigned const b)
// database for use in class Filter // database for use in class Filter
**************************************************************************/ **************************************************************************/
const FilterImpl::FilterEntry FilterImpl::filters[] = { /*static*/ const FilterImpl::FilterEntry FilterImpl::filters[] = {
// no filter // no filter
{ 0x00, 0, 0, nullptr, nullptr, nullptr }, { 0x00, 0, 0, nullptr, nullptr, nullptr },
@ -261,6 +261,6 @@ const FilterImpl::FilterEntry FilterImpl::filters[] = {
{ 0xd0, 8, 0, f_ppcbxx, u_ppcbxx, s_ppcbxx }, { 0xd0, 8, 0, f_ppcbxx, u_ppcbxx, s_ppcbxx },
}; };
const int FilterImpl::n_filters = TABLESIZE(filters); /*static*/ const int FilterImpl::n_filters = TABLESIZE(filters);
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -46,6 +46,8 @@ PackArmPe::PackArmPe(InputFile *f) : super(f) {}
PackArmPe::~PackArmPe() {} PackArmPe::~PackArmPe() {}
Linker *PackArmPe::newLinker() const { return new ElfLinkerArmLE; }
const int *PackArmPe::getCompressionMethods(int method, int level) const { const int *PackArmPe::getCompressionMethods(int method, int level) const {
static const int m_all[] = {M_NRV2B_8, M_NRV2E_8, M_LZMA, M_END}; static const int m_all[] = {M_NRV2B_8, M_NRV2E_8, M_LZMA, M_END};
static const int m_lzma[] = {M_LZMA, M_END}; static const int m_lzma[] = {M_LZMA, M_END};
@ -71,8 +73,6 @@ const int *PackArmPe::getFilters() const {
return filters; return filters;
} }
Linker *PackArmPe::newLinker() const { return new ElfLinkerArmLE; }
/************************************************************************* /*************************************************************************
// import handling // import handling
**************************************************************************/ **************************************************************************/
@ -127,37 +127,37 @@ void PackArmPe::buildLoader(const Filter *ft) {
initLoader(loader, size); initLoader(loader, size);
if (isdll) if (isdll)
addLoader("DllStart", nullptr); addLoader("DllStart");
addLoader("ExeStart", nullptr); addLoader("ExeStart");
if (ph.method == M_NRV2E_8) if (ph.method == M_NRV2E_8)
addLoader("Call2E", nullptr); addLoader("Call2E");
else if (ph.method == M_NRV2B_8) else if (ph.method == M_NRV2B_8)
addLoader("Call2B", nullptr); addLoader("Call2B");
else if (ph.method == M_NRV2D_8) else if (ph.method == M_NRV2D_8)
addLoader("Call2D", nullptr); addLoader("Call2D");
else if (M_IS_LZMA(ph.method)) else if (M_IS_LZMA(ph.method))
addLoader("+40C,CallLZMA", nullptr); addLoader("+40C,CallLZMA");
if (ft->id == 0x50) if (ft->id == 0x50)
addLoader("+40C,Unfilter_0x50", nullptr); addLoader("+40C,Unfilter_0x50");
if (sorelocs) if (sorelocs)
addLoader("+40C,Relocs", nullptr); addLoader("+40C,Relocs");
addLoader("+40C,Imports", nullptr); addLoader("+40C,Imports");
addLoader("ProcessEnd", nullptr); addLoader("ProcessEnd");
if (ph.method == M_NRV2E_8) if (ph.method == M_NRV2E_8)
addLoader(".ucl_nrv2e_decompress_8", nullptr); addLoader(".ucl_nrv2e_decompress_8");
else if (ph.method == M_NRV2B_8) else if (ph.method == M_NRV2B_8)
addLoader(".ucl_nrv2b_decompress_8", nullptr); addLoader(".ucl_nrv2b_decompress_8");
else if (ph.method == M_NRV2D_8) else if (ph.method == M_NRV2D_8)
addLoader(".ucl_nrv2d_decompress_8", nullptr); addLoader(".ucl_nrv2d_decompress_8");
else if (M_IS_LZMA(ph.method)) else if (M_IS_LZMA(ph.method))
addLoader("+40C,LZMA_DECODE,LZMA_DEC10", nullptr); addLoader("+40C,LZMA_DECODE,LZMA_DEC10");
addLoader("IDENTSTR,UPX1HEAD", nullptr); addLoader("IDENTSTR,UPX1HEAD");
} }
bool PackArmPe::handleForceOption() { bool PackArmPe::handleForceOption() {

View File

@ -1,4 +1,4 @@
/* p_com.cpp -- /* p_com.cpp -- dos/com executable format
This file is part of the UPX executable compressor. This file is part of the UPX executable compressor.
@ -35,23 +35,21 @@
static const CLANG_FORMAT_DUMMY_STATEMENT static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/i086-dos16.com.h" #include "stub/i086-dos16.com.h"
// #define TESTING 1
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
Linker *PackCom::newLinker() const { return new ElfLinkerX86(); }
const int *PackCom::getCompressionMethods(int method, int level) const { const int *PackCom::getCompressionMethods(int method, int level) const {
static const int m_nrv2b[] = {M_NRV2B_LE16, M_END}; static const int m_nrv2b[] = {M_NRV2B_LE16, M_END};
#if 0
static const int m_nrv2d[] = { M_NRV2D_LE16, M_END };
#endif
UNUSED(method); UNUSED(method);
UNUSED(level); UNUSED(level);
return m_nrv2b; return m_nrv2b;
} }
const int *PackCom::getFilters() const { const int *PackCom::getFilters() const {
// see class FilterImpl
static const int filters[] = {0x06, 0x03, 0x04, 0x01, 0x05, 0x02, FT_END}; static const int filters[] = {0x06, 0x03, 0x04, 0x01, 0x05, 0x02, FT_END};
return filters; return filters;
} }
@ -64,16 +62,17 @@ bool PackCom::canPack() {
unsigned char buf[128]; unsigned char buf[128];
fi->readx(buf, sizeof(buf)); fi->readx(buf, sizeof(buf));
if (memcmp(buf, "MZ", 2) == 0 || memcmp(buf, "ZM", 2) == 0 // .exe if (memcmp(buf, "MZ", 2) == 0 || memcmp(buf, "ZM", 2) == 0) // .exe
|| memcmp(buf, "\xff\xff\xff\xff", 4) == 0) // .sys
return false; return false;
if (!fn_has_ext(fi->getName(), "com")) if (memcmp(buf, "\xff\xff\xff\xff", 4) == 0) // .sys
return false;
if (!fn_has_ext(fi->getName(), "com")) // query file name
return false; return false;
checkAlreadyPacked(buf, sizeof(buf)); checkAlreadyPacked(buf, sizeof(buf));
if (file_size < 1024) if (file_size < 1024)
throwCantPack("file is too small"); throwCantPack("file is too small for dos/com");
if (file_size > 0xFF00) if (file_size > 0xFF00)
throwCantPack("file is too big for dos/com"); throwCantPack("file is too large for dos/com");
return true; return true;
} }
@ -81,6 +80,49 @@ bool PackCom::canPack() {
// //
**************************************************************************/ **************************************************************************/
void PackCom::addFilter16(int filter_id) {
assert(filter_id > 0);
assert(isValidFilter(filter_id));
if (filter_id % 3 == 0) {
// clang-format off
addLoader("CALLTR16",
filter_id < 4 ? "CT16SUB0" : "",
filter_id < 4 ? "" : (opt->cpu == opt->CPU_8086 ? "CT16I086" : "CT16I286,CT16SUB0"),
"CALLTRI2",
getFormat() == UPX_F_DOS_COM ? "CORETURN" : "");
// clang-format on
} else {
// clang-format off
addLoader(filter_id % 3 == 1 ? "CT16E800" : "CT16E900",
"CALLTRI5",
getFormat() == UPX_F_DOS_COM ? "CT16JEND" : "CT16JUL2",
filter_id < 4 ? "CT16SUB1" : "",
filter_id < 4 ? "" : (opt->cpu == opt->CPU_8086 ? "CT16I087" : "CT16I287,CT16SUB1"),
"CALLTRI6");
// clang-format on
}
}
void PackCom::buildLoader(const Filter *ft) {
initLoader(stub_i086_dos16_com, sizeof(stub_i086_dos16_com));
// clang-format off
addLoader("COMMAIN1",
ph.first_offset_found == 1 ? "COMSBBBP" : "",
"COMPSHDI",
ft->id ? "COMCALLT" : "",
"COMMAIN2,UPX1HEAD,COMCUTPO,NRV2B160",
ft->id ? "NRVDDONE" : "NRVDRETU",
"NRVDECO1",
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
"NRVDECO2");
// clang-format on
if (ft->id) {
assert(ft->calls > 0);
addFilter16(ft->id);
}
}
void PackCom::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned calls) { void PackCom::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned calls) {
const int e_len = getLoaderSectionStart("COMCUTPO"); const int e_len = getLoaderSectionStart("COMCUTPO");
const int d_len = lsize - e_len; const int d_len = lsize - e_len;
@ -92,7 +134,7 @@ void PackCom::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned
if (upper_end + stacksize > 0xfffe) if (upper_end + stacksize > 0xfffe)
stacksize = 0x56; stacksize = 0x56;
if (upper_end + stacksize > 0xfffe) if (upper_end + stacksize > 0xfffe)
throwCantPack("file is too big for dos/com"); throwCantPack("file is too large for dos/com");
linker->defineSymbol("calltrick_calls", calls); linker->defineSymbol("calltrick_calls", calls);
linker->defineSymbol("sp_limit", upper_end + stacksize); linker->defineSymbol("sp_limit", upper_end + stacksize);
@ -105,46 +147,15 @@ void PackCom::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned
relocateLoader(); relocateLoader();
loader = getLoader(); loader = getLoader();
// some day we could use the relocation stuff for patchPackHeader too // some day we could use the relocation stuff for patchPackHeader too..
patchPackHeader(loader, e_len); patchPackHeader(loader, e_len);
// write loader + compressed file // write loader + compressed file
fo->write(loader, e_len); // entry fo->write(loader, e_len); // entry
fo->write(obuf, ph.c_len); fo->write(obuf, ph.c_len); // compressed
fo->write(loader + e_len, d_len); // decompressor fo->write(loader + e_len, d_len); // decompressor
#if 0 NO_printf("%-13s: entry : %8u bytes\n", getName(), e_len);
printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len); NO_printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len); NO_printf("%-13s: decompressor : %8u bytes\n", getName(), d_len);
printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) d_len);
#endif
}
void PackCom::buildLoader(const Filter *ft) {
initLoader(stub_i086_dos16_com, sizeof(stub_i086_dos16_com));
addLoader("COMMAIN1", ph.first_offset_found == 1 ? "COMSBBBP" : "", "COMPSHDI",
ft->id ? "COMCALLT" : "", "COMMAIN2,UPX1HEAD,COMCUTPO,NRV2B160",
ft->id ? "NRVDDONE" : "NRVDRETU", "NRVDECO1",
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00", "NRVDECO2", nullptr);
if (ft->id) {
assert(ft->calls > 0);
addFilter16(ft->id);
}
}
void PackCom::addFilter16(int filter_id) {
assert(filter_id > 0);
assert(isValidFilter(filter_id));
if (filter_id % 3 == 0)
addLoader("CALLTR16", filter_id < 4 ? "CT16SUB0" : "",
filter_id < 4 ? ""
: (opt->cpu == opt->CPU_8086 ? "CT16I086" : "CT16I286,CT16SUB0"),
"CALLTRI2", getFormat() == UPX_F_DOS_COM ? "CORETURN" : "", nullptr);
else
addLoader(
filter_id % 3 == 1 ? "CT16E800" : "CT16E900", "CALLTRI5",
getFormat() == UPX_F_DOS_COM ? "CT16JEND" : "CT16JUL2", filter_id < 4 ? "CT16SUB1" : "",
filter_id < 4 ? "" : (opt->cpu == opt->CPU_8086 ? "CT16I087" : "CT16I287,CT16SUB1"),
"CALLTRI6", nullptr);
} }
/************************************************************************* /*************************************************************************
@ -187,7 +198,7 @@ void PackCom::pack(OutputFile *fo) {
**************************************************************************/ **************************************************************************/
int PackCom::canUnpack() { int PackCom::canUnpack() {
if (!readPackHeader(128)) if (!readPackHeader(128)) // read "ph"
return false; return false;
if (file_size_u <= ph.c_len) if (file_size_u <= ph.c_len)
return false; return false;
@ -224,6 +235,4 @@ void PackCom::unpack(OutputFile *fo) {
fo->write(obuf, ph.u_len); fo->write(obuf, ph.u_len);
} }
Linker *PackCom::newLinker() const { return new ElfLinkerX86(); }
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -1,4 +1,4 @@
/* p_com.h -- /* p_com.h -- dos/com executable format
This file is part of the UPX executable compressor. This file is part of the UPX executable compressor.
@ -52,13 +52,12 @@ public:
virtual int canUnpack() override; virtual int canUnpack() override;
protected: protected:
virtual unsigned getCallTrickOffset() const { return 0x100; }
virtual Linker *newLinker() const override; virtual Linker *newLinker() const override;
void addFilter16(int filter_id);
protected: // dos/sys will override these:
virtual unsigned getCallTrickOffset() const { return 0x100; }
virtual void buildLoader(const Filter *ft) override; virtual void buildLoader(const Filter *ft) override;
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned); virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned);
virtual void addFilter16(int filter_id);
}; };
#endif /* already included */ #endif /* already included */

View File

@ -54,6 +54,8 @@ PackDjgpp2::PackDjgpp2(InputFile *f) : super(f), coff_offset(0) {
// assert(upx_adler32(stubify_stub, sizeof(stubify_stub)) == STUBIFY_STUB_ADLER32); // assert(upx_adler32(stubify_stub, sizeof(stubify_stub)) == STUBIFY_STUB_ADLER32);
} }
Linker *PackDjgpp2::newLinker() const { return new ElfLinkerX86; }
const int *PackDjgpp2::getCompressionMethods(int method, int level) const { const int *PackDjgpp2::getCompressionMethods(int method, int level) const {
return Packer::getDefaultCompressionMethods_le32(method, level); return Packer::getDefaultCompressionMethods_le32(method, level);
} }
@ -71,21 +73,19 @@ unsigned PackDjgpp2::findOverlapOverhead(const upx_bytep buf, const upx_bytep tb
return o; return o;
} }
Linker *PackDjgpp2::newLinker() const { return new ElfLinkerX86; }
void PackDjgpp2::buildLoader(const Filter *ft) { void PackDjgpp2::buildLoader(const Filter *ft) {
// prepare loader // prepare loader
initLoader(stub_i386_dos32_djgpp2, sizeof(stub_i386_dos32_djgpp2)); initLoader(stub_i386_dos32_djgpp2, sizeof(stub_i386_dos32_djgpp2));
addLoader("IDENTSTR,DJ2MAIN1", ft->id ? "DJCALLT1" : "", addLoader("IDENTSTR,DJ2MAIN1", ft->id ? "DJCALLT1" : "",
ph.first_offset_found == 1 ? "DJ2MAIN2" : "", ph.first_offset_found == 1 ? "DJ2MAIN2" : "",
M_IS_LZMA(ph.method) ? "LZMA_INIT_STACK" : "", getDecompressorSections(), M_IS_LZMA(ph.method) ? "LZMA_INIT_STACK" : "", getDecompressorSections(),
M_IS_LZMA(ph.method) ? "LZMA_DONE_STACK" : "", "DJ2BSS00", nullptr); M_IS_LZMA(ph.method) ? "LZMA_DONE_STACK" : "", "DJ2BSS00");
if (ft->id) { if (ft->id) {
assert(ft->calls > 0); assert(ft->calls > 0);
addLoader("DJCALLT2", nullptr); addLoader("DJCALLT2");
addFilter32(ft->id); addFilter32(ft->id);
} }
addLoader("DJRETURN,+40C,UPX1HEAD", nullptr); addLoader("DJRETURN,+40C,UPX1HEAD");
} }
/************************************************************************* /*************************************************************************
@ -99,7 +99,7 @@ void PackDjgpp2::handleStub(OutputFile *fo) {
Packer::handleStub(fi, fo, coff_offset); Packer::handleStub(fi, fo, coff_offset);
} else { } else {
// "stubify" stub // "stubify" stub
info("Adding stub: %ld bytes", (long) sizeof(stub_i386_dos32_djgpp2_stubify)); info("Adding stub: %zd bytes", sizeof(stub_i386_dos32_djgpp2_stubify));
fo->write(stub_i386_dos32_djgpp2_stubify, sizeof(stub_i386_dos32_djgpp2_stubify)); fo->write(stub_i386_dos32_djgpp2_stubify, sizeof(stub_i386_dos32_djgpp2_stubify));
} }
} }
@ -179,9 +179,9 @@ int PackDjgpp2::readFileHeader() {
return 0; return 0;
// FIXME: check for Linux etc. // FIXME: check for Linux etc.
text = coff_hdr.sh; text = &coff_hdr.sh[0];
data = text + 1; data = &coff_hdr.sh[1];
bss = data + 1; bss = &coff_hdr.sh[2];
return UPX_F_DJGPP2_COFF; return UPX_F_DJGPP2_COFF;
} }
@ -242,7 +242,7 @@ void PackDjgpp2::pack(OutputFile *fo) {
// read file // read file
const unsigned size = text->size + data->size; const unsigned size = text->size + data->size;
const unsigned tpos = text->scnptr; const unsigned tpos = text->scnptr;
const unsigned hdrsize = 20 + 28 + sizeof(external_scnhdr_t) * coff_hdr.f_nscns; const unsigned hdrsize = 20 + 28 + mem_size(sizeof(external_scnhdr_t), coff_hdr.f_nscns);
const unsigned usize = size + hdrsize; const unsigned usize = size + hdrsize;
if (hdrsize < sizeof(coff_hdr) || hdrsize > tpos) if (hdrsize < sizeof(coff_hdr) || hdrsize > tpos)
throwCantPack("coff header error"); throwCantPack("coff header error");
@ -371,11 +371,14 @@ void PackDjgpp2::unpack(OutputFile *fo) {
// decompress // decompress
decompress(ibuf, obuf); decompress(ibuf, obuf);
coff_header_t *chdr = (coff_header_t *) obuf.getVoidPtr(); coff_header_t *chdr = (coff_header_t *) raw_bytes(obuf, sizeof(coff_header_t));
text = chdr->sh; text = &chdr->sh[0];
data = text + 1; data = &chdr->sh[1];
bss = &chdr->sh[2];
const unsigned hdrsize = 20 + 28 + sizeof(external_scnhdr_t) * chdr->f_nscns; const unsigned hdrsize = 20 + 28 + mem_size(sizeof(external_scnhdr_t), chdr->f_nscns);
if (hdrsize < sizeof(coff_hdr) || hdrsize > text->scnptr || hdrsize > ph.u_len)
throwCantUnpack("coff header error");
unsigned addvalue; unsigned addvalue;
if (ph.version >= 14) if (ph.version >= 14)

View File

@ -98,7 +98,9 @@ protected:
}; };
coff_header_t coff_hdr; coff_header_t coff_hdr;
external_scnhdr_t *text, *data, *bss; external_scnhdr_t *text = nullptr;
external_scnhdr_t *data = nullptr;
external_scnhdr_t *bss = nullptr;
void stripDebug(); void stripDebug();
}; };

View File

@ -1,4 +1,4 @@
/* p_exe.cpp -- /* p_exe.cpp -- dos/exe executable format
This file is part of the UPX executable compressor. This file is part of the UPX executable compressor.
@ -54,6 +54,8 @@ PackExe::PackExe(InputFile *f) : super(f) {
use_clear_dirty_stack = false; use_clear_dirty_stack = false;
} }
Linker *PackExe::newLinker() const { return new ElfLinkerX86(); }
const int *PackExe::getCompressionMethods(int method, int level) const { const int *PackExe::getCompressionMethods(int method, int level) const {
bool small = ih_imagesize <= 256 * 1024; bool small = ih_imagesize <= 256 * 1024;
// disable lzma for "--brute" unless explicitly given "--lzma" // disable lzma for "--brute" unless explicitly given "--lzma"
@ -106,16 +108,16 @@ int PackExe::fillExeHeader(struct exe_header_t *eh) const {
} }
void PackExe::addLoaderEpilogue(int flag) { void PackExe::addLoaderEpilogue(int flag) {
addLoader("EXEMAIN5", nullptr); addLoader("EXEMAIN5");
if (relocsize) if (relocsize)
addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ" addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ"
: "EXEADJUS", : "EXEADJUS",
"EXERELO1", has_9a ? "EXEREL9A" : "", "EXERELO2", "EXERELO1", has_9a ? "EXEREL9A" : "", "EXERELO2",
ih_exesize > 0xFE00 ? "EXEREBIG" : "", "EXERELO3", nullptr); ih_exesize > 0xFE00 ? "EXEREBIG" : "", "EXERELO3");
addLoader("EXEMAIN8", device_driver ? "DEVICEEND" : "", (flag & SS) ? "EXESTACK" : "", addLoader("EXEMAIN8", device_driver ? "DEVICEEND" : "", (flag & SS) ? "EXESTACK" : "",
(flag & SP) ? "EXESTASP" : "", (flag & USEJUMP) ? "EXEJUMPF" : "", nullptr); (flag & SP) ? "EXESTASP" : "", (flag & USEJUMP) ? "EXEJUMPF" : "");
if (!(flag & USEJUMP)) if (!(flag & USEJUMP))
addLoader(ih.cs ? "EXERCSPO" : "", "EXERETIP", nullptr); addLoader(ih.cs ? "EXERCSPO" : "", "EXERETIP");
linker->defineSymbol("original_cs", ih.cs); linker->defineSymbol("original_cs", ih.cs);
linker->defineSymbol("original_ip", ih.ip); linker->defineSymbol("original_ip", ih.ip);
@ -136,7 +138,7 @@ void PackExe::buildLoader(const Filter *) {
if (M_IS_LZMA(ph.method)) { if (M_IS_LZMA(ph.method)) {
addLoader("LZMA_DEC00", opt->small ? "LZMA_DEC10" : "LZMA_DEC20", "LZMA_DEC30", addLoader("LZMA_DEC00", opt->small ? "LZMA_DEC10" : "LZMA_DEC20", "LZMA_DEC30",
use_clear_dirty_stack ? "LZMA_DEC31" : "", "LZMA_DEC32", use_clear_dirty_stack ? "LZMA_DEC31" : "", "LZMA_DEC32",
ph.u_len > 0xffff ? "LZMA_DEC33" : "", nullptr); ph.u_len > 0xffff ? "LZMA_DEC33" : "");
addLoaderEpilogue(flag); addLoaderEpilogue(flag);
defineDecompressorSymbols(); defineDecompressorSymbols();
@ -173,35 +175,35 @@ void PackExe::buildLoader(const Filter *) {
initLoader(stub_i086_dos16_exe, sizeof(stub_i086_dos16_exe)); initLoader(stub_i086_dos16_exe, sizeof(stub_i086_dos16_exe));
// prepare loader // prepare loader
if (device_driver) if (device_driver)
addLoader("DEVICEENTRY,LZMADEVICE,DEVICEENTRY2", nullptr); addLoader("DEVICEENTRY,LZMADEVICE,DEVICEENTRY2");
linker->addSection("COMPRESSED_LZMA", compressed_lzma, c_len_lzma, 0); linker->addSection("COMPRESSED_LZMA", compressed_lzma, c_len_lzma, 0);
addLoader("LZMAENTRY,NRV2B160,NRVDDONE,NRVDECO1,NRVGTD00,NRVDECO2", nullptr); addLoader("LZMAENTRY,NRV2B160,NRVDDONE,NRVDECO1,NRVGTD00,NRVDECO2");
} else if (device_driver) } else if (device_driver)
addLoader("DEVICEENTRY,DEVICEENTRY2", nullptr); addLoader("DEVICEENTRY,DEVICEENTRY2");
addLoader("EXEENTRY", M_IS_LZMA(ph.method) && device_driver ? "LONGSUB" : "SHORTSUB", addLoader("EXEENTRY", M_IS_LZMA(ph.method) && device_driver ? "LONGSUB" : "SHORTSUB",
"JNCDOCOPY", relocsize ? "EXERELPU" : "", "EXEMAIN4", "JNCDOCOPY", relocsize ? "EXERELPU" : "", "EXEMAIN4",
M_IS_LZMA(ph.method) ? "" : "EXEMAIN4B", "EXEMAIN4C", M_IS_LZMA(ph.method) ? "" : "EXEMAIN4B", "EXEMAIN4C",
M_IS_LZMA(ph.method) ? "COMPRESSED_LZMA_START,COMPRESSED_LZMA" : "", M_IS_LZMA(ph.method) ? "COMPRESSED_LZMA_START,COMPRESSED_LZMA" : "",
"+G5DXXXX,UPX1HEAD,EXECUTPO", nullptr); "+G5DXXXX,UPX1HEAD,EXECUTPO");
if (ph.method == M_NRV2B_8) if (ph.method == M_NRV2B_8)
addLoader("NRV2B16S", // decompressor addLoader("NRV2B16S", // decompressor
ph.u_len > DI_LIMIT ? "N2B64K01" : "", "NRV2BEX1", ph.u_len > DI_LIMIT ? "N2B64K01" : "", "NRV2BEX1",
opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601", "NRV2BEX2", opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601", "NRV2BEX2",
opt->cpu == opt->CPU_8086 ? "N2BX8602" : "N2B28602", "NRV2BEX3", opt->cpu == opt->CPU_8086 ? "N2BX8602" : "N2B28602", "NRV2BEX3",
ph.c_len > 0xffff ? "N2B64K02" : "", "NRV2BEX9", nullptr); ph.c_len > 0xffff ? "N2B64K02" : "", "NRV2BEX9");
else if (ph.method == M_NRV2D_8) else if (ph.method == M_NRV2D_8)
addLoader("NRV2D16S", ph.u_len > DI_LIMIT ? "N2D64K01" : "", "NRV2DEX1", addLoader("NRV2D16S", ph.u_len > DI_LIMIT ? "N2D64K01" : "", "NRV2DEX1",
opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601", "NRV2DEX2", opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601", "NRV2DEX2",
opt->cpu == opt->CPU_8086 ? "N2DX8602" : "N2D28602", "NRV2DEX3", opt->cpu == opt->CPU_8086 ? "N2DX8602" : "N2D28602", "NRV2DEX3",
ph.c_len > 0xffff ? "N2D64K02" : "", "NRV2DEX9", nullptr); ph.c_len > 0xffff ? "N2D64K02" : "", "NRV2DEX9");
else if (ph.method == M_NRV2E_8) else if (ph.method == M_NRV2E_8)
addLoader("NRV2E16S", ph.u_len > DI_LIMIT ? "N2E64K01" : "", "NRV2EEX1", addLoader("NRV2E16S", ph.u_len > DI_LIMIT ? "N2E64K01" : "", "NRV2EEX1",
opt->cpu == opt->CPU_8086 ? "N2EX8601" : "N2E28601", "NRV2EEX2", opt->cpu == opt->CPU_8086 ? "N2EX8601" : "N2E28601", "NRV2EEX2",
opt->cpu == opt->CPU_8086 ? "N2EX8602" : "N2E28602", "NRV2EEX3", opt->cpu == opt->CPU_8086 ? "N2EX8602" : "N2E28602", "NRV2EEX3",
ph.c_len > 0xffff ? "N2E64K02" : "", "NRV2EEX9", nullptr); ph.c_len > 0xffff ? "N2E64K02" : "", "NRV2EEX9");
else if M_IS_LZMA (ph.method) else if M_IS_LZMA (ph.method)
return; return;
else else
@ -229,9 +231,7 @@ int PackExe::readFileHeader() {
throwCantPack("illegal exe header"); throwCantPack("illegal exe header");
if (file_size_u < ih_exesize || ih_imagesize <= 0 || ih_imagesize > ih_exesize) if (file_size_u < ih_exesize || ih_imagesize <= 0 || ih_imagesize > ih_exesize)
throwCantPack("exe header corrupted"); throwCantPack("exe header corrupted");
#if 0 NO_printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay);
printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay);
#endif
return UPX_F_DOS_EXE; return UPX_F_DOS_EXE;
} }
@ -553,13 +553,11 @@ void PackExe::pack(OutputFile *fo) {
fo->write(loader + e_len, d_len); // decompressor fo->write(loader + e_len, d_len); // decompressor
fo->write(extra_info, eisize); fo->write(extra_info, eisize);
assert(eisize <= 9); assert(eisize <= 9);
#if 0 NO_printf("%-13s: program hdr : %8u bytes\n", getName(), usizeof(oh));
printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh)); NO_printf("%-13s: entry : %8u bytes\n", getName(), e_len);
printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len); NO_printf("%-13s: compressed : %8u bytes\n", getName(), packedsize);
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) packedsize); NO_printf("%-13s: decompressor : %8u bytes\n", getName(), d_len);
printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) d_len); NO_printf("%-13s: extra info : %8u bytes\n", getName(), eisize);
printf("%-13s: extra info : %8ld bytes\n", getName(), (long) eisize);
#endif
// verify // verify
verifyOverlappingDecompression(); verifyOverlappingDecompression();
@ -711,8 +709,6 @@ void PackExe::unpack(OutputFile *fo) {
copyOverlay(fo, ih_overlay, obuf); copyOverlay(fo, ih_overlay, obuf);
} }
Linker *PackExe::newLinker() const { return new ElfLinkerX86(); }
/* /*
memory layout at decompression time memory layout at decompression time

View File

@ -1,4 +1,4 @@
/* p_exe.h -- /* p_exe.h -- dos/exe executable format
This file is part of the UPX executable compressor. This file is part of the UPX executable compressor.

View File

@ -30,6 +30,7 @@
*/ */
#define ALLOW_INT_PLUS_MEMBUFFER 1
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"

View File

@ -92,7 +92,7 @@ PackLinuxI386sh::buildLoader(Filter const *ft)
optimizeFilter(&fold_ft, buf, sz_fold); optimizeFilter(&fold_ft, buf, sz_fold);
unsigned fold_hdrlen = sizeof(l_info) + sizeof(Elf32_Ehdr) + unsigned fold_hdrlen = sizeof(l_info) + sizeof(Elf32_Ehdr) +
sizeof(Elf32_Phdr) * get_te32(&((Elf32_Ehdr const *)(void *)buf)->e_phnum); sizeof(Elf32_Phdr) * get_te32(&((Elf32_Ehdr const *)(void *)buf)->e_phnum);
if (0 == get_le32(fold_hdrlen + buf)) { if (0 == get_le32(buf + fold_hdrlen)) {
// inconsistent SIZEOF_HEADERS in *.lds (ld, binutils) // inconsistent SIZEOF_HEADERS in *.lds (ld, binutils)
fold_hdrlen = umax(0x80, fold_hdrlen); fold_hdrlen = umax(0x80, fold_hdrlen);
} }

View File

@ -25,6 +25,7 @@
*/ */
#define ALLOW_INT_PLUS_MEMBUFFER 1
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"

View File

@ -1,4 +1,4 @@
/* p_sys.cpp -- /* p_sys.cpp -- dos/sys executable format
This file is part of the UPX executable compressor. This file is part of the UPX executable compressor.
@ -46,13 +46,13 @@ bool PackSys::canPack() {
fi->readx(buf, sizeof(buf)); fi->readx(buf, sizeof(buf));
if (memcmp(buf, "\xff\xff\xff\xff", 4) != 0) if (memcmp(buf, "\xff\xff\xff\xff", 4) != 0)
return false; return false;
if (!fn_has_ext(fi->getName(), "sys")) if (!fn_has_ext(fi->getName(), "sys")) // query file name
return false; return false;
checkAlreadyPacked(buf, sizeof(buf)); checkAlreadyPacked(buf, sizeof(buf));
if (file_size < 1024) if (file_size < 1024)
throwCantPack("file is too small"); throwCantPack("file is too small for dos/sys");
if (file_size > 0x10000) if (file_size > 0x10000)
throwCantPack("file is too big for dos/sys"); throwCantPack("file is too large for dos/sys");
return true; return true;
} }
@ -60,6 +60,29 @@ bool PackSys::canPack() {
// //
**************************************************************************/ **************************************************************************/
void PackSys::buildLoader(const Filter *ft) {
initLoader(stub_i086_dos16_sys, sizeof(stub_i086_dos16_sys));
// clang-format off
addLoader("SYSMAIN1",
opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861",
"SYSMAIN2",
ph.first_offset_found == 1 ? "SYSSBBBP" : "",
ft->id ? "SYSCALLT" : "",
"SYSMAIN3,UPX1HEAD,SYSCUTPO,NRV2B160,NRVDDONE,NRVDECO1",
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
"NRVDECO2");
// clang-format on
if (ft->id) {
assert(ft->calls > 0);
addFilter16(ft->id);
}
// clang-format off
addLoader("SYSMAIN5",
opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862",
"SYSJUMP1");
// clang-format on
}
void PackSys::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned calls) { void PackSys::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned calls) {
const int e_len = getLoaderSectionStart("SYSCUTPO"); const int e_len = getLoaderSectionStart("SYSCUTPO");
const int d_len = lsize - e_len; const int d_len = lsize - e_len;
@ -85,24 +108,15 @@ void PackSys::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned
relocateLoader(); relocateLoader();
loader = getLoader(); loader = getLoader();
// some day we could use the relocation stuff for patchPackHeader too..
patchPackHeader(loader, e_len); patchPackHeader(loader, e_len);
// write loader + compressed file // write loader + compressed file
fo->write(loader, e_len); // entry fo->write(loader, e_len); // entry
fo->write(obuf, ph.c_len); fo->write(obuf, ph.c_len); // compressed
fo->write(loader + e_len, d_len); // decompressor fo->write(loader + e_len, d_len); // decompressor
} NO_printf("%-13s: entry : %8u bytes\n", getName(), e_len);
NO_printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
void PackSys::buildLoader(const Filter *ft) { NO_printf("%-13s: decompressor : %8u bytes\n", getName(), d_len);
initLoader(stub_i086_dos16_sys, sizeof(stub_i086_dos16_sys));
addLoader("SYSMAIN1", opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861", "SYSMAIN2",
ph.first_offset_found == 1 ? "SYSSBBBP" : "", ft->id ? "SYSCALLT" : "",
"SYSMAIN3,UPX1HEAD,SYSCUTPO,NRV2B160,NRVDDONE,NRVDECO1",
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00", "NRVDECO2", nullptr);
if (ft->id) {
assert(ft->calls > 0);
addFilter16(ft->id);
}
addLoader("SYSMAIN5", opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862", "SYSJUMP1", nullptr);
} }
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -1,4 +1,4 @@
/* p_sys.h -- /* p_sys.h -- dos/sys executable format
This file is part of the UPX executable compressor. This file is part of the UPX executable compressor.
@ -45,10 +45,8 @@ public:
virtual bool canPack() override; virtual bool canPack() override;
protected: protected: // dos/com overrides
virtual unsigned getCallTrickOffset() const override { return 0; } virtual unsigned getCallTrickOffset() const override { return 0; }
protected:
virtual void buildLoader(const Filter *ft) override; virtual void buildLoader(const Filter *ft) override;
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned) override; virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned) override;
}; };

View File

@ -46,6 +46,8 @@ PackTmt::PackTmt(InputFile *f) : super(f) {
COMPILE_TIME_ASSERT(sizeof(tmt_header_t) == 44) COMPILE_TIME_ASSERT(sizeof(tmt_header_t) == 44)
} }
Linker *PackTmt::newLinker() const { return new ElfLinkerX86; }
const int *PackTmt::getCompressionMethods(int method, int level) const { const int *PackTmt::getCompressionMethods(int method, int level) const {
return Packer::getDefaultCompressionMethods_le32(method, level); return Packer::getDefaultCompressionMethods_le32(method, level);
} }
@ -64,24 +66,22 @@ unsigned PackTmt::findOverlapOverhead(const upx_bytep buf, const upx_bytep tbuf,
return o; return o;
} }
Linker *PackTmt::newLinker() const { return new ElfLinkerX86; }
void PackTmt::buildLoader(const Filter *ft) { void PackTmt::buildLoader(const Filter *ft) {
// prepare loader // prepare loader
initLoader(stub_i386_dos32_tmt, sizeof(stub_i386_dos32_tmt)); initLoader(stub_i386_dos32_tmt, sizeof(stub_i386_dos32_tmt));
addLoader("IDENTSTR,TMTMAIN1", ph.first_offset_found == 1 ? "TMTMAIN1A" : "", "TMTMAIN1B", addLoader("IDENTSTR,TMTMAIN1", ph.first_offset_found == 1 ? "TMTMAIN1A" : "", "TMTMAIN1B",
ft->id ? "TMTCALT1" : "", "TMTMAIN2,UPX1HEAD,TMTCUTPO", nullptr); ft->id ? "TMTCALT1" : "", "TMTMAIN2,UPX1HEAD,TMTCUTPO");
// fake alignment for the start of the decompressor // fake alignment for the start of the decompressor
linker->defineSymbol("TMTCUTPO", 0x1000); linker->defineSymbol("TMTCUTPO", 0x1000);
addLoader(getDecompressorSections(), "TMTMAIN5", nullptr); addLoader(getDecompressorSections(), "TMTMAIN5");
if (ft->id) { if (ft->id) {
assert(ft->calls > 0); assert(ft->calls > 0);
addLoader("TMTCALT2", nullptr); addLoader("TMTCALT2");
addFilter32(ft->id); addFilter32(ft->id);
} }
addLoader("TMTRELOC,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J,TMTJUMP1", nullptr); addLoader("TMTRELOC,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J,TMTJUMP1");
} }
/************************************************************************* /*************************************************************************
@ -139,8 +139,8 @@ int PackTmt::readFileHeader() {
unsigned const imagesize = ih.imagesize; unsigned const imagesize = ih.imagesize;
unsigned const entry = ih.entry; unsigned const entry = ih.entry;
unsigned const relocsize = ih.relocsize; unsigned const relocsize = ih.relocsize;
if (imagesize < sizeof(ih) || entry < sizeof(ih) || file_size <= imagesize || if (imagesize < sizeof(ih) || entry < sizeof(ih) || file_size_u <= imagesize ||
file_size <= entry || file_size <= relocsize) { file_size_u <= entry || file_size_u <= relocsize) {
printWarn(getName(), "bad header; imagesize=%#x entry=%#x relocsize=%#x", imagesize, printWarn(getName(), "bad header; imagesize=%#x entry=%#x relocsize=%#x", imagesize,
entry, relocsize); entry, relocsize);
return 0; return 0;
@ -202,7 +202,7 @@ void PackTmt::pack(OutputFile *fo) {
relocsize += 4; relocsize += 4;
set_le32(wrkmem + relocsize, relocsize + 4); set_le32(wrkmem + relocsize, relocsize + 4);
relocsize += 4; relocsize += 4;
memcpy(ibuf + usize, wrkmem, relocsize); memcpy(raw_index_bytes(ibuf, usize, relocsize), wrkmem, relocsize);
// prepare packheader // prepare packheader
ph.u_len = usize + relocsize; ph.u_len = usize + relocsize;

View File

@ -50,6 +50,8 @@ PackTos::PackTos(InputFile *f) : super(f) {
COMPILE_TIME_ASSERT_ALIGNED1(tos_header_t) COMPILE_TIME_ASSERT_ALIGNED1(tos_header_t)
} }
Linker *PackTos::newLinker() const { return new ElfLinkerM68k; }
const int *PackTos::getCompressionMethods(int method, int level) const { const int *PackTos::getCompressionMethods(int method, int level) const {
bool small = ih.fh_text + ih.fh_data <= 256 * 1024; bool small = ih.fh_text + ih.fh_data <= 256 * 1024;
return Packer::getDefaultCompressionMethods_8(method, level, small); return Packer::getDefaultCompressionMethods_8(method, level, small);
@ -57,8 +59,6 @@ const int *PackTos::getCompressionMethods(int method, int level) const {
const int *PackTos::getFilters() const { return nullptr; } const int *PackTos::getFilters() const { return nullptr; }
Linker *PackTos::newLinker() const { return new ElfLinkerM68k; }
void PackTos::LinkerSymbols::LoopInfo::init(unsigned count_, bool allow_dbra) { void PackTos::LinkerSymbols::LoopInfo::init(unsigned count_, bool allow_dbra) {
count = value = count_; count = value = count_;
if (count == 0) if (count == 0)

View File

@ -26,6 +26,7 @@
*/ */
#define ALLOW_INT_PLUS_MEMBUFFER 1
#include "conf.h" #include "conf.h"
#include "p_elf.h" #include "p_elf.h"

View File

@ -98,44 +98,44 @@ void PackW32Pe::buildLoader(const Filter *ft) {
tmp_tlsindex ? "PETLSHAK" : "", "PEMAIN02", tmp_tlsindex ? "PETLSHAK" : "", "PEMAIN02",
ph.first_offset_found == 1 ? "PEMAIN03" : "", getDecompressorSections(), ph.first_offset_found == 1 ? "PEMAIN03" : "", getDecompressorSections(),
// multipass ? "PEMULTIP" : "", // multipass ? "PEMULTIP" : "",
"PEMAIN10", nullptr); "PEMAIN10");
addLoader(tmp_tlsindex ? "PETLSHAK2" : ""); addLoader(tmp_tlsindex ? "PETLSHAK2" : "");
if (ft->id) { if (ft->id) {
const unsigned texv = ih.codebase - rvamin; const unsigned texv = ih.codebase - rvamin;
assert(ft->calls > 0); assert(ft->calls > 0);
addLoader(texv ? "PECTTPOS" : "PECTTNUL", nullptr); addLoader(texv ? "PECTTPOS" : "PECTTNUL");
addFilter32(ft->id); addFilter32(ft->id);
} }
if (soimport) if (soimport)
addLoader("PEIMPORT", importbyordinal ? "PEIBYORD" : "", kernel32ordinal ? "PEK32ORD" : "", addLoader("PEIMPORT", importbyordinal ? "PEIBYORD" : "", kernel32ordinal ? "PEK32ORD" : "",
importbyordinal ? "PEIMORD1" : "", "PEIMPOR2", isdll ? "PEIERDLL" : "PEIEREXE", importbyordinal ? "PEIMORD1" : "", "PEIMPOR2", isdll ? "PEIERDLL" : "PEIEREXE",
"PEIMDONE", nullptr); "PEIMDONE");
if (sorelocs) { if (sorelocs) {
addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2", addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2",
"PERELOC3,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J", nullptr); "PERELOC3,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J");
// FIXME: the following should be moved out of the above if // FIXME: the following should be moved out of the above if
addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "", addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "",
big_relocs & 2 ? "PERELHI0" : "", nullptr); big_relocs & 2 ? "PERELHI0" : "");
} }
if (use_dep_hack) if (use_dep_hack)
addLoader("PEDEPHAK", nullptr); addLoader("PEDEPHAK");
// NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann // NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann
if (use_tls_callbacks) if (use_tls_callbacks)
addLoader("PETLSC", nullptr); addLoader("PETLSC");
addLoader("PEMAIN20", nullptr); addLoader("PEMAIN20");
if (use_clear_dirty_stack) if (use_clear_dirty_stack)
addLoader("CLEARSTACK", nullptr); addLoader("CLEARSTACK");
addLoader("PEMAIN21", nullptr); addLoader("PEMAIN21");
// NEW: last loader sections split up to insert TLS callback handler - Stefan Widmann // NEW: last loader sections split up to insert TLS callback handler - Stefan Widmann
addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN", nullptr); addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN");
// NEW: TLS callback support PART 2, the callback handler - Stefan Widmann // NEW: TLS callback support PART 2, the callback handler - Stefan Widmann
if (use_tls_callbacks) if (use_tls_callbacks)
addLoader("PETLSC2", nullptr); addLoader("PETLSC2");
addLoader("IDENTSTR,UPX1HEAD", nullptr); addLoader("IDENTSTR,UPX1HEAD");
} }
bool PackW32Pe::handleForceOption() { bool PackW32Pe::handleForceOption() {

View File

@ -97,49 +97,49 @@ void PackW64Pep::buildLoader(const Filter *ft) {
: M_IS_NRV2E(ph.method) ? "NRV_HEAD,NRV2E" : M_IS_NRV2E(ph.method) ? "NRV_HEAD,NRV2E"
: "UNKNOWN_COMPRESSION_METHOD", : "UNKNOWN_COMPRESSION_METHOD",
// getDecompressorSections(), // getDecompressorSections(),
/*multipass ? "PEMULTIP" : */ "", "PEMAIN10", nullptr); /*multipass ? "PEMULTIP" : */ "", "PEMAIN10");
addLoader(tmp_tlsindex ? "PETLSHAK2" : ""); addLoader(tmp_tlsindex ? "PETLSHAK2" : "");
if (ft->id) { if (ft->id) {
const unsigned texv = ih.codebase - rvamin; const unsigned texv = ih.codebase - rvamin;
assert(ft->calls > 0); assert(ft->calls > 0);
addLoader(texv ? "PECTTPOS" : "PECTTNUL", nullptr); addLoader(texv ? "PECTTPOS" : "PECTTNUL");
addLoader("PEFILTER49"); addLoader("PEFILTER49");
} }
if (soimport) if (soimport)
addLoader("PEIMPORT", importbyordinal ? "PEIBYORD" : "", kernel32ordinal ? "PEK32ORD" : "", addLoader("PEIMPORT", importbyordinal ? "PEIBYORD" : "", kernel32ordinal ? "PEK32ORD" : "",
importbyordinal ? "PEIMORD1" : "", "PEIMPOR2", isdll ? "PEIERDLL" : "PEIEREXE", importbyordinal ? "PEIMORD1" : "", "PEIMPOR2", isdll ? "PEIERDLL" : "PEIEREXE",
"PEIMDONE", nullptr); "PEIMDONE");
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", nullptr); "PERELOC3", big_relocs ? "REL64BIG" : "", "RELOC64J");
if __acc_cte (0) { if __acc_cte (0) {
addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "", addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "",
big_relocs & 2 ? "PERELHI0" : "", nullptr); big_relocs & 2 ? "PERELHI0" : "");
} }
} }
if (use_dep_hack) if (use_dep_hack)
addLoader("PEDEPHAK", nullptr); addLoader("PEDEPHAK");
// NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann // NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann
if (use_tls_callbacks) if (use_tls_callbacks)
addLoader("PETLSC", nullptr); addLoader("PETLSC");
addLoader("PEMAIN20", nullptr); addLoader("PEMAIN20");
if (use_clear_dirty_stack) if (use_clear_dirty_stack)
addLoader("CLEARSTACK", nullptr); addLoader("CLEARSTACK");
addLoader("PEMAIN21", nullptr); addLoader("PEMAIN21");
if (ih.entry && isdll) if (ih.entry && isdll)
addLoader("PEISDLL9"); addLoader("PEISDLL9");
if (isefi) if (isefi)
addLoader("PEISEFI9"); addLoader("PEISEFI9");
addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN", nullptr); addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN");
// NEW: TLS callback support PART 2, the callback handler - Stefan Widmann // NEW: TLS callback support PART 2, the callback handler - Stefan Widmann
if (use_tls_callbacks) if (use_tls_callbacks)
addLoader("PETLSC2", nullptr); addLoader("PETLSC2");
addLoader("IDENTSTR,UPX1HEAD", nullptr); addLoader("IDENTSTR,UPX1HEAD");
} }
bool PackW64Pep::handleForceOption() { bool PackW64Pep::handleForceOption() {

View File

@ -85,22 +85,22 @@ void PackWcle::buildLoader(const Filter *ft) {
// prepare loader // prepare loader
initLoader(stub_i386_dos32_watcom_le, sizeof(stub_i386_dos32_watcom_le)); initLoader(stub_i386_dos32_watcom_le, sizeof(stub_i386_dos32_watcom_le));
addLoader("IDENTSTR,WCLEMAIN", ph.first_offset_found == 1 ? "WCLEMAIN02" : "", addLoader("IDENTSTR,WCLEMAIN", ph.first_offset_found == 1 ? "WCLEMAIN02" : "",
"WCLEMAIN03,UPX1HEAD,WCLECUTP", nullptr); "WCLEMAIN03,UPX1HEAD,WCLECUTP");
// fake alignment for the start of the decompressor // fake alignment for the start of the decompressor
linker->defineSymbol("WCLECUTP", 0x1000); linker->defineSymbol("WCLECUTP", 0x1000);
addLoader(getDecompressorSections(), "WCLEMAI2", nullptr); addLoader(getDecompressorSections(), "WCLEMAI2");
if (ft->id) { if (ft->id) {
assert(ft->calls > 0); assert(ft->calls > 0);
addLoader(ft->addvalue ? "WCCTTPOS" : "WCCTTNUL", nullptr); addLoader(ft->addvalue ? "WCCTTPOS" : "WCCTTNUL");
addFilter32(ft->id); addFilter32(ft->id);
} }
#if 1 #if 1
// FIXME: if (has_relocation) // FIXME: if (has_relocation)
{ addLoader("WCRELOC1,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J", nullptr); } { addLoader("WCRELOC1,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J"); }
#endif #endif
addLoader(has_extra_code ? "WCRELSEL" : "", "WCLEMAI4", nullptr); addLoader(has_extra_code ? "WCRELSEL" : "", "WCLEMAI4");
} }
/************************************************************************* /*************************************************************************

View File

@ -1270,9 +1270,11 @@ void Packer::compressWithFilters(upx_bytep i_ptr,
assert(nfilters < 256); assert(nfilters < 256);
#if 0 #if 0
printf("compressWithFilters: m(%d):", nmethods); printf("compressWithFilters: m(%d):", nmethods);
for (int i = 0; i < nmethods; i++) printf(" %#x", methods[i]); for (int i = 0; i < nmethods; i++)
printf(" %#x", methods[i]);
printf(" f(%d):", nfilters); printf(" f(%d):", nfilters);
for (int i = 0; i < nfilters; i++) printf(" %#x", filters[i]); for (int i = 0; i < nfilters; i++)
printf(" %#x", filters[i]);
printf("\n"); printf("\n");
#endif #endif
@ -1294,9 +1296,7 @@ void Packer::compressWithFilters(upx_bytep i_ptr,
int nfilters_success_total = 0; int nfilters_success_total = 0;
for (int mm = 0; mm < nmethods; mm++) // for all methods for (int mm = 0; mm < nmethods; mm++) // for all methods
{ {
#if 0 //{ NO_printf("\nmethod %d (%d of %d)\n", methods[mm], 1 + mm, nmethods);
printf("\nmethod %d (%d of %d)\n", methods[mm], 1+ mm, nmethods);
#endif //}
assert(isValidCompressionMethod(methods[mm])); assert(isValidCompressionMethod(methods[mm]));
unsigned hdr_c_len = 0; unsigned hdr_c_len = 0;
if (hdr_ptr != nullptr && hdr_len) { if (hdr_ptr != nullptr && hdr_len) {
@ -1341,10 +1341,9 @@ void Packer::compressWithFilters(upx_bytep i_ptr,
continue; continue;
} }
// filter success // filter success
#if 0 NO_printf("\nfilter: id 0x%02x size %6d, calls %5d/%5d/%3d/%5d/%5d, cto 0x%02x\n",
printf("\nfilter: id 0x%02x size %6d, calls %5d/%5d/%3d/%5d/%5d, cto 0x%02x\n", ft.id, ft.buf_len, ft.calls, ft.noncalls, ft.wrongcalls, ft.firstcall,
ft.id, ft.buf_len, ft.calls, ft.noncalls, ft.wrongcalls, ft.firstcall, ft.lastcall, ft.cto); ft.lastcall, ft.cto);
#endif
if (nfilters_success_total != 0 && o_tmp == o_ptr) { if (nfilters_success_total != 0 && o_tmp == o_ptr) {
o_tmp_buf.allocForCompression(i_len); o_tmp_buf.allocForCompression(i_len);
o_tmp = o_tmp_buf; o_tmp = o_tmp_buf;
@ -1365,11 +1364,10 @@ void Packer::compressWithFilters(upx_bytep i_ptr,
lsize = getLoaderSize(); lsize = getLoaderSize();
assert(lsize > 0); assert(lsize > 0);
} }
#if 0 //{ NO_printf("\n%2d %02x: %d +%4d +%3d = %d (best: %d +%4d +%3d = %d)\n", ph.method,
printf("\n%2d %02x: %d +%4d +%3d = %d (best: %d +%4d +%3d = %d)\n", ph.method, ph.filter, ph.filter, ph.c_len, lsize, hdr_c_len, ph.c_len + lsize + hdr_c_len,
ph.c_len, lsize, hdr_c_len, ph.c_len + lsize + hdr_c_len, best_ph.c_len, best_ph_lsize, best_hdr_c_len,
best_ph.c_len, best_ph_lsize, best_hdr_c_len, best_ph.c_len + best_ph_lsize + best_hdr_c_len); best_ph.c_len + best_ph_lsize + best_hdr_c_len);
#endif //}
bool update = false; bool update = false;
if (ph.c_len + lsize + hdr_c_len < best_ph.c_len + best_ph_lsize + best_hdr_c_len) if (ph.c_len + lsize + hdr_c_len < best_ph.c_len + best_ph_lsize + best_hdr_c_len)
update = true; update = true;

View File

@ -34,7 +34,6 @@
class InputFile; class InputFile;
class OutputFile; class OutputFile;
class Packer; class Packer;
class PackMaster;
class UiPacker; class UiPacker;
class Filter; class Filter;

View File

@ -25,12 +25,9 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#include "conf.h" #include "conf.h"
#include "packer.h" #include "packer.h"
#include "linker.h" #include "linker.h"
//#include "filter.h"
/************************************************************************* /*************************************************************************
// compression method util // compression method util
@ -40,7 +37,7 @@ bool Packer::isValidCompressionMethod(int method)
{ {
if (M_IS_LZMA(method)) if (M_IS_LZMA(method))
return true; return true;
return (method >= M_NRV2B_LE32 && method <= M_LZMA); return method >= M_NRV2B_LE32 && method <= M_LZMA;
} }

View File

@ -25,282 +25,240 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#include "conf.h" #include "conf.h"
#include "packer.h" #include "packer.h"
#include "filter.h" #include "filter.h"
#include "linker.h" #include "linker.h"
/************************************************************************* /*************************************************************************
// filter util // filter util; see class FilterImpl
**************************************************************************/ **************************************************************************/
bool Packer::isValidFilter(int filter_id) const bool Packer::isValidFilter(int filter_id) const {
{
return Filter::isValidFilter(filter_id, getFilters()); return Filter::isValidFilter(filter_id, getFilters());
} }
/************************************************************************* /*************************************************************************
// addFilter32 // addFilter32
**************************************************************************/ **************************************************************************/
#define NOFILT 0 // no filter #define NOFILT 0 // no filter
#define FNOMRU 1 // filter, but not using mru #define FNOMRU 1 // filter, but not using mru
#define MRUFLT 2 // mru filter #define MRUFLT 2 // mru filter
static inline unsigned f80_call(int filter_id) static inline unsigned f80_call(int filter_id) { return (1 + (0x0f & filter_id)) % 3; }
{
return (1+ (0x0f & filter_id)) % 3;
}
static inline unsigned f80_jmp1(int filter_id) static inline unsigned f80_jmp1(int filter_id) { return ((1 + (0x0f & filter_id)) / 3) % 3; }
{
return ((1+ (0x0f & filter_id)) / 3) % 3;
}
static inline unsigned f80_jcc2(int filter_id) static inline unsigned f80_jcc2(int filter_id) { return f80_jmp1(filter_id); }
{
return f80_jmp1(filter_id);
}
void Packer::addFilter32(int filter_id) {
void Packer::addFilter32(int filter_id)
{
assert(filter_id > 0); assert(filter_id > 0);
assert(isValidFilter(filter_id)); assert(isValidFilter(filter_id));
if (filter_id < 0x80) { if (filter_id < 0x80) {
if (0x50==(0xF0 & filter_id)) { if (0x50 == (0xF0 & filter_id)) {
addLoader("ctok32.00", addLoader("ctok32.00",
((0x50==filter_id) ? "ctok32.50" : ((0x50 == filter_id) ? "ctok32.50"
(0x51==filter_id) ? "ctok32.51" : ""), : (0x51 == filter_id) ? "ctok32.51"
"ctok32.10", nullptr); : ""),
} "ctok32.10");
else if ((filter_id & 0xf) % 3 == 0) { } else if ((filter_id & 0xf) % 3 == 0) {
if (filter_id < 0x40) { if (filter_id < 0x40) {
addLoader("CALLTR00", addLoader("CALLTR00", (filter_id > 0x20) ? "CTCLEVE1" : "", "CALLTR01",
(filter_id > 0x20) ? "CTCLEVE1" : "", (filter_id & 0xf) > 3
"CALLTR01", ? (filter_id > 0x20 ? "CTBSHR01,CTBSWA01" : "CTBROR01,CTBSWA01")
(filter_id & 0xf) > 3 ? (filter_id > 0x20 ? "CTBSHR01,CTBSWA01" : "CTBROR01,CTBSWA01") : "", : "",
"CALLTR02", "CALLTR02");
nullptr } else if (0x40 == (0xF0 & filter_id)) {
); addLoader("ctok32.00");
} if (9 <= (0xf & filter_id)) {
else if (0x40==(0xF0 & filter_id)) { addLoader("ctok32.10");
addLoader("ctok32.00", nullptr);
if (9<=(0xf & filter_id)) {
addLoader("ctok32.10", nullptr);
} }
addLoader("ctok32.20", nullptr); addLoader("ctok32.20");
if (9<=(0xf & filter_id)) { if (9 <= (0xf & filter_id)) {
addLoader("ctok32.30", nullptr); addLoader("ctok32.30");
} }
addLoader("ctok32.40", nullptr); addLoader("ctok32.40");
} }
} } else
else addLoader("CALLTR10", (filter_id & 0xf) % 3 == 1 ? "CALLTRE8" : "CALLTRE9", "CALLTR11",
addLoader("CALLTR10", (filter_id > 0x20) ? "CTCLEVE2" : "", "CALLTR12",
(filter_id & 0xf) % 3 == 1 ? "CALLTRE8" : "CALLTRE9", (filter_id & 0xf) > 3
"CALLTR11", ? (filter_id > 0x20 ? "CTBSHR11,CTBSWA11" : "CTBROR11,CTBSWA11")
(filter_id > 0x20) ? "CTCLEVE2" : "", : "",
"CALLTR12", "CALLTR13");
(filter_id & 0xf) > 3 ? (filter_id > 0x20 ? "CTBSHR11,CTBSWA11" : "CTBROR11,CTBSWA11") : "",
"CALLTR13",
nullptr
);
} }
if (0x80==(filter_id & 0xF0)) { if (0x80 == (filter_id & 0xF0)) {
bool const x386 = (opt->cpu <= opt->CPU_386); bool const x386 = (opt->cpu <= opt->CPU_386);
unsigned const n_mru = ph.n_mru ? 1+ ph.n_mru : 0; unsigned const n_mru = ph.n_mru ? 1 + ph.n_mru : 0;
bool const mrupwr2 = (0!=n_mru) && 0==((n_mru -1) & n_mru); bool const mrupwr2 = (0 != n_mru) && 0 == ((n_mru - 1) & n_mru);
unsigned const f_call = f80_call(filter_id); unsigned const f_call = f80_call(filter_id);
unsigned const f_jmp1 = f80_jmp1(filter_id); unsigned const f_jmp1 = f80_jmp1(filter_id);
unsigned const f_jcc2 = f80_jcc2(filter_id); unsigned const f_jcc2 = f80_jcc2(filter_id);
if (NOFILT!=f_jcc2) { if (NOFILT != f_jcc2) {
addLoader("LXJCC010", nullptr); addLoader("LXJCC010");
if (n_mru) { if (n_mru) {
addLoader("LXMRU045", nullptr); addLoader("LXMRU045");
} } else {
else { addLoader("LXMRU046");
addLoader("LXMRU046", nullptr); }
} if (0 == n_mru || MRUFLT != f_jcc2) {
if (0==n_mru || MRUFLT!=f_jcc2) { addLoader("LXJCC020");
addLoader("LXJCC020", nullptr); } else { // 0 != n_mru
} addLoader("LXJCC021");
else { // 0!=n_mru }
addLoader("LXJCC021", nullptr); if (NOFILT != f_jcc2) {
} addLoader("LXJCC023");
if (NOFILT!=f_jcc2) { }
addLoader("LXJCC023", nullptr);
}
} }
addLoader("LXUNF037", nullptr); addLoader("LXUNF037");
if (x386) { if (x386) {
if (n_mru) { if (n_mru) {
addLoader("LXUNF386", nullptr); addLoader("LXUNF386");
} }
addLoader("LXUNF387", nullptr); addLoader("LXUNF387");
if (n_mru) { if (n_mru) {
addLoader("LXUNF388", nullptr); addLoader("LXUNF388");
} }
} } else {
else { addLoader("LXUNF486");
addLoader("LXUNF486", nullptr);
if (n_mru) { if (n_mru) {
addLoader("LXUNF487", nullptr); addLoader("LXUNF487");
} }
} }
if (n_mru) { if (n_mru) {
addLoader("LXMRU065", nullptr); addLoader("LXMRU065");
if (256==n_mru) { if (256 == n_mru) {
addLoader("MRUBYTE3", nullptr); addLoader("MRUBYTE3");
} } else {
else { addLoader("MRUARB30");
addLoader("MRUARB30", nullptr);
if (mrupwr2) { if (mrupwr2) {
addLoader("MRUBITS3", nullptr); addLoader("MRUBITS3");
} } else {
else { addLoader("MRUARB40");
addLoader("MRUARB40", nullptr);
} }
} }
addLoader("LXMRU070", nullptr); addLoader("LXMRU070");
if (256==n_mru) { if (256 == n_mru) {
addLoader("MRUBYTE4", nullptr); addLoader("MRUBYTE4");
} else if (mrupwr2) {
addLoader("MRUBITS4");
} else {
addLoader("MRUARB50");
} }
else if (mrupwr2) { addLoader("LXMRU080");
addLoader("MRUBITS4", nullptr); if (256 == n_mru) {
} addLoader("MRUBYTE5");
else { } else {
addLoader("MRUARB50", nullptr); addLoader("MRUARB60");
}
addLoader("LXMRU080", nullptr);
if (256==n_mru) {
addLoader("MRUBYTE5", nullptr);
}
else {
addLoader("MRUARB60", nullptr);
if (mrupwr2) { if (mrupwr2) {
addLoader("MRUBITS5", nullptr); addLoader("MRUBITS5");
} } else {
else { addLoader("MRUARB70");
addLoader("MRUARB70", nullptr);
} }
} }
addLoader("LXMRU090", nullptr); addLoader("LXMRU090");
if (256==n_mru) { if (256 == n_mru) {
addLoader("MRUBYTE6", nullptr); addLoader("MRUBYTE6");
} } else {
else { addLoader("MRUARB80");
addLoader("MRUARB80", nullptr);
if (mrupwr2) { if (mrupwr2) {
addLoader("MRUBITS6", nullptr); addLoader("MRUBITS6");
} } else {
else { addLoader("MRUARB90");
addLoader("MRUARB90", nullptr);
} }
} }
addLoader("LXMRU100", nullptr); addLoader("LXMRU100");
} }
addLoader("LXUNF040", nullptr); addLoader("LXUNF040");
if (n_mru) { if (n_mru) {
addLoader("LXMRU110", nullptr); addLoader("LXMRU110");
} else {
addLoader("LXMRU111");
} }
else { addLoader("LXUNF041");
addLoader("LXMRU111", nullptr); addLoader("LXUNF042");
}
addLoader("LXUNF041", nullptr);
addLoader("LXUNF042", nullptr);
if (n_mru) { if (n_mru) {
addLoader("LXMRU010", nullptr); addLoader("LXMRU010");
if (NOFILT!=f_jmp1 && NOFILT==f_call) { if (NOFILT != f_jmp1 && NOFILT == f_call) {
addLoader("LXJMPA00", nullptr); addLoader("LXJMPA00");
} else {
addLoader("LXCALLB0");
} }
else { addLoader("LXUNF021");
addLoader("LXCALLB0", nullptr); } else {
} addLoader("LXMRU022");
addLoader("LXUNF021", nullptr); if (NOFILT != f_jmp1 && NOFILT == f_call) {
} addLoader("LXJMPA01");
else { } else {
addLoader("LXMRU022", nullptr); addLoader("LXCALLB1");
if (NOFILT!=f_jmp1 && NOFILT==f_call) {
addLoader("LXJMPA01", nullptr);
}
else {
addLoader("LXCALLB1", nullptr);
} }
} }
if (n_mru) { if (n_mru) {
if (256!=n_mru && mrupwr2) { if (256 != n_mru && mrupwr2) {
addLoader("MRUBITS1", nullptr); addLoader("MRUBITS1");
} }
addLoader("LXMRU030", nullptr); addLoader("LXMRU030");
if (256==n_mru) { if (256 == n_mru) {
addLoader("MRUBYTE1", nullptr); addLoader("MRUBYTE1");
} else {
addLoader("MRUARB10");
} }
else { addLoader("LXMRU040");
addLoader("MRUARB10", nullptr);
}
addLoader("LXMRU040", nullptr);
} }
addLoader("LXUNF030", nullptr); addLoader("LXUNF030");
if (NOFILT!=f_jcc2) { if (NOFILT != f_jcc2) {
addLoader("LXJCC000", nullptr); addLoader("LXJCC000");
} }
if (NOFILT!=f_call || NOFILT!=f_jmp1) { // at least one is filtered if (NOFILT != f_call || NOFILT != f_jmp1) { // at least one is filtered
// shift opcode origin to zero // shift opcode origin to zero
if (0==n_mru) { if (0 == n_mru) {
addLoader("LXCJ0MRU", nullptr); addLoader("LXCJ0MRU");
} } else {
else { addLoader("LXCJ1MRU");
addLoader("LXCJ1MRU", nullptr);
} }
// determine if in range // determine if in range
if ((NOFILT!=f_call) && (NOFILT!=f_jmp1)) { // unfilter both if ((NOFILT != f_call) && (NOFILT != f_jmp1)) { // unfilter both
addLoader("LXCALJMP", nullptr); addLoader("LXCALJMP");
} }
if ((NOFILT==f_call) ^ (NOFILT==f_jmp1)) { // unfilter just one if ((NOFILT == f_call) ^ (NOFILT == f_jmp1)) { // unfilter just one
if (0==n_mru) { if (0 == n_mru) {
addLoader("LXCALL00", nullptr); addLoader("LXCALL00");
} } else {
else { addLoader("LXCALL01");
addLoader("LXCALL01", nullptr);
} }
} }
// determine if mru applies // determine if mru applies
if (0==n_mru || ! ((FNOMRU==f_call) || (FNOMRU==f_jmp1)) ) { if (0 == n_mru || !((FNOMRU == f_call) || (FNOMRU == f_jmp1))) {
addLoader("LXCJ2MRU", nullptr); // no mru, or no exceptions // no mru, or no exceptions
} addLoader("LXCJ2MRU");
else { // mru on one, but not the other } else {
addLoader("LXCJ4MRU", nullptr); // mru on one, but not the other
if (MRUFLT==f_jmp1) { // JMP only addLoader("LXCJ4MRU");
addLoader("LXCJ6MRU", nullptr); if (MRUFLT == f_jmp1) { // JMP only
} else addLoader("LXCJ6MRU");
if (MRUFLT==f_call) { // CALL only } else if (MRUFLT == f_call) { // CALL only
addLoader("LXCJ7MRU", nullptr); addLoader("LXCJ7MRU");
} }
addLoader("LXCJ8MRU", nullptr); addLoader("LXCJ8MRU");
} }
} }
addLoader("LXUNF034", nullptr); addLoader("LXUNF034");
if (n_mru) { if (n_mru) {
addLoader("LXMRU055", nullptr); addLoader("LXMRU055");
if (256==n_mru) { if (256 == n_mru) {
addLoader("MRUBYTE2", nullptr); addLoader("MRUBYTE2");
} else if (mrupwr2) {
addLoader("MRUBITS2");
} else if (n_mru) {
addLoader("MRUARB20");
} }
else if (mrupwr2) { addLoader("LXMRU057");
addLoader("MRUBITS2", nullptr);
}
else if (n_mru) {
addLoader("MRUARB20", nullptr);
}
addLoader("LXMRU057", nullptr);
} }
} }
} }
@ -309,15 +267,12 @@ void Packer::addFilter32(int filter_id)
#undef FNOMRU #undef FNOMRU
#undef MRUFLT #undef MRUFLT
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void Packer::defineFilterSymbols(const Filter *ft) void Packer::defineFilterSymbols(const Filter *ft) {
{ if (ft->id == 0) {
if (ft->id == 0)
{
linker->defineSymbol("filter_length", 0); linker->defineSymbol("filter_length", 0);
linker->defineSymbol("filter_cto", 0); linker->defineSymbol("filter_cto", 0);
return; return;
@ -325,33 +280,26 @@ void Packer::defineFilterSymbols(const Filter *ft)
assert(ft->calls > 0); assert(ft->calls > 0);
assert(ft->buf_len > 0); assert(ft->buf_len > 0);
if (ft->id >= 0x40 && ft->id <= 0x4f) if (ft->id >= 0x40 && ft->id <= 0x4f) {
{
linker->defineSymbol("filter_length", ft->buf_len); linker->defineSymbol("filter_length", ft->buf_len);
linker->defineSymbol("filter_cto", ft->cto); linker->defineSymbol("filter_cto", ft->cto);
} } else if (ft->id >= 0x50 && ft->id <= 0x5f) {
else if (ft->id >= 0x50 && ft->id <= 0x5f)
{
linker->defineSymbol("filter_id", ft->id); linker->defineSymbol("filter_id", ft->id);
linker->defineSymbol("filter_cto", ft->cto); linker->defineSymbol("filter_cto", ft->cto);
} } else if ((ft->id & 0xf) % 3 == 0) {
else if ((ft->id & 0xf) % 3 == 0)
{
linker->defineSymbol("filter_length", ft->calls); linker->defineSymbol("filter_length", ft->calls);
linker->defineSymbol("filter_cto", ft->cto); linker->defineSymbol("filter_cto", ft->cto);
} } else {
else
{
linker->defineSymbol("filter_length", ft->lastcall - ft->calls * 4); linker->defineSymbol("filter_length", ft->lastcall - ft->calls * 4);
linker->defineSymbol("filter_cto", ft->cto); linker->defineSymbol("filter_cto", ft->cto);
} }
#if 0 #if 0
if (0x80==(ft->id & 0xF0)) { if (0x80 == (ft->id & 0xF0)) {
int const mru = ph.n_mru ? 1+ ph.n_mru : 0; int const mru = ph.n_mru ? 1 + ph.n_mru : 0;
if (mru && mru!=256) { if (mru && mru != 256) {
unsigned const is_pwr2 = (0==((mru -1) & mru)); unsigned const is_pwr2 = (0 == ((mru - 1) & mru));
//patch_le32(0x80 + (char *)loader, lsize - 0x80, "NMRU", mru - is_pwr2); // patch_le32(0x80 + (char *) loader, lsize - 0x80, "NMRU", mru - is_pwr2);
} }
} }
#endif #endif

View File

@ -33,52 +33,29 @@
#include "linker.h" #include "linker.h"
#define FILLVAL 0 #define FILLVAL 0
#define import my_import // "import" is a keyword since C++20
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
#if (WITH_XSPAN >= 2) && 1 #define IPTR_VAR(type, var, first) SPAN_S_VAR(type, var, first, ibuf)
// #define IPTR(type, var) Span<type> var(ibuf, ibuf.getSize(), ibuf) #define OPTR_VAR(type, var, first) SPAN_S_VAR(type, var, first, obuf)
// #define OPTR(type, var) Span<type> var(obuf, obuf.getSize(), obuf) #define IPTR_VAR_OFFSET(type, var, offset) \
#define IPTR_I_D(type, var, disp) \ SPAN_S_VAR(type, var, ibuf + (offset), ibuf.getSize() - (offset), ibuf + (offset))
Span<type> var(ibuf + (disp), ibuf.getSize() - (disp), ibuf + (disp))
#define IPTR_I(type, var, first) Span<type> var(first, ibuf)
#define OPTR_I(type, var, first) Span<type> var(first, obuf)
#define IPTR_C(type, var, first) const Span<type> var(first, ibuf)
#define OPTR_C(type, var, first) const Span<type> var(first, obuf)
#else
#include "util/bptr.h"
// #define IPTR(type, var) BoundedPtr<type> var(ibuf, ibuf.getSize())
// #define OPTR(type, var) BoundedPtr<type> var(obuf, obuf.getSize())
#define IPTR_I_D(type, var, disp) \
BoundedPtr<type> var(ibuf + (disp), ibuf.getSize() - (disp), ibuf + (disp))
#define IPTR_I(type, var, first) BoundedPtr<type> var(ibuf, ibuf.getSize(), first)
#define OPTR_I(type, var, first) BoundedPtr<type> var(obuf, obuf.getSize(), first)
#define IPTR_C(type, var, first) const BoundedPtr<type> var(ibuf, ibuf.getSize(), first)
#define OPTR_C(type, var, first) const BoundedPtr<type> var(obuf, obuf.getSize(), first)
#endif
static void xcheck(const void *p) { static void xcheck(const void *p) {
if (!p) if very_unlikely (p == nullptr)
throwCantUnpack("xcheck unexpected nullptr pointer; take care!"); throwCantUnpack("xcheck unexpected nullptr pointer; take care!");
} }
static void xcheck(const void *p, size_t plen, const void *b, size_t blen) { static void xcheck(const void *p, size_t plen, const void *b, size_t blen) {
const char *pp = (const char *) p; const char *pp = (const char *) p;
const char *bb = (const char *) b; const char *bb = (const char *) b;
if (pp < bb || pp > bb + blen || pp + plen > bb + blen) if very_unlikely (pp < bb || pp > bb + blen || pp + plen > bb + blen)
throwCantUnpack("xcheck pointer out of range; take care!"); throwCantUnpack("xcheck pointer out of range; take care!");
} }
#if 0 #define ICHECK(p, bytes) xcheck(raw_bytes(p, 0), bytes, ibuf, ibuf.getSize())
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen) #define OCHECK(p, bytes) xcheck(raw_bytes(p, 0), bytes, obuf, obuf.getSize())
{
ACC_UNUSED(b);
if (poff > blen || poff + plen > blen)
throwCantUnpack("xcheck pointer out of range; take care!");
}
#endif
#define ICHECK(x, size) xcheck(raw_bytes(x, 0), size, ibuf, ibuf.getSize())
#define OCHECK(x, size) xcheck(raw_bytes(x, 0), size, obuf, obuf.getSize())
// #define imemset(a,b,c) ICHECK(a,c), memset(a,b,c) // #define imemset(a,b,c) ICHECK(a,c), memset(a,b,c)
// #define omemset(a,b,c) OCHECK(a,c), memset(a,b,c) // #define omemset(a,b,c) OCHECK(a,c), memset(a,b,c)
@ -892,15 +869,15 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
soimport += strlen(dlls[ic].name) + 1 + 4; soimport += strlen(dlls[ic].name) + 1 + 4;
for (IPTR_I(LEXX, tarr, dlls[ic].lookupt); *tarr; tarr += 1) { for (IPTR_VAR(const LEXX, tarr, dlls[ic].lookupt); *tarr; tarr += 1) {
if (*tarr & ord_mask) { if (*tarr & ord_mask) {
importbyordinal = true; importbyordinal = true;
soimport += 2; // ordinal num: 2 bytes soimport += 2; // ordinal num: 2 bytes
dlls[ic].ordinal = *tarr & 0xffff; dlls[ic].ordinal = *tarr & 0xffff;
} else // it's an import by name } else // it's an import by name
{ {
IPTR_I(const upx_byte, n, ibuf + *tarr + 2); IPTR_VAR(const upx_byte, const name, ibuf + *tarr + 2);
unsigned len = strlen(n); unsigned len = strlen(name);
soimport += len + 1; soimport += len + 1;
if (dlls[ic].shname == nullptr || len < strlen(dlls[ic].shname)) if (dlls[ic].shname == nullptr || len < strlen(dlls[ic].shname))
dlls[ic].shname = ibuf + *tarr + 2; dlls[ic].shname = ibuf + *tarr + 2;
@ -1462,6 +1439,7 @@ PeFile::Resource::Resource(const upx_byte *p, const upx_byte *ibufstart_,
const upx_byte *ibufend_) { const upx_byte *ibufend_) {
ibufstart = ibufstart_; ibufstart = ibufstart_;
ibufend = ibufend_; ibufend = ibufend_;
newstart = nullptr;
init(p); init(p);
} }
@ -1945,7 +1923,7 @@ void PeFile::readSectionHeaders(unsigned objs, unsigned sizeof_ih) {
if (objs == 0) if (objs == 0)
return; return;
mb_isection.alloc(mem_size(sizeof(pe_section_t), objs)); mb_isection.alloc(mem_size(sizeof(pe_section_t), objs));
isection = mb_isection; // => isection now is a SPAN_S isection = SPAN_S_MAKE(pe_section_t, mb_isection); // => isection now is a SPAN_S
if (file_size_u < pe_offset + sizeof_ih + sizeof(pe_section_t) * objs) { if (file_size_u < pe_offset + sizeof_ih + sizeof(pe_section_t) * objs) {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "too many sections %d", objs); snprintf(buf, sizeof(buf), "too many sections %d", objs);
@ -2599,7 +2577,7 @@ void PeFile::rebuildRelocs(SPAN_S(upx_byte) & extrainfo, unsigned bits, unsigned
SPAN_S_VAR(upx_byte, const wrkmem, mb_wrkmem); SPAN_S_VAR(upx_byte, const wrkmem, mb_wrkmem);
for (unsigned ic = 0; ic < relocn; ic++) { for (unsigned ic = 0; ic < relocn; ic++) {
OPTR_I(upx_byte, p, obuf + get_le32(wrkmem + 4 * ic)); OPTR_VAR(upx_byte, const p, obuf + get_le32(wrkmem + 4 * ic));
if (bits == 32) if (bits == 32)
set_le32(p, get_le32(p) + imagebase + rvamin); set_le32(p, get_le32(p) + imagebase + rvamin);
else else
@ -2648,8 +2626,8 @@ void PeFile::rebuildResources(SPAN_S(upx_byte) & extrainfo, unsigned lastvaddr)
Resource res(r + vaddr, ibuf, ibuf + ibuf.getSize()); Resource res(r + vaddr, ibuf, ibuf + ibuf.getSize());
while (res.next()) while (res.next())
if (res.offs() > vaddr) { if (res.offs() > vaddr) {
ICHECK(r + res.offs() - 4, 4); ICHECK(r + (res.offs() - 4), 4);
unsigned origoffs = get_le32(r + res.offs() - 4); unsigned origoffs = get_le32(r + (res.offs() - 4));
res.newoffs() = origoffs; res.newoffs() = origoffs;
omemcpy(obuf + (origoffs - rvamin), r + res.offs(), res.size()); omemcpy(obuf + (origoffs - rvamin), r + res.offs(), res.size());
if (icondir_count && res.itype() == RT_GROUP_ICON) { if (icondir_count && res.itype() == RT_GROUP_ICON) {
@ -2671,14 +2649,14 @@ void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, b
if (ODADDR(PEDIR_IMPORT) == 0 || ODSIZE(PEDIR_IMPORT) <= sizeof(import_desc)) if (ODADDR(PEDIR_IMPORT) == 0 || ODSIZE(PEDIR_IMPORT) <= sizeof(import_desc))
return; return;
OPTR_C(const upx_byte, idata, obuf + get_le32(extrainfo)); OPTR_VAR(const upx_byte, const imdata, obuf + get_le32(extrainfo));
const unsigned inamespos = get_le32(extrainfo + 4); const unsigned inamespos = get_le32(extrainfo + 4);
extrainfo += 8; extrainfo += 8;
unsigned sdllnames = 0; unsigned sdllnames = 0;
IPTR_I_D(const upx_byte, import, IDADDR(PEDIR_IMPORT) - isection[2].vaddr); IPTR_VAR_OFFSET(const upx_byte, const import, IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
OPTR_I(const upx_byte, p, raw_bytes(idata, 4)); OPTR_VAR(const upx_byte, p, raw_bytes(imdata, 4));
for (; get_le32(p) != 0; ++p) { for (; get_le32(p) != 0; ++p) {
const upx_byte *dname = raw_bytes(import + get_le32(p), 1); const upx_byte *dname = raw_bytes(import + get_le32(p), 1);
@ -2688,7 +2666,7 @@ void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, b
sdllnames += dlen + 1; sdllnames += dlen + 1;
for (p += 8; *p;) for (p += 8; *p;)
if (*p == 1) if (*p == 1)
p += strlen(++p) + 1; p += 1 + strlen(p + 1) + 1;
else if (*p == 0xff) else if (*p == 0xff)
p += 3; // ordinal p += 3; // ordinal
else else
@ -2712,7 +2690,7 @@ void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, b
SPAN_0_VAR(upx_byte, const importednames_start, importednames); SPAN_0_VAR(upx_byte, const importednames_start, importednames);
#endif #endif
for (p = idata; get_le32(p) != 0; ++p) { for (p = imdata; get_le32(p) != 0; ++p) {
// restore the name of the dll // restore the name of the dll
const upx_byte *dname = raw_bytes(import + get_le32(p), 1); const upx_byte *dname = raw_bytes(import + get_le32(p), 1);
const unsigned dlen = strlen(dname); const unsigned dlen = strlen(dname);
@ -2722,7 +2700,7 @@ void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, b
if (inamespos) { if (inamespos) {
// now I rebuild the dll names // now I rebuild the dll names
omemcpy(dllnames, dname, dlen + 1); omemcpy(dllnames, dname, dlen + 1);
im->dllname = ptr_diff_bytes(dllnames, Obuf); im->dllname = ptr_udiff_bytes(dllnames, Obuf);
//;;;printf("\ndll: %s:",dllnames); //;;;printf("\ndll: %s:",dllnames);
dllnames += dlen + 1; dllnames += dlen + 1;
} else { } else {
@ -2732,18 +2710,18 @@ void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, b
if (set_oft) if (set_oft)
im->oft = iatoffs; im->oft = iatoffs;
OPTR_I(LEXX, newiat, (LEXX *) (Obuf + iatoffs)); OPTR_VAR(LEXX, newiat, (LEXX *) (Obuf + iatoffs));
// restore the imported names+ordinals // restore the imported names+ordinals
for (p += 8; *p; ++newiat) for (p += 8; *p; ++newiat)
if (*p == 1) { if (*p == 1) {
const unsigned ilen = strlen(++p) + 1; const unsigned ilen = strlen(++p) + 1;
if (inamespos) { if (inamespos) {
if (ptr_diff_bytes(importednames, importednames_start) & 1) if (ptr_udiff_bytes(importednames, importednames_start) & 1)
importednames -= 1; importednames -= 1;
omemcpy(importednames + 2, p, ilen); omemcpy(importednames + 2, p, ilen);
//;;;printf(" %s",importednames+2); //;;;printf(" %s",importednames+2);
*newiat = ptr_diff_bytes(importednames, Obuf); *newiat = ptr_udiff_bytes(importednames, Obuf);
importednames += 2 + ilen; importednames += 2 + ilen;
} else { } else {
// Beware overlap! // Beware overlap!
@ -2762,7 +2740,7 @@ void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, b
*newiat = 0; *newiat = 0;
im++; im++;
} }
// memset(idata,0,p - idata); // memset(imdata, 0, ptr_udiff_bytes(p, imdata));
} }
template <typename ht, typename LEXX, typename ord_mask_t> template <typename ht, typename LEXX, typename ord_mask_t>
@ -2864,16 +2842,16 @@ void PeFile::unpack0(OutputFile *fo, const ht &ih, ht &oh, ord_mask_t ord_mask,
// write decompressed file // write decompressed file
if (fo) { if (fo) {
unsigned ic; unsigned ic = 0;
for (ic = 0; ic < objs && osection[ic].rawdataptr == 0; ic++) while (ic < objs && osection[ic].rawdataptr == 0)
; ic++;
ibuf.dealloc(); ibuf.dealloc();
ibuf.alloc(osection[ic].rawdataptr); ibuf.alloc(osection[ic].rawdataptr);
ibuf.clear(); ibuf.clear();
infoHeader("[Writing uncompressed file]"); infoHeader("[Writing uncompressed file]");
// write loader + compressed file // write header + decompressed file
fo->write(&oh, sizeof(oh)); fo->write(&oh, sizeof(oh));
fo->write(osection, objs * sizeof(pe_section_t)); fo->write(osection, objs * sizeof(pe_section_t));
fo->write(ibuf, osection[ic].rawdataptr - fo->getBytesWritten()); fo->write(ibuf, osection[ic].rawdataptr - fo->getBytesWritten());
@ -2891,7 +2869,7 @@ int PeFile::canUnpack0(unsigned max_sections, unsigned objs, unsigned ih_entry,
if (objs < min_sections) if (objs < min_sections)
return -1; return -1;
mb_isection.alloc(mem_size(sizeof(pe_section_t), objs)); mb_isection.alloc(mem_size(sizeof(pe_section_t), objs));
isection = mb_isection; // => isection now is a SPAN_S isection = SPAN_S_MAKE(pe_section_t, mb_isection); // => isection now is a SPAN_S
fi->seek(pe_offset + ih_size, SEEK_SET); fi->seek(pe_offset + ih_size, SEEK_SET);
fi->readx(isection, sizeof(pe_section_t) * objs); fi->readx(isection, sizeof(pe_section_t) * objs);
bool is_packed = (objs <= max_sections && (IDSIZE(15) || ih_entry > isection[1].vaddr)); bool is_packed = (objs <= max_sections && (IDSIZE(15) || ih_entry > isection[1].vaddr));

View File

@ -25,6 +25,9 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
// INFO: not thread-safe; assumes a single UiPacker instance that
// is exclusively called from main thread
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
#include "packer.h" #include "packer.h"
@ -92,19 +95,14 @@ unsigned UiPacker::update_fu_len = 0;
**************************************************************************/ **************************************************************************/
static const char header_line1[] = " File size Ratio Format Name\n"; static const char header_line1[] = " File size Ratio Format Name\n";
static char header_line2[] = " -------------------- ------ ----------- -----------\n"; static const char header_line2[] = " -------------------- ------ ----------- -----------\n";
static char progress_filler[4 + 1] = ".*[]"; static const char progress_filler[4 + 1] = ".*[]";
static void init_global_constants(void) { static void init_global_constants(void) noexcept {
#if 0 && (ACC_OS_DOS16 || ACC_OS_DOS32) #if 0 && (ACC_OS_DOS16 || ACC_OS_DOS32)
// FIXME: should test codepage here // FIXME: should test codepage here
static bool done = false;
if (done)
return;
done = true;
#if 1 && (ACC_OS_DOS32) && defined(__DJGPP__) #if 1 && (ACC_OS_DOS32) && defined(__DJGPP__)
/* check for Windows NT/2000/XP */ /* check for Windows NT/2000/XP */
if (_get_dos_version(1) == 0x0532) if (_get_dos_version(1) == 0x0532)
@ -158,7 +156,8 @@ static const char *mkline(upx_uint64_t fu_len, upx_uint64_t fc_len, upx_uint64_t
**************************************************************************/ **************************************************************************/
UiPacker::UiPacker(const Packer *p_) : ui_pass(0), ui_total_passes(0), p(p_), s(nullptr) { UiPacker::UiPacker(const Packer *p_) : ui_pass(0), ui_total_passes(0), p(p_), s(nullptr) {
init_global_constants(); static upx_std_once_flag init_done;
upx_std_call_once(init_done, init_global_constants);
cb.reset(); cb.reset();

View File

@ -1,155 +0,0 @@
/* bptr.h --
This file is part of the UPX executable compressor.
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2023 Laszlo Molnar
All Rights Reserved.
UPX and the UCL library are free software; you can redistribute them
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer Laszlo Molnar
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
#pragma once
#ifndef UPX_BPTR_H__
#define UPX_BPTR_H__ 1
#if WITH_XSPAN >= 2
#error "this file is deprecated, please use xspan.h instead"
#endif
/*************************************************************************
// BoundedPtr
**************************************************************************/
template <class T>
class BoundedPtr {
public:
typedef T element_type;
typedef typename std::add_pointer<T>::type pointer;
~BoundedPtr() {}
BoundedPtr(void *base, size_t size_in_bytes, T *ptr = nullptr)
: ptr_(ptr), base_(base), size_in_bytes_(0) {
assert(base_ != nullptr);
size_in_bytes_ = mem_size(1, size_in_bytes);
check();
}
// assignment
BoundedPtr &operator=(const BoundedPtr &other) {
assert(base_ == other.base_);
assert(size_in_bytes_ == other.size_in_bytes_);
ptr_ = other.ptr_;
check();
return *this;
}
BoundedPtr &operator=(T *other) {
ptr_ = other;
check();
return *this;
}
// dereference
T &operator*() {
checkNULL();
checkRange(ptr_ + 1);
return *ptr_;
}
const T &operator*() const {
checkNULL();
checkRange(ptr_ + 1);
return *ptr_;
}
operator T *() { return ptr_; }
operator const T *() const { return ptr_; }
BoundedPtr &operator+=(size_t n) {
checkNULL();
ptr_ += n;
checkRange();
return *this;
}
BoundedPtr &operator-=(size_t n) {
checkNULL();
ptr_ -= n;
checkRange();
return *this;
}
BoundedPtr &operator++(void) {
checkNULL();
ptr_ += 1;
checkRange();
return *this;
}
T *raw_bytes(size_t bytes) const {
checkNULL();
if (bytes > 0)
checkRange((const char *) (const void *) ptr_ + bytes);
return ptr_;
}
private:
void checkNULL() const {
if very_unlikely (!ptr_)
throwCantUnpack("unexpected NULL pointer; take care!");
}
forceinline void checkRange() const { checkRange(ptr_, base_, size_in_bytes_); }
forceinline void checkRange(const void *p) const { checkRange(p, base_, size_in_bytes_); }
static void checkRange(const void *ptr, const void *base, size_t size_in_bytes) {
size_t off = (const char *) ptr - (const char *) base;
if very_unlikely (off > size_in_bytes)
throwCantUnpack("pointer out of range; take care!");
}
void check() const { // check ptr_ invariant: either NULL or valid checkRange()
if (ptr_ != nullptr)
checkRange();
}
T *ptr_;
void *base_;
size_t size_in_bytes_;
// disable copy
BoundedPtr(const BoundedPtr &) = delete;
// disable dynamic allocation
ACC_CXX_DISABLE_NEW_DELETE
// disable taking the address => force passing by reference
// [I'm not too sure about this design decision, but we can always allow it if needed]
BoundedPtr<T> *operator&() const = delete;
};
// raw_bytes overload
template <class T>
inline typename BoundedPtr<T>::pointer raw_bytes(const BoundedPtr<T> &a, size_t size_in_bytes) {
return a.raw_bytes(size_in_bytes);
}
template <class T>
inline typename BoundedPtr<T>::pointer raw_index_bytes(const BoundedPtr<T> &a, size_t index,
size_t size_in_bytes) {
typedef typename BoundedPtr<T>::element_type element_type;
return raw_bytes(a, mem_size(sizeof(element_type), index, size_in_bytes)) + index;
}
#endif /* already included */
/* vim:set ts=4 sw=4 et: */

View File

@ -47,18 +47,19 @@ unsigned membuffer_get_size(MemBuffer &mb) { return mb.getSize(); }
#if defined(__SANITIZE_ADDRESS__) #if defined(__SANITIZE_ADDRESS__)
static forceinline constexpr bool use_simple_mcheck() { return false; } static forceinline constexpr bool use_simple_mcheck() { return false; }
#elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND) #elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND)
static int use_simple_mcheck_flag = -1; static bool use_simple_mcheck_flag;
static noinline void use_simple_mcheck_init() { static noinline void init_use_simple_mcheck() noexcept {
use_simple_mcheck_flag = 1; bool r = true;
if (RUNNING_ON_VALGRIND) { if (RUNNING_ON_VALGRIND) {
use_simple_mcheck_flag = 0; r = false;
// fprintf(stderr, "upx: detected RUNNING_ON_VALGRIND\n"); NO_fprintf(stderr, "upx: detected RUNNING_ON_VALGRIND\n");
} }
use_simple_mcheck_flag = r;
} }
static forceinline bool use_simple_mcheck() { static bool use_simple_mcheck() {
if very_unlikely (use_simple_mcheck_flag < 0) static upx_std_once_flag init_done;
use_simple_mcheck_init(); upx_std_call_once(init_done, init_use_simple_mcheck);
return (bool) use_simple_mcheck_flag; return use_simple_mcheck_flag;
} }
#else #else
static forceinline constexpr bool use_simple_mcheck() { return true; } static forceinline constexpr bool use_simple_mcheck() { return true; }
@ -68,8 +69,8 @@ static forceinline constexpr bool use_simple_mcheck() { return true; }
// //
**************************************************************************/ **************************************************************************/
MemBuffer::MemBuffer(upx_uint64_t size_in_bytes) { MemBuffer::MemBuffer(upx_uint64_t bytes) {
alloc(size_in_bytes); alloc(bytes);
debug_set(debug.last_return_address_alloc, upx_return_address()); debug_set(debug.last_return_address_alloc, upx_return_address());
} }
@ -80,7 +81,7 @@ MemBuffer::~MemBuffer() { this->dealloc(); }
void *MemBuffer::subref_impl(const char *errfmt, size_t skip, size_t take) { void *MemBuffer::subref_impl(const char *errfmt, size_t skip, size_t take) {
debug_set(debug.last_return_address_subref, upx_return_address()); debug_set(debug.last_return_address_subref, upx_return_address());
// check overrun and wrap-around // check overrun and wrap-around
if (skip + take > b_size_in_bytes || skip + take < skip) { if (skip + take > size_in_bytes || skip + take < skip) {
char buf[100]; char buf[100];
// printf is using unsigned formatting // printf is using unsigned formatting
if (!errfmt || !errfmt[0]) if (!errfmt || !errfmt[0])
@ -88,7 +89,7 @@ void *MemBuffer::subref_impl(const char *errfmt, size_t skip, size_t take) {
snprintf(buf, sizeof(buf), errfmt, (unsigned) skip, (unsigned) take); snprintf(buf, sizeof(buf), errfmt, (unsigned) skip, (unsigned) take);
throwCantPack(buf); throwCantPack(buf);
} }
return &b[skip]; return ptr + skip;
} }
static unsigned width(unsigned x) { static unsigned width(unsigned x) {
@ -116,62 +117,55 @@ static unsigned width(unsigned x) {
return 1 + w; return 1 + w;
} }
static inline unsigned umax(unsigned a, unsigned b) { return (a >= b) ? a : b; } static forceinline size_t umax(size_t a, size_t b) { return (a >= b) ? a : b; }
unsigned MemBuffer::getSizeForCompression(unsigned uncompressed_size, unsigned extra) { unsigned MemBuffer::getSizeForCompression(unsigned uncompressed_size, unsigned extra) {
if (uncompressed_size == 0) if (uncompressed_size == 0)
throwCantPack("invalid uncompressed_size"); throwCantPack("invalid uncompressed_size");
const unsigned z = uncompressed_size; // fewer keystrokes and display columns const size_t z = uncompressed_size; // fewer keystrokes and display columns
const unsigned w = umax(8, width(z - 1)); // ignore tiny offsets const size_t w = umax(8, width(z - 1)); // ignore tiny offsets
unsigned bytes = ACC_ICONV(unsigned, mem_size(1, z)); // check size_t bytes = mem_size(1, z); // check size
// Worst matching: All match at max_offset, which implies 3==min_match // Worst matching: All match at max_offset, which implies 3==min_match
// All literal: 1 bit overhead per literal byte // All literal: 1 bit overhead per literal byte; from UCL documentation
bytes = umax(bytes, z + z / 8); bytes = umax(bytes, z + z / 8 + 256);
// NRV2B: 1 byte plus 2 bits per width exceeding 8 ("ss11") // NRV2B: 1 byte plus 2 bits per width exceeding 8 ("ss11")
bytes = umax(bytes, (z / 3 * (8 + 2 * (w - 8) / 1)) / 8); bytes = umax(bytes, (z / 3 * (8 + 2 * (w - 8) / 1)) / 8);
// NRV2E: 1 byte plus 3 bits per pair of width exceeding 7 ("ss12") // NRV2E: 1 byte plus 3 bits per pair of width exceeding 7 ("ss12")
bytes = umax(bytes, (z / 3 * (8 + 3 * (w - 7) / 2)) / 8); bytes = umax(bytes, (z / 3 * (8 + 3 * (w - 7) / 2)) / 8);
// zstd: ZSTD_COMPRESSBOUND // zstd: ZSTD_COMPRESSBOUND
bytes = umax(bytes, z + (z >> 8) + ((z < (128 << 10)) ? (((128 << 10) - z) >> 11) : 0)); bytes = umax(bytes, z + (z >> 8) + ((z < (128 << 10)) ? (((128 << 10) - z) >> 11) : 0));
// extra + 256 safety for rounding // add extra and 256 safety for various rounding/alignments
bytes = mem_size(1, bytes, extra, 256); bytes = mem_size(1, bytes, extra, 256);
UNUSED(w); UNUSED(w);
return bytes; return ACC_ICONV(unsigned, bytes);
} }
unsigned MemBuffer::getSizeForDecompression(unsigned uncompressed_size, unsigned extra) { unsigned MemBuffer::getSizeForDecompression(unsigned uncompressed_size, unsigned extra) {
if (uncompressed_size == 0) if (uncompressed_size == 0)
throwCantPack("invalid uncompressed_size"); throwCantPack("invalid uncompressed_size");
size_t bytes = mem_size(1, uncompressed_size, extra); // check size_t bytes = mem_size(1, uncompressed_size, extra); // check size
return ACC_ICONV(unsigned, bytes); return ACC_ICONV(unsigned, bytes);
} }
void MemBuffer::allocForCompression(unsigned uncompressed_size, unsigned extra) { void MemBuffer::allocForCompression(unsigned uncompressed_size, unsigned extra) {
if (uncompressed_size == 0) unsigned bytes = getSizeForCompression(uncompressed_size, extra);
throwCantPack("invalid uncompressed_size"); alloc(bytes);
unsigned size = getSizeForCompression(uncompressed_size, extra);
alloc(size);
debug_set(debug.last_return_address_alloc, upx_return_address()); debug_set(debug.last_return_address_alloc, upx_return_address());
} }
void MemBuffer::allocForDecompression(unsigned uncompressed_size, unsigned extra) { void MemBuffer::allocForDecompression(unsigned uncompressed_size, unsigned extra) {
if (uncompressed_size == 0) unsigned bytes = getSizeForDecompression(uncompressed_size, extra);
throwCantPack("invalid uncompressed_size"); alloc(bytes);
unsigned size = getSizeForDecompression(uncompressed_size, extra);
alloc(size);
debug_set(debug.last_return_address_alloc, upx_return_address()); debug_set(debug.last_return_address_alloc, upx_return_address());
} }
void MemBuffer::fill(unsigned off, unsigned len, int value) { void MemBuffer::fill(unsigned off, unsigned len, int value) {
debug_set(debug.last_return_address_fill, upx_return_address()); debug_set(debug.last_return_address_fill, upx_return_address());
checkState(); checkState();
assert((int) off >= 0); if (off > size_in_bytes || len > size_in_bytes || off + len > size_in_bytes)
assert((int) len >= 0); throwCantPack("MemBuffer::fill out of range; take care!");
assert(off <= b_size_in_bytes);
assert(len <= b_size_in_bytes);
assert(off + len <= b_size_in_bytes);
if (len > 0) if (len > 0)
memset(b + off, value, len); memset(ptr + off, value, len);
} }
/************************************************************************* /*************************************************************************
@ -183,22 +177,22 @@ void MemBuffer::fill(unsigned off, unsigned len, int value) {
#define MAGIC2(p) ((PTR_BITS(p) ^ 0xfefdbeeb ^ 0x80024011) | 1) #define MAGIC2(p) ((PTR_BITS(p) ^ 0xfefdbeeb ^ 0x80024011) | 1)
void MemBuffer::checkState() const { void MemBuffer::checkState() const {
if (!b) if (!ptr)
throwInternalError("block not allocated"); throwInternalError("block not allocated");
if (use_simple_mcheck()) { if (use_simple_mcheck()) {
if (get_ne32(b - 4) != MAGIC1(b)) if (get_ne32(ptr - 4) != MAGIC1(ptr))
throwInternalError("memory clobbered before allocated block 1"); throwInternalError("memory clobbered before allocated block 1");
if (get_ne32(b - 8) != b_size_in_bytes) if (get_ne32(ptr - 8) != size_in_bytes)
throwInternalError("memory clobbered before allocated block 2"); throwInternalError("memory clobbered before allocated block 2");
if (get_ne32(b + b_size_in_bytes) != MAGIC2(b)) if (get_ne32(ptr + size_in_bytes) != MAGIC2(ptr))
throwInternalError("memory clobbered past end of allocated block"); throwInternalError("memory clobbered past end of allocated block");
} }
} }
void MemBuffer::alloc(upx_uint64_t size) { void MemBuffer::alloc(upx_uint64_t size) {
// NOTE: we don't automatically free a used buffer // NOTE: we don't automatically free a used buffer
assert(b == nullptr); assert(ptr == nullptr);
assert(b_size_in_bytes == 0); assert(size_in_bytes == 0);
// //
assert(size > 0); assert(size > 0);
debug_set(debug.last_return_address_alloc, upx_return_address()); debug_set(debug.last_return_address_alloc, upx_return_address());
@ -207,44 +201,44 @@ void MemBuffer::alloc(upx_uint64_t size) {
NO_printf("MemBuffer::alloc %llu: %p\n", size, p); NO_printf("MemBuffer::alloc %llu: %p\n", size, p);
if (!p) if (!p)
throwOutOfMemoryException(); throwOutOfMemoryException();
b = p; ptr = p;
b_size_in_bytes = ACC_ICONV(unsigned, size); size_in_bytes = ACC_ICONV(unsigned, size);
if (use_simple_mcheck()) { if (use_simple_mcheck()) {
b = p + 16; ptr = p + 16;
// store magic constants to detect buffer overruns // store magic constants to detect buffer overruns
set_ne32(b - 8, b_size_in_bytes); set_ne32(ptr - 8, size_in_bytes);
set_ne32(b - 4, MAGIC1(b)); set_ne32(ptr - 4, MAGIC1(ptr));
set_ne32(b + b_size_in_bytes, MAGIC2(b)); set_ne32(ptr + size_in_bytes, MAGIC2(ptr));
set_ne32(b + b_size_in_bytes + 4, stats.global_alloc_counter); set_ne32(ptr + size_in_bytes + 4, stats.global_alloc_counter);
} }
#if !defined(__SANITIZE_ADDRESS__) && 0 #if !defined(__SANITIZE_ADDRESS__) && 0
fill(0, b_size_in_bytes, (rand() & 0xff) | 1); // debug fill(0, size_in_bytes, (rand() & 0xff) | 1); // debug
(void) VALGRIND_MAKE_MEM_UNDEFINED(b, b_size_in_bytes); (void) VALGRIND_MAKE_MEM_UNDEFINED(ptr, size_in_bytes);
#endif #endif
stats.global_alloc_counter += 1; stats.global_alloc_counter += 1;
stats.global_total_bytes += b_size_in_bytes; stats.global_total_bytes += size_in_bytes;
stats.global_total_active_bytes += b_size_in_bytes; stats.global_total_active_bytes += size_in_bytes;
} }
void MemBuffer::dealloc() { void MemBuffer::dealloc() {
if (b != nullptr) { if (ptr != nullptr) {
debug_set(debug.last_return_address_dealloc, upx_return_address()); debug_set(debug.last_return_address_dealloc, upx_return_address());
checkState(); checkState();
stats.global_total_active_bytes -= b_size_in_bytes; stats.global_total_active_bytes -= size_in_bytes;
if (use_simple_mcheck()) { if (use_simple_mcheck()) {
// clear magic constants // clear magic constants
set_ne32(b - 8, 0); set_ne32(ptr - 8, 0);
set_ne32(b - 4, 0); set_ne32(ptr - 4, 0);
set_ne32(b + b_size_in_bytes, 0); set_ne32(ptr + size_in_bytes, 0);
set_ne32(b + b_size_in_bytes + 4, 0); set_ne32(ptr + size_in_bytes + 4, 0);
// //
::free(b - 16); ::free(ptr - 16);
} else } else
::free(b); ::free(ptr);
b = nullptr; ptr = nullptr;
b_size_in_bytes = 0; size_in_bytes = 0;
} else { } else {
assert(b_size_in_bytes == 0); assert(size_in_bytes == 0);
} }
} }
@ -264,9 +258,11 @@ TEST_CASE("MemBuffer") {
CHECK(raw_bytes(mb, 64) == mb.getVoidPtr()); CHECK(raw_bytes(mb, 64) == mb.getVoidPtr());
CHECK_THROWS(raw_bytes(mb, 65)); CHECK_THROWS(raw_bytes(mb, 65));
CHECK_NOTHROW(mb + 64); CHECK_NOTHROW(mb + 64);
CHECK_NOTHROW(64 + mb);
CHECK_THROWS(mb + 65); CHECK_THROWS(mb + 65);
#if ALLOW_INT_PLUS_MEMBUFFER
CHECK_NOTHROW(64 + mb);
CHECK_THROWS(65 + mb); CHECK_THROWS(65 + mb);
#endif
if (use_simple_mcheck()) { if (use_simple_mcheck()) {
upx_byte *b = raw_bytes(mb, 0); upx_byte *b = raw_bytes(mb, 0);
unsigned magic1 = get_ne32(b - 4); unsigned magic1 = get_ne32(b - 4);
@ -280,9 +276,9 @@ TEST_CASE("MemBuffer") {
TEST_CASE("MemBuffer::getSizeForCompression") { TEST_CASE("MemBuffer::getSizeForCompression") {
CHECK_THROWS(MemBuffer::getSizeForCompression(0)); CHECK_THROWS(MemBuffer::getSizeForCompression(0));
CHECK_THROWS(MemBuffer::getSizeForDecompression(0)); CHECK_THROWS(MemBuffer::getSizeForDecompression(0));
CHECK(MemBuffer::getSizeForCompression(1) == 320); CHECK(MemBuffer::getSizeForCompression(1) == 513);
CHECK(MemBuffer::getSizeForCompression(256) == 576); CHECK(MemBuffer::getSizeForCompression(256) == 800);
CHECK(MemBuffer::getSizeForCompression(1024) == 1408); CHECK(MemBuffer::getSizeForCompression(1024) == 1664);
// CHECK(MemBuffer::getSizeForCompression(1024 * 1024) == 0); // TODO // CHECK(MemBuffer::getSizeForCompression(1024 * 1024) == 0); // TODO
// CHECK(MemBuffer::getSizeForCompression(UPX_RSIZE_MAX) == 0); // TODO // CHECK(MemBuffer::getSizeForCompression(UPX_RSIZE_MAX) == 0); // TODO
} }

View File

@ -37,18 +37,20 @@ template <class T>
class MemBufferBase { class MemBufferBase {
public: public:
typedef T element_type; typedef T element_type;
typedef typename std::add_lvalue_reference<T>::type reference;
typedef typename std::add_pointer<T>::type pointer; typedef typename std::add_pointer<T>::type pointer;
typedef unsigned size_type;
protected: protected:
pointer b; pointer ptr;
unsigned b_size_in_bytes; size_type size_in_bytes;
public: public:
MemBufferBase() : b(nullptr), b_size_in_bytes(0) {} MemBufferBase() : ptr(nullptr), size_in_bytes(0) {}
// NOTE: implicit conversion to underlying pointer // NOTE: implicit conversion to underlying pointer
// NOTE: for fully bound-checked pointer use XSPAN_S from xspan.h // NOTE: for fully bound-checked pointer use XSPAN_S from xspan.h
operator pointer() const { return b; } operator pointer() const { return ptr; }
template <class U> template <class U>
typename std::enable_if<std::is_integral<U>::value, pointer>::type operator+(U n) const { typename std::enable_if<std::is_integral<U>::value, pointer>::type operator+(U n) const {
@ -59,18 +61,21 @@ public:
private: private:
// NOT allowed; use raw_bytes() instead // NOT allowed; use raw_bytes() instead
template <class U> template <class U>
typename std::enable_if<std::is_integral<U>::value, pointer>::type typename std::enable_if<std::is_integral<U>::value, pointer>::type operator-(U n) const
operator-(U n) const DELETED_FUNCTION; DELETED_FUNCTION;
public: // raw access
pointer raw_ptr() const { return ptr; }
size_type raw_size_in_bytes() const { return size_in_bytes; }
public:
pointer raw_bytes(size_t bytes) const { pointer raw_bytes(size_t bytes) const {
if (bytes > 0) { if (bytes > 0) {
if very_unlikely (b == nullptr) if very_unlikely (ptr == nullptr)
throwInternalError("MemBuffer raw_bytes unexpected NULL ptr"); throwCantPack("MemBuffer raw_bytes unexpected NULL ptr");
if very_unlikely (bytes > b_size_in_bytes) if very_unlikely (bytes > size_in_bytes)
throwInternalError("MemBuffer raw_bytes invalid size"); throwCantPack("MemBuffer raw_bytes invalid size");
} }
return b; return ptr;
} }
}; };
@ -89,19 +94,19 @@ public:
void dealloc(); void dealloc();
void checkState() const; void checkState() const;
unsigned getSize() const { return b_size_in_bytes; } unsigned getSize() const { return size_in_bytes; }
// explicit converstion // explicit converstion
void *getVoidPtr() { return (void *) b; } void *getVoidPtr() { return (void *) ptr; }
const void *getVoidPtr() const { return (const void *) b; } const void *getVoidPtr() const { return (const void *) ptr; }
// util // util
void fill(unsigned off, unsigned len, int value); void fill(unsigned off, unsigned len, int value);
forceinline void clear(unsigned off, unsigned len) { fill(off, len, 0); } forceinline void clear(unsigned off, unsigned len) { fill(off, len, 0); }
forceinline void clear() { fill(0, b_size_in_bytes, 0); } forceinline void clear() { fill(0, size_in_bytes, 0); }
// If the entire range [skip, skip+take) is inside the buffer, // If the entire range [skip, skip+take) is inside the buffer,
// then return &b[skip]; else throwCantPack(sprintf(errfmt, skip, take)). // then return &ptr[skip]; else throwCantPack(sprintf(errfmt, skip, take)).
// This is similar to BoundedPtr, except only checks once. // This is similar to BoundedPtr, except only checks once.
// skip == offset, take == size_in_bytes // skip == offset, take == size_in_bytes
forceinline pointer subref(const char *errfmt, size_t skip, size_t take) { forceinline pointer subref(const char *errfmt, size_t skip, size_t take) {
@ -130,7 +135,7 @@ private:
Debug debug; Debug debug;
#endif #endif
// disable copy, assignment and move // disable copy and move
MemBuffer(const MemBuffer &) DELETED_FUNCTION; MemBuffer(const MemBuffer &) DELETED_FUNCTION;
MemBuffer &operator=(const MemBuffer &) DELETED_FUNCTION; MemBuffer &operator=(const MemBuffer &) DELETED_FUNCTION;
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
@ -159,11 +164,17 @@ inline typename MemBufferBase<T>::pointer raw_index_bytes(const MemBufferBase<T>
} }
// global operators // global operators
#if ALLOW_INT_PLUS_MEMBUFFER
// rewrite "n + membuffer" to "membuffer + n" so that this will get checked above // rewrite "n + membuffer" to "membuffer + n" so that this will get checked above
template <class T, class U> template <class T, class U>
inline typename std::enable_if<std::is_integral<U>::value, typename MemBufferBase<T>::pointer>::type inline typename std::enable_if<std::is_integral<U>::value, typename MemBufferBase<T>::pointer>::type
operator+(U n, const MemBufferBase<T> &mbb) { operator+(U n, const MemBufferBase<T> &mbb) {
return mbb + n; return mbb + n;
} }
#else
template <class T, class U>
inline typename std::enable_if<std::is_integral<U>::value, typename MemBufferBase<T>::pointer>::type
operator+(U n, const MemBufferBase<T> &mbb) DELETED_FUNCTION;
#endif
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -47,7 +47,9 @@
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_MEM == UPX_RSIZE_MAX) ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_MEM == UPX_RSIZE_MAX)
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_STR <= UPX_RSIZE_MAX / 256) ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_STR <= UPX_RSIZE_MAX / 256)
ACC_COMPILE_TIME_ASSERT_HEADER(2ull * UPX_RSIZE_MAX * 9 / 8 + 16 * 1024 * 1024 < INT_MAX) ACC_COMPILE_TIME_ASSERT_HEADER(2ull * UPX_RSIZE_MAX * 9 / 8 + 16 * 1024 * 1024 < INT_MAX)
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX >= 65536 * 8192) ACC_COMPILE_TIME_ASSERT_HEADER(5ull * UPX_RSIZE_MAX < UINT_MAX)
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX >= 8192 * 65536)
ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_STR >= 1024)
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1, upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
upx_uint64_t extra2) { upx_uint64_t extra2) {

View File

@ -161,8 +161,7 @@ inline R *xspan_make_helper__(R * /*dummy*/, MemBuffer &first) {
/************************************************************************* /*************************************************************************
// raw_bytes() - get underlying memory from checked buffers/pointers. // raw_bytes() - get underlying memory from checked buffers/pointers.
// This is overloaded by various utility classes like BoundedPtr, // This is overloaded by various utility classes like MemBuffer and XSpan.
// MemBuffer and XSpan.
// //
// Note that the pointer type is retained, the "_bytes" hints size_in_bytes // Note that the pointer type is retained, the "_bytes" hints size_in_bytes
**************************************************************************/ **************************************************************************/

View File

@ -31,6 +31,10 @@
template <class T, class U> \ template <class T, class U> \
inline XSPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION(T, U, RType) inline XSPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION(T, U, RType)
template <class T, class U>
inline typename std::enable_if<std::is_integral<U>::value, void *>::type operator+(U, const C<T> &)
DELETED_FUNCTION;
/************************************************************************* /*************************************************************************
// overloads for standard functions // overloads for standard functions
**************************************************************************/ **************************************************************************/

View File

@ -1,8 +1,8 @@
#define UPX_VERSION_HEX 0x040003 /* 04.00.03 */ #define UPX_VERSION_HEX 0x040003 /* 04.00.03 */
#define UPX_VERSION_STRING "4.0.3" #define UPX_VERSION_STRING "4.0.3"
#define UPX_VERSION_STRING4 "4.03" #define UPX_VERSION_STRING4 "4.03"
#define UPX_VERSION_DATE "Jan 30th 2023" #define UPX_VERSION_DATE "Feb 5th 2023"
#define UPX_VERSION_DATE_ISO "2023-01-30" #define UPX_VERSION_DATE_ISO "2023-02-05"
#define UPX_VERSION_YEAR "2023" #define UPX_VERSION_YEAR "2023"
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -25,9 +25,10 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
// work.cpp implements the central loop, and it uses class PackMaster to // This file implements the central loop, and it uses class PackMaster to
// dispatch. PackMaster by itself will instatiate a concrete subclass // dispatch. PackMaster by itself will instatiate a concrete subclass
// of class Packer which then does the actual work. // of class Packer which then does the actual work.
// And see p_com.cpp for a simple executable format.
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
@ -155,7 +156,7 @@ void do_one_file(const char *iname, char *oname) {
} }
} }
// handle command // handle command - actual work is here
PackMaster pm(&fi, opt); PackMaster pm(&fi, opt);
if (opt->cmd == CMD_COMPRESS) if (opt->cmd == CMD_COMPRESS)
pm.pack(&fo); pm.pack(&fo);
@ -258,7 +259,7 @@ static void unlink_ofile(char *oname) {
IGNORE_ERROR(r); IGNORE_ERROR(r);
#endif #endif
if (unlink(oname) == 0) if (unlink(oname) == 0)
oname[0] = 0; oname[0] = 0; // done with oname
} }
} }