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_static_noinline
- __acc_static_forceinline
- DELETED_FUNCTION
- XSPAN_DELETED_FUNCTION
- forceinline
- noinline
EmptyLineBeforeAccessModifier: Leave

View File

@ -101,6 +101,10 @@ jobs:
with:
name: ${{ env.artifact_name }}
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'
run: |
make -C build/extra/gcc/debug test
@ -171,6 +175,10 @@ jobs:
with:
name: ${{ env.artifact_name }}
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'
run: |
make -C build/extra/clang/debug test
@ -250,12 +258,12 @@ jobs:
fail-fast: false
matrix:
include:
- { 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: arm64-win64-vs2019, os: windows-2019, C: msvc-14.2-x64, arch: amd64_arm64 }
- { name: arm64-win64-vs2022, os: windows-2022, C: msvc-14.3-x64, arch: amd64_arm64 }
- { 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: 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: 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-arm64, arch: amd64_arm64 }
- { 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 }
steps:
- name: 'Check out code'
uses: actions/checkout@v3
@ -358,8 +366,8 @@ jobs:
- { zig_target: x86_64-macos.13-none }
- { zig_target: x86_64-windows-gnu }
env:
# 2023-01-30
ZIG_DIST_VERSION: 0.11.0-dev.1491+2b27bc2c6
# 2023-02-05
ZIG_DIST_VERSION: 0.11.0-dev.1575+289e8fab7
# for zig-cc wrapper scripts (see below):
ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING
ZIG_FLAGS: ${{ matrix.zig_flags }}
@ -391,7 +399,7 @@ jobs:
mkdir -p -v ~/.local/bin
cd ~/.local/bin
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
tar -xoJf ${ZIG_DIST_NAME}.tar.xz
rm ${ZIG_DIST_NAME}.tar.xz

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@ name: 'Static Analyzer - scan-build'
on:
schedule:
- cron: '40 1 * * 3'
- cron: '40 4 * * 3'
workflow_dispatch:
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
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_WSTRICT "Do not compile with strict compiler warnings." ON)
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." ON)
else()
# strict config defaults for devel builds
# strict config defaults for Git developer builds
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_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)
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
# 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_SOURCE_CHANGES ON)
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_EXPORT_COMPILE_COMMANDS ON)
# determine git revision
# determine Git revision
set(GITREV_SHORT "")
set(GITREV_PLUS "")
set(GIT_DESCRIBE "")
find_package(Git)
if(Git_FOUND AND NOT UPX_CONFIG_DISABLE_GITREV)
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse --short=12 HEAD
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)
execute_process(RESULT_VARIABLE result COMMAND "${GIT_EXECUTABLE}" diff --quiet)
if(NOT ${result} EQUAL 0)
set(GITREV_PLUS "+")
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git" AND NOT UPX_CONFIG_DISABLE_GITREV)
find_package(Git)
if(Git_FOUND)
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse --short=12 HEAD
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)
execute_process(RESULT_VARIABLE result COMMAND "${GIT_EXECUTABLE}" diff --quiet)
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()
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()
if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") # extra check
set(GITREV_SHORT "")
endif()
if(GITREV_SHORT)
message(STATUS "UPX_VERSION_GITREV = \"${GITREV_SHORT}${GITREV_PLUS}\"")
@ -87,7 +88,7 @@ if(is_multi_config)
set(c "${CMAKE_CONFIGURATION_TYPES}")
list(INSERT c 0 "Release")
list(INSERT c 1 "Debug")
if (CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE)
list(INSERT c 0 "${CMAKE_BUILD_TYPE}")
endif()
list(REMOVE_DUPLICATES c)
@ -97,7 +98,7 @@ elseif(NOT CMAKE_BUILD_TYPE)
endif()
#***********************************************************************
# targets and compilation flags
# targets
#***********************************************************************
#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)
target_link_libraries(upx upx_vendor_ucl upx_vendor_zlib)
if(NOT MSVC)
# rather strict default compilation warnings
set(warn_strict
-Wall -Wextra -Wcast-align -Wcast-qual -Wmissing-declarations
-Wpointer-arith -Wshadow -Wvla -Wwrite-strings
)
#***********************************************************************
# compilation flags
#***********************************************************************
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()
if(UPX_CONFIG_DISABLE_WERROR)
set(warn_Werror "")
@ -159,7 +166,7 @@ if(MSVC)
add_definitions(-Zc:__cplusplus -Zc:preprocessor)
else()
# 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)
endif()
add_definitions(-fno-strict-aliasing -fno-strict-overflow -funsigned-char)
@ -167,7 +174,7 @@ else()
add_definitions(-fno-tree-vectorize)
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)
if(MSVC)
# 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_sanitize_target(${t})
if(MSVC)
target_compile_options(${t} PRIVATE -J -W4 ${warn_WX})
target_compile_options(${t} PRIVATE -J ${warn_WN} ${warn_WX})
else()
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror})
target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
endif()
set(t upx_vendor_zlib)
@ -208,7 +215,8 @@ if(MSVC)
else()
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
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()
if(NOT UPX_CONFIG_DISABLE_ZSTD)
@ -217,9 +225,9 @@ upx_compile_target_debug_with_O2(${t})
upx_sanitize_target(${t})
target_compile_options(${t} PRIVATE -DDYNAMIC_BMI2=0 -DZSTD_DISABLE_ASM)
if(MSVC)
target_compile_options(${t} PRIVATE -J -W4 ${warn_WX})
target_compile_options(${t} PRIVATE -J ${warn_WN} ${warn_WX})
else()
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror})
target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
endif()
endif()
@ -232,12 +240,18 @@ if(GITREV_SHORT)
target_compile_definitions(${t} PRIVATE UPX_VERSION_GIT_DESCRIBE="${GIT_DESCRIBE}")
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_sanitize_target(${t})
if(MSVC)
target_compile_options(${t} PRIVATE -EHsc -J -W4 ${warn_WX})
target_compile_options(${t} PRIVATE -EHsc -J ${warn_WN} ${warn_WX})
else()
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror})
target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
endif()
if(NOT UPX_CONFIG_DISABLE_ZSTD)
target_compile_definitions(${t} PRIVATE WITH_ZSTD=1)
@ -302,7 +316,7 @@ endif()
if(CMAKE_INSTALL_PREFIX AND DEFINED CMAKE_INSTALL_FULL_BINDIR)
install(TARGETS upx DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}")
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}"
)
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)
endif() # UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO
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\"")
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
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/%: export CC = i686-w64-mingw32-gcc
build/extra/cross-windows-mingw32/%: export CXX = i686-w64-mingw32-g++
build/extra/cross-windows-mingw32/%: export CC = i686-w64-mingw32-gcc -static
build/extra/cross-windows-mingw32/%: export CXX = i686-w64-mingw32-g++ -static
# cross compiler: Windows x64 win64 MinGW
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/%: export CC = x86_64-w64-mingw32-gcc
build/extra/cross-windows-mingw64/%: export CXX = x86_64-w64-mingw32-g++
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++ -static
# cross compiler: macOS arm64
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):
@ -78,7 +78,7 @@ Changes in 3.08 (12 Dec 2011):
* 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).
* Better diagnostic when ELF -fPIC is needed.
* PT_NOTE improvements for *BSD.
* PT_NOTE improvements for BSD.
* Preserve more ELF .e_flags on ARM.
* Minor code improvements for ELF stubs.
* 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)
* 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
* win32/pe: stricter checks of some PE values
* 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)
* 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"
.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
.\" way too many mistakes in technical documents.
.if n .ad l

View File

@ -6,10 +6,10 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# 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
# 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"

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# run an interactive shell in the image
# using a rootless Podman container
image=upx-cross-compile-20230115-v2
image=upx-cross-compile-20230115-v3
flags=( -ti --read-only --rm )
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 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:
# 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
# qemu-hppa -L /usr/hppa-linux-gnu upx --version
# qemu-hppa -L /usr/hppa-linux-gnu ./upx --version
# (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
# WARNING: we install many packages, so the resulting image needs A LOT of disk space!
FROM localhost/upx-stubtools-20221212-v4
ENV UPX_CONTAINER_IMAGE_NAME=upx-cross-compile-20230115-v2
FROM localhost/upx-stubtools-20221212-v5
ENV UPX_CONTAINER_IMAGE_NAME=upx-cross-compile-20230115-v3
ARG DEBIAN_FRONTEND=noninteractive
USER root

View File

@ -27,9 +27,13 @@ function run_config_and_build {
# these old architectures do not support sanitize
alpha-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
i686-w64-mingw32) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;;
x86_64-w64-mingw32) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;;
# avoid sanitize link errors with current MinGW-w64 versions; link libstdc++ statically
i686-w64-mingw32)
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
arm-linux-*) CXX="$CXX -Wno-psabi" ;;
esac

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-stubtools-20221212-v4
image=upx-stubtools-20221212-v5
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
# using a rootless Podman container
image=upx-stubtools-20221212-v4
image=upx-stubtools-20221212-v5
flags=( -ti --read-only --rm )
flags+=( --cap-drop=all ) # drop all capabilities

View File

@ -1,5 +1,5 @@
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
ENV LANG=C.UTF-8
@ -7,17 +7,18 @@ ENV LANG=C.UTF-8
RUN dpkg --add-architecture i386 \
&& apt-get update && apt-get upgrade -y \
&& 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 \
libc6:i386 zlib1g:i386 \
# the following packages are not required for rebuilding the stubs, but
# they do make the image much more convenient and also allow building
# the full UPX binary inside the container via CMake:
7zip bfs bzip2 cmake curl elfutils fd-find file fzf g++ gdb gojq htop hyperfine \
jq libzstd-dev lsb-release lzip lzop ninja-build p7zip patch patchelf pax-utils \
ripgrep rsync screen universal-ctags unzip vim zip zlib1g-dev zsh zstd \
7zip bfs bzip2 chrpath cmake cpio curl elfutils fd-find file fzf g++ gdb gojq \
ht htop hyperfine jq libzstd-dev lsb-release lz4 lzip lzop moreutils ninja-build \
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":
gcc-multilib g++-multilib \
g++-multilib gcc-multilib \
&& true
# manually install compat libs from Ubuntu 16.04; REQUIRED

View File

@ -80,8 +80,8 @@ endif
ifeq ($(shell uname),Linux)
# 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 += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmli%
CLANG_FORMAT_EXCLUDE_FILES += packer_c.cpp packer_f.cpp
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
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 := $(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)(-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)
# pragma clang diagnostic error "-Wsuggest-override"
#elif (ACC_CC_GNUC >= 0x0a0000)
// don't enable before gcc-10 because of gcc bug #78010
# pragma GCC diagnostic error "-Wsuggest-override"
#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++:
// 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:
// 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"
#endif
#if (ACC_CC_MSC)
# pragma warning(error: 4127)
# pragma warning(error: 4146)
# pragma warning(error: 4319)
# 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: 4267) // -Wconversion
# 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
#define upx_std_atomic(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
#include <atomic>
#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
// 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>
struct USizeOfTypeImpl {
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);
}
};

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

View File

@ -29,8 +29,6 @@
#ifndef UPX_EXCEPT_H__
#define UPX_EXCEPT_H__ 1
#ifdef __cplusplus
const char *prettyName(const char *n) noexcept;
/*************************************************************************
@ -64,7 +62,7 @@ private:
ACC_CXX_DISABLE_NEW_DELETE
private:
static unsigned long counter; // for debugging
static upx_std_atomic(size_t) debug_counter; // for debugging
};
// Exceptions can/should be caught
@ -217,8 +215,6 @@ NORET void throwEOFException(const char *msg = nullptr, int e = 0);
#undef NORET
#endif /* __cplusplus */
#endif /* already included */
/* 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) {
static bool done = false;
static unsigned char filter_map[256];
static upx_std_once_flag init_done;
if (!done) {
// init the filter_map[]
upx_std_call_once(init_done, []() noexcept {
// init the filter_map[] (using a lambda function)
assert(n_filters <= 254); // as 0xff means "empty slot"
memset(filter_map, 0xff, sizeof(filter_map));
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);
filter_map[filter_id] = (unsigned char) i;
}
done = true;
}
});
if (id < 0 || id > 255)
return nullptr;
@ -103,7 +102,8 @@ void Filter::init(int id_, unsigned addvalue_) {
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_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
@ -134,7 +134,8 @@ bool Filter::filter(upx_byte *buf_, unsigned buf_len_) {
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_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
@ -178,10 +179,11 @@ void Filter::verifyUnfilter() {
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
// 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_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);

View File

@ -54,10 +54,10 @@ public:
}
void init(int id = 0, unsigned addvalue = 0);
bool filter(upx_byte *buf, unsigned buf_len);
void unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum = false);
bool filter(SPAN_0(upx_byte) buf, unsigned buf_len);
void unfilter(SPAN_0(upx_byte) buf, unsigned buf_len, bool verify_checksum = false);
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, const int *allowed_filters);

View File

@ -168,7 +168,7 @@ umin(unsigned const a, unsigned const b)
// database for use in class Filter
**************************************************************************/
const FilterImpl::FilterEntry FilterImpl::filters[] = {
/*static*/ const FilterImpl::FilterEntry FilterImpl::filters[] = {
// no filter
{ 0x00, 0, 0, nullptr, nullptr, nullptr },
@ -261,6 +261,6 @@ const FilterImpl::FilterEntry FilterImpl::filters[] = {
{ 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: */

View File

@ -46,6 +46,8 @@ PackArmPe::PackArmPe(InputFile *f) : super(f) {}
PackArmPe::~PackArmPe() {}
Linker *PackArmPe::newLinker() const { return new ElfLinkerArmLE; }
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_lzma[] = {M_LZMA, M_END};
@ -71,8 +73,6 @@ const int *PackArmPe::getFilters() const {
return filters;
}
Linker *PackArmPe::newLinker() const { return new ElfLinkerArmLE; }
/*************************************************************************
// import handling
**************************************************************************/
@ -127,37 +127,37 @@ void PackArmPe::buildLoader(const Filter *ft) {
initLoader(loader, size);
if (isdll)
addLoader("DllStart", nullptr);
addLoader("ExeStart", nullptr);
addLoader("DllStart");
addLoader("ExeStart");
if (ph.method == M_NRV2E_8)
addLoader("Call2E", nullptr);
addLoader("Call2E");
else if (ph.method == M_NRV2B_8)
addLoader("Call2B", nullptr);
addLoader("Call2B");
else if (ph.method == M_NRV2D_8)
addLoader("Call2D", nullptr);
addLoader("Call2D");
else if (M_IS_LZMA(ph.method))
addLoader("+40C,CallLZMA", nullptr);
addLoader("+40C,CallLZMA");
if (ft->id == 0x50)
addLoader("+40C,Unfilter_0x50", nullptr);
addLoader("+40C,Unfilter_0x50");
if (sorelocs)
addLoader("+40C,Relocs", nullptr);
addLoader("+40C,Relocs");
addLoader("+40C,Imports", nullptr);
addLoader("ProcessEnd", nullptr);
addLoader("+40C,Imports");
addLoader("ProcessEnd");
if (ph.method == M_NRV2E_8)
addLoader(".ucl_nrv2e_decompress_8", nullptr);
addLoader(".ucl_nrv2e_decompress_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)
addLoader(".ucl_nrv2d_decompress_8", nullptr);
addLoader(".ucl_nrv2d_decompress_8");
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() {

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.
@ -35,23 +35,21 @@
static const CLANG_FORMAT_DUMMY_STATEMENT
#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 {
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(level);
return m_nrv2b;
}
const int *PackCom::getFilters() const {
// see class FilterImpl
static const int filters[] = {0x06, 0x03, 0x04, 0x01, 0x05, 0x02, FT_END};
return filters;
}
@ -64,16 +62,17 @@ bool PackCom::canPack() {
unsigned char buf[128];
fi->readx(buf, sizeof(buf));
if (memcmp(buf, "MZ", 2) == 0 || memcmp(buf, "ZM", 2) == 0 // .exe
|| memcmp(buf, "\xff\xff\xff\xff", 4) == 0) // .sys
if (memcmp(buf, "MZ", 2) == 0 || memcmp(buf, "ZM", 2) == 0) // .exe
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;
checkAlreadyPacked(buf, sizeof(buf));
if (file_size < 1024)
throwCantPack("file is too small");
throwCantPack("file is too small for dos/com");
if (file_size > 0xFF00)
throwCantPack("file is too big for dos/com");
throwCantPack("file is too large for dos/com");
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) {
const int e_len = getLoaderSectionStart("COMCUTPO");
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)
stacksize = 0x56;
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("sp_limit", upper_end + stacksize);
@ -105,46 +147,15 @@ void PackCom::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned
relocateLoader();
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);
// write loader + compressed file
fo->write(loader, e_len); // entry
fo->write(obuf, ph.c_len);
fo->write(loader, e_len); // entry
fo->write(obuf, ph.c_len); // compressed
fo->write(loader + e_len, d_len); // decompressor
#if 0
printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len);
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_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);
NO_printf("%-13s: entry : %8u bytes\n", getName(), e_len);
NO_printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
NO_printf("%-13s: decompressor : %8u bytes\n", getName(), d_len);
}
/*************************************************************************
@ -187,7 +198,7 @@ void PackCom::pack(OutputFile *fo) {
**************************************************************************/
int PackCom::canUnpack() {
if (!readPackHeader(128))
if (!readPackHeader(128)) // read "ph"
return false;
if (file_size_u <= ph.c_len)
return false;
@ -224,6 +235,4 @@ void PackCom::unpack(OutputFile *fo) {
fo->write(obuf, ph.u_len);
}
Linker *PackCom::newLinker() const { return new ElfLinkerX86(); }
/* 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.
@ -52,13 +52,12 @@ public:
virtual int canUnpack() override;
protected:
virtual unsigned getCallTrickOffset() const { return 0x100; }
virtual Linker *newLinker() const override;
protected:
void addFilter16(int filter_id);
// dos/sys will override these:
virtual unsigned getCallTrickOffset() const { return 0x100; }
virtual void buildLoader(const Filter *ft) override;
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned);
virtual void addFilter16(int filter_id);
};
#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);
}
Linker *PackDjgpp2::newLinker() const { return new ElfLinkerX86; }
const int *PackDjgpp2::getCompressionMethods(int method, int level) const {
return Packer::getDefaultCompressionMethods_le32(method, level);
}
@ -71,21 +73,19 @@ unsigned PackDjgpp2::findOverlapOverhead(const upx_bytep buf, const upx_bytep tb
return o;
}
Linker *PackDjgpp2::newLinker() const { return new ElfLinkerX86; }
void PackDjgpp2::buildLoader(const Filter *ft) {
// prepare loader
initLoader(stub_i386_dos32_djgpp2, sizeof(stub_i386_dos32_djgpp2));
addLoader("IDENTSTR,DJ2MAIN1", ft->id ? "DJCALLT1" : "",
ph.first_offset_found == 1 ? "DJ2MAIN2" : "",
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) {
assert(ft->calls > 0);
addLoader("DJCALLT2", nullptr);
addLoader("DJCALLT2");
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);
} else {
// "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));
}
}
@ -179,9 +179,9 @@ int PackDjgpp2::readFileHeader() {
return 0;
// FIXME: check for Linux etc.
text = coff_hdr.sh;
data = text + 1;
bss = data + 1;
text = &coff_hdr.sh[0];
data = &coff_hdr.sh[1];
bss = &coff_hdr.sh[2];
return UPX_F_DJGPP2_COFF;
}
@ -242,7 +242,7 @@ void PackDjgpp2::pack(OutputFile *fo) {
// read file
const unsigned size = text->size + data->size;
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;
if (hdrsize < sizeof(coff_hdr) || hdrsize > tpos)
throwCantPack("coff header error");
@ -371,11 +371,14 @@ void PackDjgpp2::unpack(OutputFile *fo) {
// decompress
decompress(ibuf, obuf);
coff_header_t *chdr = (coff_header_t *) obuf.getVoidPtr();
text = chdr->sh;
data = text + 1;
coff_header_t *chdr = (coff_header_t *) raw_bytes(obuf, sizeof(coff_header_t));
text = &chdr->sh[0];
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;
if (ph.version >= 14)

View File

@ -98,7 +98,9 @@ protected:
};
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();
};

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.
@ -54,6 +54,8 @@ PackExe::PackExe(InputFile *f) : super(f) {
use_clear_dirty_stack = false;
}
Linker *PackExe::newLinker() const { return new ElfLinkerX86(); }
const int *PackExe::getCompressionMethods(int method, int level) const {
bool small = ih_imagesize <= 256 * 1024;
// 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) {
addLoader("EXEMAIN5", nullptr);
addLoader("EXEMAIN5");
if (relocsize)
addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ"
: "EXEADJUS",
"EXERELO1", has_9a ? "EXEREL9A" : "", "EXERELO2",
ih_exesize > 0xFE00 ? "EXEREBIG" : "", "EXERELO3", nullptr);
ih_exesize > 0xFE00 ? "EXEREBIG" : "", "EXERELO3");
addLoader("EXEMAIN8", device_driver ? "DEVICEEND" : "", (flag & SS) ? "EXESTACK" : "",
(flag & SP) ? "EXESTASP" : "", (flag & USEJUMP) ? "EXEJUMPF" : "", nullptr);
(flag & SP) ? "EXESTASP" : "", (flag & USEJUMP) ? "EXEJUMPF" : "");
if (!(flag & USEJUMP))
addLoader(ih.cs ? "EXERCSPO" : "", "EXERETIP", nullptr);
addLoader(ih.cs ? "EXERCSPO" : "", "EXERETIP");
linker->defineSymbol("original_cs", ih.cs);
linker->defineSymbol("original_ip", ih.ip);
@ -136,7 +138,7 @@ void PackExe::buildLoader(const Filter *) {
if (M_IS_LZMA(ph.method)) {
addLoader("LZMA_DEC00", opt->small ? "LZMA_DEC10" : "LZMA_DEC20", "LZMA_DEC30",
use_clear_dirty_stack ? "LZMA_DEC31" : "", "LZMA_DEC32",
ph.u_len > 0xffff ? "LZMA_DEC33" : "", nullptr);
ph.u_len > 0xffff ? "LZMA_DEC33" : "");
addLoaderEpilogue(flag);
defineDecompressorSymbols();
@ -173,35 +175,35 @@ void PackExe::buildLoader(const Filter *) {
initLoader(stub_i086_dos16_exe, sizeof(stub_i086_dos16_exe));
// prepare loader
if (device_driver)
addLoader("DEVICEENTRY,LZMADEVICE,DEVICEENTRY2", nullptr);
addLoader("DEVICEENTRY,LZMADEVICE,DEVICEENTRY2");
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)
addLoader("DEVICEENTRY,DEVICEENTRY2", nullptr);
addLoader("DEVICEENTRY,DEVICEENTRY2");
addLoader("EXEENTRY", M_IS_LZMA(ph.method) && device_driver ? "LONGSUB" : "SHORTSUB",
"JNCDOCOPY", relocsize ? "EXERELPU" : "", "EXEMAIN4",
M_IS_LZMA(ph.method) ? "" : "EXEMAIN4B", "EXEMAIN4C",
M_IS_LZMA(ph.method) ? "COMPRESSED_LZMA_START,COMPRESSED_LZMA" : "",
"+G5DXXXX,UPX1HEAD,EXECUTPO", nullptr);
"+G5DXXXX,UPX1HEAD,EXECUTPO");
if (ph.method == M_NRV2B_8)
addLoader("NRV2B16S", // decompressor
ph.u_len > DI_LIMIT ? "N2B64K01" : "", "NRV2BEX1",
opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601", "NRV2BEX2",
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)
addLoader("NRV2D16S", ph.u_len > DI_LIMIT ? "N2D64K01" : "", "NRV2DEX1",
opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601", "NRV2DEX2",
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)
addLoader("NRV2E16S", ph.u_len > DI_LIMIT ? "N2E64K01" : "", "NRV2EEX1",
opt->cpu == opt->CPU_8086 ? "N2EX8601" : "N2E28601", "NRV2EEX2",
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)
return;
else
@ -229,9 +231,7 @@ int PackExe::readFileHeader() {
throwCantPack("illegal exe header");
if (file_size_u < ih_exesize || ih_imagesize <= 0 || ih_imagesize > ih_exesize)
throwCantPack("exe header corrupted");
#if 0
printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay);
#endif
NO_printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay);
return UPX_F_DOS_EXE;
}
@ -553,13 +553,11 @@ void PackExe::pack(OutputFile *fo) {
fo->write(loader + e_len, d_len); // decompressor
fo->write(extra_info, eisize);
assert(eisize <= 9);
#if 0
printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh));
printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len);
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) packedsize);
printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) d_len);
printf("%-13s: extra info : %8ld bytes\n", getName(), (long) eisize);
#endif
NO_printf("%-13s: program hdr : %8u bytes\n", getName(), usizeof(oh));
NO_printf("%-13s: entry : %8u bytes\n", getName(), e_len);
NO_printf("%-13s: compressed : %8u bytes\n", getName(), packedsize);
NO_printf("%-13s: decompressor : %8u bytes\n", getName(), d_len);
NO_printf("%-13s: extra info : %8u bytes\n", getName(), eisize);
// verify
verifyOverlappingDecompression();
@ -711,8 +709,6 @@ void PackExe::unpack(OutputFile *fo) {
copyOverlay(fo, ih_overlay, obuf);
}
Linker *PackExe::newLinker() const { return new ElfLinkerX86(); }
/*
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.

View File

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

View File

@ -92,7 +92,7 @@ PackLinuxI386sh::buildLoader(Filter const *ft)
optimizeFilter(&fold_ft, buf, sz_fold);
unsigned fold_hdrlen = sizeof(l_info) + sizeof(Elf32_Ehdr) +
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)
fold_hdrlen = umax(0x80, fold_hdrlen);
}

View File

@ -25,6 +25,7 @@
*/
#define ALLOW_INT_PLUS_MEMBUFFER 1
#include "conf.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.
@ -46,13 +46,13 @@ bool PackSys::canPack() {
fi->readx(buf, sizeof(buf));
if (memcmp(buf, "\xff\xff\xff\xff", 4) != 0)
return false;
if (!fn_has_ext(fi->getName(), "sys"))
if (!fn_has_ext(fi->getName(), "sys")) // query file name
return false;
checkAlreadyPacked(buf, sizeof(buf));
if (file_size < 1024)
throwCantPack("file is too small");
throwCantPack("file is too small for dos/sys");
if (file_size > 0x10000)
throwCantPack("file is too big for dos/sys");
throwCantPack("file is too large for dos/sys");
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) {
const int e_len = getLoaderSectionStart("SYSCUTPO");
const int d_len = lsize - e_len;
@ -85,24 +108,15 @@ void PackSys::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned
relocateLoader();
loader = getLoader();
// some day we could use the relocation stuff for patchPackHeader too..
patchPackHeader(loader, e_len);
// write loader + compressed file
fo->write(loader, e_len); // entry
fo->write(obuf, ph.c_len);
fo->write(loader, e_len); // entry
fo->write(obuf, ph.c_len); // compressed
fo->write(loader + e_len, d_len); // decompressor
}
void PackSys::buildLoader(const Filter *ft) {
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);
NO_printf("%-13s: entry : %8u bytes\n", getName(), e_len);
NO_printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
NO_printf("%-13s: decompressor : %8u bytes\n", getName(), d_len);
}
/* 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.
@ -45,10 +45,8 @@ public:
virtual bool canPack() override;
protected:
protected: // dos/com overrides
virtual unsigned getCallTrickOffset() const override { return 0; }
protected:
virtual void buildLoader(const Filter *ft) 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)
}
Linker *PackTmt::newLinker() const { return new ElfLinkerX86; }
const int *PackTmt::getCompressionMethods(int method, int level) const {
return Packer::getDefaultCompressionMethods_le32(method, level);
}
@ -64,24 +66,22 @@ unsigned PackTmt::findOverlapOverhead(const upx_bytep buf, const upx_bytep tbuf,
return o;
}
Linker *PackTmt::newLinker() const { return new ElfLinkerX86; }
void PackTmt::buildLoader(const Filter *ft) {
// prepare loader
initLoader(stub_i386_dos32_tmt, sizeof(stub_i386_dos32_tmt));
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
linker->defineSymbol("TMTCUTPO", 0x1000);
addLoader(getDecompressorSections(), "TMTMAIN5", nullptr);
addLoader(getDecompressorSections(), "TMTMAIN5");
if (ft->id) {
assert(ft->calls > 0);
addLoader("TMTCALT2", nullptr);
addLoader("TMTCALT2");
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 entry = ih.entry;
unsigned const relocsize = ih.relocsize;
if (imagesize < sizeof(ih) || entry < sizeof(ih) || file_size <= imagesize ||
file_size <= entry || file_size <= relocsize) {
if (imagesize < sizeof(ih) || entry < sizeof(ih) || file_size_u <= imagesize ||
file_size_u <= entry || file_size_u <= relocsize) {
printWarn(getName(), "bad header; imagesize=%#x entry=%#x relocsize=%#x", imagesize,
entry, relocsize);
return 0;
@ -202,7 +202,7 @@ void PackTmt::pack(OutputFile *fo) {
relocsize += 4;
set_le32(wrkmem + relocsize, relocsize + 4);
relocsize += 4;
memcpy(ibuf + usize, wrkmem, relocsize);
memcpy(raw_index_bytes(ibuf, usize, relocsize), wrkmem, relocsize);
// prepare packheader
ph.u_len = usize + relocsize;

View File

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

View File

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

View File

@ -98,44 +98,44 @@ void PackW32Pe::buildLoader(const Filter *ft) {
tmp_tlsindex ? "PETLSHAK" : "", "PEMAIN02",
ph.first_offset_found == 1 ? "PEMAIN03" : "", getDecompressorSections(),
// multipass ? "PEMULTIP" : "",
"PEMAIN10", nullptr);
"PEMAIN10");
addLoader(tmp_tlsindex ? "PETLSHAK2" : "");
if (ft->id) {
const unsigned texv = ih.codebase - rvamin;
assert(ft->calls > 0);
addLoader(texv ? "PECTTPOS" : "PECTTNUL", nullptr);
addLoader(texv ? "PECTTPOS" : "PECTTNUL");
addFilter32(ft->id);
}
if (soimport)
addLoader("PEIMPORT", importbyordinal ? "PEIBYORD" : "", kernel32ordinal ? "PEK32ORD" : "",
importbyordinal ? "PEIMORD1" : "", "PEIMPOR2", isdll ? "PEIERDLL" : "PEIEREXE",
"PEIMDONE", nullptr);
"PEIMDONE");
if (sorelocs) {
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
addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "",
big_relocs & 2 ? "PERELHI0" : "", nullptr);
big_relocs & 2 ? "PERELHI0" : "");
}
if (use_dep_hack)
addLoader("PEDEPHAK", nullptr);
addLoader("PEDEPHAK");
// NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann
if (use_tls_callbacks)
addLoader("PETLSC", nullptr);
addLoader("PETLSC");
addLoader("PEMAIN20", nullptr);
addLoader("PEMAIN20");
if (use_clear_dirty_stack)
addLoader("CLEARSTACK", nullptr);
addLoader("PEMAIN21", nullptr);
addLoader("CLEARSTACK");
addLoader("PEMAIN21");
// 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
if (use_tls_callbacks)
addLoader("PETLSC2", nullptr);
addLoader("PETLSC2");
addLoader("IDENTSTR,UPX1HEAD", nullptr);
addLoader("IDENTSTR,UPX1HEAD");
}
bool PackW32Pe::handleForceOption() {

View File

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

View File

@ -85,22 +85,22 @@ void PackWcle::buildLoader(const Filter *ft) {
// prepare loader
initLoader(stub_i386_dos32_watcom_le, sizeof(stub_i386_dos32_watcom_le));
addLoader("IDENTSTR,WCLEMAIN", ph.first_offset_found == 1 ? "WCLEMAIN02" : "",
"WCLEMAIN03,UPX1HEAD,WCLECUTP", nullptr);
"WCLEMAIN03,UPX1HEAD,WCLECUTP");
// fake alignment for the start of the decompressor
linker->defineSymbol("WCLECUTP", 0x1000);
addLoader(getDecompressorSections(), "WCLEMAI2", nullptr);
addLoader(getDecompressorSections(), "WCLEMAI2");
if (ft->id) {
assert(ft->calls > 0);
addLoader(ft->addvalue ? "WCCTTPOS" : "WCCTTNUL", nullptr);
addLoader(ft->addvalue ? "WCCTTPOS" : "WCCTTNUL");
addFilter32(ft->id);
}
#if 1
// FIXME: if (has_relocation)
{ addLoader("WCRELOC1,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J", nullptr); }
{ addLoader("WCRELOC1,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J"); }
#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);
#if 0
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);
for (int i = 0; i < nfilters; i++) printf(" %#x", filters[i]);
for (int i = 0; i < nfilters; i++)
printf(" %#x", filters[i]);
printf("\n");
#endif
@ -1294,9 +1296,7 @@ void Packer::compressWithFilters(upx_bytep i_ptr,
int nfilters_success_total = 0;
for (int mm = 0; mm < nmethods; mm++) // for all methods
{
#if 0 //{
printf("\nmethod %d (%d of %d)\n", methods[mm], 1+ mm, nmethods);
#endif //}
NO_printf("\nmethod %d (%d of %d)\n", methods[mm], 1 + mm, nmethods);
assert(isValidCompressionMethod(methods[mm]));
unsigned hdr_c_len = 0;
if (hdr_ptr != nullptr && hdr_len) {
@ -1341,10 +1341,9 @@ void Packer::compressWithFilters(upx_bytep i_ptr,
continue;
}
// filter success
#if 0
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.lastcall, ft.cto);
#endif
NO_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.lastcall, ft.cto);
if (nfilters_success_total != 0 && o_tmp == o_ptr) {
o_tmp_buf.allocForCompression(i_len);
o_tmp = o_tmp_buf;
@ -1365,11 +1364,10 @@ void Packer::compressWithFilters(upx_bytep i_ptr,
lsize = getLoaderSize();
assert(lsize > 0);
}
#if 0 //{
printf("\n%2d %02x: %d +%4d +%3d = %d (best: %d +%4d +%3d = %d)\n", ph.method, ph.filter,
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);
#endif //}
NO_printf("\n%2d %02x: %d +%4d +%3d = %d (best: %d +%4d +%3d = %d)\n", ph.method,
ph.filter, 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);
bool update = false;
if (ph.c_len + lsize + hdr_c_len < best_ph.c_len + best_ph_lsize + best_hdr_c_len)
update = true;

View File

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

View File

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

View File

@ -33,52 +33,29 @@
#include "linker.h"
#define FILLVAL 0
#define import my_import // "import" is a keyword since C++20
/*************************************************************************
//
**************************************************************************/
#if (WITH_XSPAN >= 2) && 1
// #define IPTR(type, var) Span<type> var(ibuf, ibuf.getSize(), ibuf)
// #define OPTR(type, var) Span<type> var(obuf, obuf.getSize(), obuf)
#define IPTR_I_D(type, var, disp) \
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
#define IPTR_VAR(type, var, first) SPAN_S_VAR(type, var, first, ibuf)
#define OPTR_VAR(type, var, first) SPAN_S_VAR(type, var, first, obuf)
#define IPTR_VAR_OFFSET(type, var, offset) \
SPAN_S_VAR(type, var, ibuf + (offset), ibuf.getSize() - (offset), ibuf + (offset))
static void xcheck(const void *p) {
if (!p)
if very_unlikely (p == nullptr)
throwCantUnpack("xcheck unexpected nullptr pointer; take care!");
}
static void xcheck(const void *p, size_t plen, const void *b, size_t blen) {
const char *pp = (const char *) p;
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!");
}
#if 0
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
{
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 ICHECK(p, bytes) xcheck(raw_bytes(p, 0), bytes, ibuf, ibuf.getSize())
#define OCHECK(p, bytes) xcheck(raw_bytes(p, 0), bytes, obuf, obuf.getSize())
// #define imemset(a,b,c) ICHECK(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;
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) {
importbyordinal = true;
soimport += 2; // ordinal num: 2 bytes
dlls[ic].ordinal = *tarr & 0xffff;
} else // it's an import by name
{
IPTR_I(const upx_byte, n, ibuf + *tarr + 2);
unsigned len = strlen(n);
IPTR_VAR(const upx_byte, const name, ibuf + *tarr + 2);
unsigned len = strlen(name);
soimport += len + 1;
if (dlls[ic].shname == nullptr || len < strlen(dlls[ic].shname))
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_) {
ibufstart = ibufstart_;
ibufend = ibufend_;
newstart = nullptr;
init(p);
}
@ -1945,7 +1923,7 @@ void PeFile::readSectionHeaders(unsigned objs, unsigned sizeof_ih) {
if (objs == 0)
return;
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) {
char buf[32];
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);
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)
set_le32(p, get_le32(p) + imagebase + rvamin);
else
@ -2648,8 +2626,8 @@ void PeFile::rebuildResources(SPAN_S(upx_byte) & extrainfo, unsigned lastvaddr)
Resource res(r + vaddr, ibuf, ibuf + ibuf.getSize());
while (res.next())
if (res.offs() > vaddr) {
ICHECK(r + res.offs() - 4, 4);
unsigned origoffs = get_le32(r + res.offs() - 4);
ICHECK(r + (res.offs() - 4), 4);
unsigned origoffs = get_le32(r + (res.offs() - 4));
res.newoffs() = origoffs;
omemcpy(obuf + (origoffs - rvamin), r + res.offs(), res.size());
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))
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);
extrainfo += 8;
unsigned sdllnames = 0;
IPTR_I_D(const upx_byte, import, IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
OPTR_I(const upx_byte, p, raw_bytes(idata, 4));
IPTR_VAR_OFFSET(const upx_byte, const import, IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
OPTR_VAR(const upx_byte, p, raw_bytes(imdata, 4));
for (; get_le32(p) != 0; ++p) {
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;
for (p += 8; *p;)
if (*p == 1)
p += strlen(++p) + 1;
p += 1 + strlen(p + 1) + 1;
else if (*p == 0xff)
p += 3; // ordinal
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);
#endif
for (p = idata; get_le32(p) != 0; ++p) {
for (p = imdata; get_le32(p) != 0; ++p) {
// restore the name of the dll
const upx_byte *dname = raw_bytes(import + get_le32(p), 1);
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) {
// now I rebuild the dll names
omemcpy(dllnames, dname, dlen + 1);
im->dllname = ptr_diff_bytes(dllnames, Obuf);
im->dllname = ptr_udiff_bytes(dllnames, Obuf);
//;;;printf("\ndll: %s:",dllnames);
dllnames += dlen + 1;
} else {
@ -2732,18 +2710,18 @@ void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, b
if (set_oft)
im->oft = iatoffs;
OPTR_I(LEXX, newiat, (LEXX *) (Obuf + iatoffs));
OPTR_VAR(LEXX, newiat, (LEXX *) (Obuf + iatoffs));
// restore the imported names+ordinals
for (p += 8; *p; ++newiat)
if (*p == 1) {
const unsigned ilen = strlen(++p) + 1;
if (inamespos) {
if (ptr_diff_bytes(importednames, importednames_start) & 1)
if (ptr_udiff_bytes(importednames, importednames_start) & 1)
importednames -= 1;
omemcpy(importednames + 2, p, ilen);
//;;;printf(" %s",importednames+2);
*newiat = ptr_diff_bytes(importednames, Obuf);
*newiat = ptr_udiff_bytes(importednames, Obuf);
importednames += 2 + ilen;
} else {
// Beware overlap!
@ -2762,7 +2740,7 @@ void PeFile::rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, b
*newiat = 0;
im++;
}
// memset(idata,0,p - idata);
// memset(imdata, 0, ptr_udiff_bytes(p, imdata));
}
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
if (fo) {
unsigned ic;
for (ic = 0; ic < objs && osection[ic].rawdataptr == 0; ic++)
;
unsigned ic = 0;
while (ic < objs && osection[ic].rawdataptr == 0)
ic++;
ibuf.dealloc();
ibuf.alloc(osection[ic].rawdataptr);
ibuf.clear();
infoHeader("[Writing uncompressed file]");
// write loader + compressed file
// write header + decompressed file
fo->write(&oh, sizeof(oh));
fo->write(osection, objs * sizeof(pe_section_t));
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)
return -1;
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->readx(isection, sizeof(pe_section_t) * objs);
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>
*/
// INFO: not thread-safe; assumes a single UiPacker instance that
// is exclusively called from main thread
#include "conf.h"
#include "file.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 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)
// FIXME: should test codepage here
static bool done = false;
if (done)
return;
done = true;
#if 1 && (ACC_OS_DOS32) && defined(__DJGPP__)
/* check for Windows NT/2000/XP */
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) {
init_global_constants();
static upx_std_once_flag init_done;
upx_std_call_once(init_done, init_global_constants);
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__)
static forceinline constexpr bool use_simple_mcheck() { return false; }
#elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND)
static int use_simple_mcheck_flag = -1;
static noinline void use_simple_mcheck_init() {
use_simple_mcheck_flag = 1;
static bool use_simple_mcheck_flag;
static noinline void init_use_simple_mcheck() noexcept {
bool r = true;
if (RUNNING_ON_VALGRIND) {
use_simple_mcheck_flag = 0;
// fprintf(stderr, "upx: detected RUNNING_ON_VALGRIND\n");
r = false;
NO_fprintf(stderr, "upx: detected RUNNING_ON_VALGRIND\n");
}
use_simple_mcheck_flag = r;
}
static forceinline bool use_simple_mcheck() {
if very_unlikely (use_simple_mcheck_flag < 0)
use_simple_mcheck_init();
return (bool) use_simple_mcheck_flag;
static bool use_simple_mcheck() {
static upx_std_once_flag init_done;
upx_std_call_once(init_done, init_use_simple_mcheck);
return use_simple_mcheck_flag;
}
#else
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) {
alloc(size_in_bytes);
MemBuffer::MemBuffer(upx_uint64_t bytes) {
alloc(bytes);
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) {
debug_set(debug.last_return_address_subref, upx_return_address());
// 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];
// printf is using unsigned formatting
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);
throwCantPack(buf);
}
return &b[skip];
return ptr + skip;
}
static unsigned width(unsigned x) {
@ -116,62 +117,55 @@ static unsigned width(unsigned x) {
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) {
if (uncompressed_size == 0)
throwCantPack("invalid uncompressed_size");
const unsigned z = uncompressed_size; // fewer keystrokes and display columns
const unsigned w = umax(8, width(z - 1)); // ignore tiny offsets
unsigned bytes = ACC_ICONV(unsigned, mem_size(1, z)); // check
const size_t z = uncompressed_size; // fewer keystrokes and display columns
const size_t w = umax(8, width(z - 1)); // ignore tiny offsets
size_t bytes = mem_size(1, z); // check size
// Worst matching: All match at max_offset, which implies 3==min_match
// All literal: 1 bit overhead per literal byte
bytes = umax(bytes, z + z / 8);
// All literal: 1 bit overhead per literal byte; from UCL documentation
bytes = umax(bytes, z + z / 8 + 256);
// NRV2B: 1 byte plus 2 bits per width exceeding 8 ("ss11")
bytes = umax(bytes, (z / 3 * (8 + 2 * (w - 8) / 1)) / 8);
// NRV2E: 1 byte plus 3 bits per pair of width exceeding 7 ("ss12")
bytes = umax(bytes, (z / 3 * (8 + 3 * (w - 7) / 2)) / 8);
// zstd: ZSTD_COMPRESSBOUND
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);
UNUSED(w);
return bytes;
return ACC_ICONV(unsigned, bytes);
}
unsigned MemBuffer::getSizeForDecompression(unsigned uncompressed_size, unsigned extra) {
if (uncompressed_size == 0)
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);
}
void MemBuffer::allocForCompression(unsigned uncompressed_size, unsigned extra) {
if (uncompressed_size == 0)
throwCantPack("invalid uncompressed_size");
unsigned size = getSizeForCompression(uncompressed_size, extra);
alloc(size);
unsigned bytes = getSizeForCompression(uncompressed_size, extra);
alloc(bytes);
debug_set(debug.last_return_address_alloc, upx_return_address());
}
void MemBuffer::allocForDecompression(unsigned uncompressed_size, unsigned extra) {
if (uncompressed_size == 0)
throwCantPack("invalid uncompressed_size");
unsigned size = getSizeForDecompression(uncompressed_size, extra);
alloc(size);
unsigned bytes = getSizeForDecompression(uncompressed_size, extra);
alloc(bytes);
debug_set(debug.last_return_address_alloc, upx_return_address());
}
void MemBuffer::fill(unsigned off, unsigned len, int value) {
debug_set(debug.last_return_address_fill, upx_return_address());
checkState();
assert((int) off >= 0);
assert((int) len >= 0);
assert(off <= b_size_in_bytes);
assert(len <= b_size_in_bytes);
assert(off + len <= b_size_in_bytes);
if (off > size_in_bytes || len > size_in_bytes || off + len > size_in_bytes)
throwCantPack("MemBuffer::fill out of range; take care!");
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)
void MemBuffer::checkState() const {
if (!b)
if (!ptr)
throwInternalError("block not allocated");
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");
if (get_ne32(b - 8) != b_size_in_bytes)
if (get_ne32(ptr - 8) != size_in_bytes)
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");
}
}
void MemBuffer::alloc(upx_uint64_t size) {
// NOTE: we don't automatically free a used buffer
assert(b == nullptr);
assert(b_size_in_bytes == 0);
assert(ptr == nullptr);
assert(size_in_bytes == 0);
//
assert(size > 0);
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);
if (!p)
throwOutOfMemoryException();
b = p;
b_size_in_bytes = ACC_ICONV(unsigned, size);
ptr = p;
size_in_bytes = ACC_ICONV(unsigned, size);
if (use_simple_mcheck()) {
b = p + 16;
ptr = p + 16;
// store magic constants to detect buffer overruns
set_ne32(b - 8, b_size_in_bytes);
set_ne32(b - 4, MAGIC1(b));
set_ne32(b + b_size_in_bytes, MAGIC2(b));
set_ne32(b + b_size_in_bytes + 4, stats.global_alloc_counter);
set_ne32(ptr - 8, size_in_bytes);
set_ne32(ptr - 4, MAGIC1(ptr));
set_ne32(ptr + size_in_bytes, MAGIC2(ptr));
set_ne32(ptr + size_in_bytes + 4, stats.global_alloc_counter);
}
#if !defined(__SANITIZE_ADDRESS__) && 0
fill(0, b_size_in_bytes, (rand() & 0xff) | 1); // debug
(void) VALGRIND_MAKE_MEM_UNDEFINED(b, b_size_in_bytes);
fill(0, size_in_bytes, (rand() & 0xff) | 1); // debug
(void) VALGRIND_MAKE_MEM_UNDEFINED(ptr, size_in_bytes);
#endif
stats.global_alloc_counter += 1;
stats.global_total_bytes += b_size_in_bytes;
stats.global_total_active_bytes += b_size_in_bytes;
stats.global_total_bytes += size_in_bytes;
stats.global_total_active_bytes += size_in_bytes;
}
void MemBuffer::dealloc() {
if (b != nullptr) {
if (ptr != nullptr) {
debug_set(debug.last_return_address_dealloc, upx_return_address());
checkState();
stats.global_total_active_bytes -= b_size_in_bytes;
stats.global_total_active_bytes -= size_in_bytes;
if (use_simple_mcheck()) {
// clear magic constants
set_ne32(b - 8, 0);
set_ne32(b - 4, 0);
set_ne32(b + b_size_in_bytes, 0);
set_ne32(b + b_size_in_bytes + 4, 0);
set_ne32(ptr - 8, 0);
set_ne32(ptr - 4, 0);
set_ne32(ptr + size_in_bytes, 0);
set_ne32(ptr + size_in_bytes + 4, 0);
//
::free(b - 16);
::free(ptr - 16);
} else
::free(b);
b = nullptr;
b_size_in_bytes = 0;
::free(ptr);
ptr = nullptr;
size_in_bytes = 0;
} 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_THROWS(raw_bytes(mb, 65));
CHECK_NOTHROW(mb + 64);
CHECK_NOTHROW(64 + mb);
CHECK_THROWS(mb + 65);
#if ALLOW_INT_PLUS_MEMBUFFER
CHECK_NOTHROW(64 + mb);
CHECK_THROWS(65 + mb);
#endif
if (use_simple_mcheck()) {
upx_byte *b = raw_bytes(mb, 0);
unsigned magic1 = get_ne32(b - 4);
@ -280,9 +276,9 @@ TEST_CASE("MemBuffer") {
TEST_CASE("MemBuffer::getSizeForCompression") {
CHECK_THROWS(MemBuffer::getSizeForCompression(0));
CHECK_THROWS(MemBuffer::getSizeForDecompression(0));
CHECK(MemBuffer::getSizeForCompression(1) == 320);
CHECK(MemBuffer::getSizeForCompression(256) == 576);
CHECK(MemBuffer::getSizeForCompression(1024) == 1408);
CHECK(MemBuffer::getSizeForCompression(1) == 513);
CHECK(MemBuffer::getSizeForCompression(256) == 800);
CHECK(MemBuffer::getSizeForCompression(1024) == 1664);
// CHECK(MemBuffer::getSizeForCompression(1024 * 1024) == 0); // TODO
// CHECK(MemBuffer::getSizeForCompression(UPX_RSIZE_MAX) == 0); // TODO
}

View File

@ -37,18 +37,20 @@ template <class T>
class MemBufferBase {
public:
typedef T element_type;
typedef typename std::add_lvalue_reference<T>::type reference;
typedef typename std::add_pointer<T>::type pointer;
typedef unsigned size_type;
protected:
pointer b;
unsigned b_size_in_bytes;
pointer ptr;
size_type size_in_bytes;
public:
MemBufferBase() : b(nullptr), b_size_in_bytes(0) {}
MemBufferBase() : ptr(nullptr), size_in_bytes(0) {}
// NOTE: implicit conversion to underlying pointer
// 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>
typename std::enable_if<std::is_integral<U>::value, pointer>::type operator+(U n) const {
@ -59,18 +61,21 @@ public:
private:
// NOT allowed; use raw_bytes() instead
template <class U>
typename std::enable_if<std::is_integral<U>::value, pointer>::type
operator-(U n) const DELETED_FUNCTION;
typename std::enable_if<std::is_integral<U>::value, pointer>::type operator-(U n) const
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 {
if (bytes > 0) {
if very_unlikely (b == nullptr)
throwInternalError("MemBuffer raw_bytes unexpected NULL ptr");
if very_unlikely (bytes > b_size_in_bytes)
throwInternalError("MemBuffer raw_bytes invalid size");
if very_unlikely (ptr == nullptr)
throwCantPack("MemBuffer raw_bytes unexpected NULL ptr");
if very_unlikely (bytes > size_in_bytes)
throwCantPack("MemBuffer raw_bytes invalid size");
}
return b;
return ptr;
}
};
@ -89,19 +94,19 @@ public:
void dealloc();
void checkState() const;
unsigned getSize() const { return b_size_in_bytes; }
unsigned getSize() const { return size_in_bytes; }
// explicit converstion
void *getVoidPtr() { return (void *) b; }
const void *getVoidPtr() const { return (const void *) b; }
void *getVoidPtr() { return (void *) ptr; }
const void *getVoidPtr() const { return (const void *) ptr; }
// util
void fill(unsigned off, unsigned len, int value);
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,
// 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.
// skip == offset, take == size_in_bytes
forceinline pointer subref(const char *errfmt, size_t skip, size_t take) {
@ -130,7 +135,7 @@ private:
Debug debug;
#endif
// disable copy, assignment and move
// disable copy and move
MemBuffer(const MemBuffer &) DELETED_FUNCTION;
MemBuffer &operator=(const MemBuffer &) DELETED_FUNCTION;
#if __cplusplus >= 201103L
@ -159,11 +164,17 @@ inline typename MemBufferBase<T>::pointer raw_index_bytes(const MemBufferBase<T>
}
// global operators
#if ALLOW_INT_PLUS_MEMBUFFER
// rewrite "n + membuffer" to "membuffer + n" so that this will get checked above
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) {
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: */

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_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(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_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.
// This is overloaded by various utility classes like BoundedPtr,
// MemBuffer and XSpan.
// This is overloaded by various utility classes like MemBuffer and XSpan.
//
// Note that the pointer type is retained, the "_bytes" hints size_in_bytes
**************************************************************************/

View File

@ -31,6 +31,10 @@
template <class T, class U> \
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
**************************************************************************/

View File

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

View File

@ -25,9 +25,10 @@
<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
// of class Packer which then does the actual work.
// And see p_com.cpp for a simple executable format.
#include "conf.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);
if (opt->cmd == CMD_COMPRESS)
pm.pack(&fo);
@ -258,7 +259,7 @@ static void unlink_ofile(char *oname) {
IGNORE_ERROR(r);
#endif
if (unlink(oname) == 0)
oname[0] = 0;
oname[0] = 0; // done with oname
}
}