mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
CI updates and cleanups
This commit is contained in:
parent
6dac3dd248
commit
4a24fe8c53
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
|
@ -13,8 +13,8 @@ env:
|
||||||
CTEST_OUTPUT_ON_FAILURE: "ON"
|
CTEST_OUTPUT_ON_FAILURE: "ON"
|
||||||
DEBIAN_FRONTEND: noninteractive
|
DEBIAN_FRONTEND: noninteractive
|
||||||
UPX_CMAKE_BUILD_FLAGS: --verbose
|
UPX_CMAKE_BUILD_FLAGS: --verbose
|
||||||
# 2023-10-27
|
# 2023-10-29
|
||||||
ZIG_DIST_VERSION: 0.12.0-dev.1297+a9e66ed73
|
ZIG_DIST_VERSION: 0.12.0-dev.1327+256ab68a9
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
job-rebuild-and-verify-stubs:
|
job-rebuild-and-verify-stubs:
|
||||||
|
@ -317,7 +317,8 @@ jobs:
|
||||||
where cl & where link
|
where cl & where link
|
||||||
set RUN_CL=cl ${{ matrix.cl_machine_flags }} -MT
|
set RUN_CL=cl ${{ matrix.cl_machine_flags }} -MT
|
||||||
set RUN_LIB=link -lib ${{ matrix.link_machine_flags }}
|
set RUN_LIB=link -lib ${{ matrix.link_machine_flags }}
|
||||||
set DEFS=-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -DWIN32_LEAN_AND_MEAN
|
@rem UPX only uses the very basic Windows API
|
||||||
|
set DEFS=-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0400
|
||||||
set BDIR=%H%\build\%C%\%B%
|
set BDIR=%H%\build\%C%\%B%
|
||||||
git rev-parse --short=12 HEAD > %BDIR%\upx\.GITREV.txt
|
git rev-parse --short=12 HEAD > %BDIR%\upx\.GITREV.txt
|
||||||
@REM ===== build bzip2 =====
|
@REM ===== build bzip2 =====
|
||||||
|
|
|
@ -27,9 +27,9 @@ jobs:
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with: { submodules: true }
|
with: { submodules: true }
|
||||||
- { name: 'Config cmake Xcode', run: 'cmake -S . -B build/xcode -G Xcode' }
|
- { name: 'Config cmake Xcode', run: 'cmake -S . -B build/xcode -G Xcode' }
|
||||||
- { name: 'Build cmake Xcode default', run: 'cmake --build build/xcode' }
|
- { name: 'Build cmake Xcode default', run: 'cmake --build build/xcode --parallel --verbose' }
|
||||||
- { name: 'Build cmake Xcode Debug', run: 'cmake --build build/xcode --config Debug' }
|
- { name: 'Build cmake Xcode Debug', run: 'cmake --build build/xcode --parallel --verbose --config Debug' }
|
||||||
- { name: 'Build cmake Xcode Release', run: 'cmake --build build/xcode --config Release' }
|
- { name: 'Build cmake Xcode Release', run: 'cmake --build build/xcode --parallel --verbose --config Release' }
|
||||||
- name: 'Make artifact'
|
- name: 'Make artifact'
|
||||||
run: |
|
run: |
|
||||||
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-xcode-${{ matrix.os }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
|
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-xcode-${{ matrix.os }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
|
||||||
|
|
|
@ -11,6 +11,7 @@ env:
|
||||||
CMAKE_REQUIRED_QUIET: "OFF"
|
CMAKE_REQUIRED_QUIET: "OFF"
|
||||||
CTEST_OUTPUT_ON_FAILURE: "ON"
|
CTEST_OUTPUT_ON_FAILURE: "ON"
|
||||||
DEBIAN_FRONTEND: noninteractive
|
DEBIAN_FRONTEND: noninteractive
|
||||||
|
UPX_CMAKE_CONFIG_FLAGS: -DCMAKE_VERBOSE_MAKEFILE=ON
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
job-llvm-mingw: # uses cmake + make
|
job-llvm-mingw: # uses cmake + make
|
||||||
|
@ -51,18 +52,22 @@ jobs:
|
||||||
- name: 'Build clang aarch64'
|
- name: 'Build clang aarch64'
|
||||||
run: |
|
run: |
|
||||||
export CC="aarch64-w64-mingw32-clang -static" CXX="aarch64-w64-mingw32-clang++ -static"
|
export CC="aarch64-w64-mingw32-clang -static" CXX="aarch64-w64-mingw32-clang++ -static"
|
||||||
|
CC="$CC -D_WIN32_WINNT=0x0400"; CXX="$CXX -D_WIN32_WINNT=0x0400"
|
||||||
make UPX_XTARGET=aarch64-w64-mingw32-clang xtarget/debug xtarget/release
|
make UPX_XTARGET=aarch64-w64-mingw32-clang xtarget/debug xtarget/release
|
||||||
- name: 'Build clang armv7'
|
- name: 'Build clang armv7'
|
||||||
run: |
|
run: |
|
||||||
export CC="armv7-w64-mingw32-clang -static" CXX="armv7-w64-mingw32-clang++ -static"
|
export CC="armv7-w64-mingw32-clang -static" CXX="armv7-w64-mingw32-clang++ -static"
|
||||||
|
CC="$CC -D_WIN32_WINNT=0x0400"; CXX="$CXX -D_WIN32_WINNT=0x0400"
|
||||||
make UPX_XTARGET=armv7-w64-mingw32-clang xtarget/debug xtarget/release
|
make UPX_XTARGET=armv7-w64-mingw32-clang xtarget/debug xtarget/release
|
||||||
- name: 'Build clang i686'
|
- name: 'Build clang i686'
|
||||||
run: |
|
run: |
|
||||||
export CC="i686-w64-mingw32-clang -static" CXX="i686-w64-mingw32-clang++ -static"
|
export CC="i686-w64-mingw32-clang -static" CXX="i686-w64-mingw32-clang++ -static"
|
||||||
|
CC="$CC -D_WIN32_WINNT=0x0400"; CXX="$CXX -D_WIN32_WINNT=0x0400"
|
||||||
make UPX_XTARGET=i686-w64-mingw32-clang xtarget/debug xtarget/release
|
make UPX_XTARGET=i686-w64-mingw32-clang xtarget/debug xtarget/release
|
||||||
- name: 'Build clang x86_64'
|
- name: 'Build clang x86_64'
|
||||||
run: |
|
run: |
|
||||||
export CC="x86_64-w64-mingw32-clang -static" CXX="x86_64-w64-mingw32-clang++ -static"
|
export CC="x86_64-w64-mingw32-clang -static" CXX="x86_64-w64-mingw32-clang++ -static"
|
||||||
|
CC="$CC -D_WIN32_WINNT=0x0400"; CXX="$CXX -D_WIN32_WINNT=0x0400"
|
||||||
make UPX_XTARGET=x86_64-w64-mingw32-clang xtarget/debug xtarget/release
|
make UPX_XTARGET=x86_64-w64-mingw32-clang xtarget/debug xtarget/release
|
||||||
- name: 'Make artifact'
|
- name: 'Make artifact'
|
||||||
run: |
|
run: |
|
||||||
|
|
4
.github/workflows/weekly-ci-cc-zigcc.yml
vendored
4
.github/workflows/weekly-ci-cc-zigcc.yml
vendored
|
@ -11,8 +11,8 @@ env:
|
||||||
CMAKE_REQUIRED_QUIET: "OFF"
|
CMAKE_REQUIRED_QUIET: "OFF"
|
||||||
CTEST_OUTPUT_ON_FAILURE: "ON"
|
CTEST_OUTPUT_ON_FAILURE: "ON"
|
||||||
DEBIAN_FRONTEND: noninteractive
|
DEBIAN_FRONTEND: noninteractive
|
||||||
# 2023-10-27
|
# 2023-10-29
|
||||||
ZIG_DIST_VERSION: 0.12.0-dev.1297+a9e66ed73
|
ZIG_DIST_VERSION: 0.12.0-dev.1327+256ab68a9
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
job-linux-zigcc: # uses cmake + make
|
job-linux-zigcc: # uses cmake + make
|
||||||
|
|
|
@ -11,9 +11,23 @@
|
||||||
if(DEFINED UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION)
|
if(DEFINED UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION)
|
||||||
cmake_minimum_required(VERSION "${UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION}" FATAL_ERROR)
|
cmake_minimum_required(VERSION "${UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION}" FATAL_ERROR)
|
||||||
else()
|
else()
|
||||||
cmake_minimum_required(VERSION 3.8 FATAL_ERROR) # CMake >= 3.8 is needed for CXX_STANDARD 17
|
cmake_minimum_required(VERSION "3.8" FATAL_ERROR) # CMake >= 3.8 is needed for CXX_STANDARD 17
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Sections of this CMakeLists.txt:
|
||||||
|
# - options
|
||||||
|
# - init
|
||||||
|
# - common compilation flags
|
||||||
|
# - targets
|
||||||
|
# - target compilation flags
|
||||||
|
# - test
|
||||||
|
# - install
|
||||||
|
# - print summary
|
||||||
|
|
||||||
|
#***********************************************************************
|
||||||
|
# options
|
||||||
|
#***********************************************************************
|
||||||
|
|
||||||
# compilation config options
|
# compilation config options
|
||||||
if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")
|
if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")
|
||||||
# permissive config defaults when building from source code tarball
|
# permissive config defaults when building from source code tarball
|
||||||
|
@ -281,12 +295,23 @@ if(NOT CMAKE_C_COMPILER_ID MATCHES "^MSVC")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# compile a source file with -O2 even in Debug build
|
# compile a target with -O2 optimization even in Debug build
|
||||||
|
function(upx_compile_target_debug_with_O2)
|
||||||
|
foreach(t ${ARGV})
|
||||||
|
if(MSVC_FRONTEND)
|
||||||
|
# MSVC uses some Debug compilation options like -RTC1 that are incompatible with -O2
|
||||||
|
else()
|
||||||
|
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-O2>)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# compile a source file with -O2 optimization even in Debug build; messy because of CMake limitations
|
||||||
function(upx_compile_source_debug_with_O2)
|
function(upx_compile_source_debug_with_O2)
|
||||||
set(flags "$<$<CONFIG:Debug>:-O2>")
|
set(flags "$<$<CONFIG:Debug>:-O2>")
|
||||||
if (CMAKE_VERSION VERSION_LESS 3.8)
|
if(${CMAKE_VERSION} VERSION_LESS "3.8")
|
||||||
# 3.8: The COMPILE_FLAGS source file property learned to support generator expressions
|
# 3.8: The COMPILE_FLAGS source file property learned to support generator expressions
|
||||||
if (is_multi_config OR NOT CMAKE_BUILD_TYPE MATCHES "^Debug$")
|
if(is_multi_config OR NOT CMAKE_BUILD_TYPE MATCHES "^Debug$")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
set(flags "-O2")
|
set(flags "-O2")
|
||||||
|
@ -309,17 +334,6 @@ function(upx_compile_source_debug_with_O2)
|
||||||
endforeach()
|
endforeach()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# compile a target with -O2 even in Debug build
|
|
||||||
function(upx_compile_target_debug_with_O2)
|
|
||||||
foreach(t ${ARGV})
|
|
||||||
if(MSVC_FRONTEND)
|
|
||||||
# MSVC uses some Debug compilation options like -RTC1 that are incompatible with -O2
|
|
||||||
else()
|
|
||||||
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-O2>)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# sanitize a target
|
# sanitize a target
|
||||||
function(upx_sanitize_target)
|
function(upx_sanitize_target)
|
||||||
foreach(t ${ARGV})
|
foreach(t ${ARGV})
|
||||||
|
@ -484,7 +498,7 @@ if(HAVE_UTIMENSAT)
|
||||||
target_compile_definitions(${t} PRIVATE HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC=1)
|
target_compile_definitions(${t} PRIVATE HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC=1)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
# improve speed of the debug versions
|
# improve speed of the Debug versions
|
||||||
upx_compile_source_debug_with_O2(src/compress/compress_lzma.cpp)
|
upx_compile_source_debug_with_O2(src/compress/compress_lzma.cpp)
|
||||||
upx_compile_source_debug_with_O2(src/filter/filter_impl.cpp)
|
upx_compile_source_debug_with_O2(src/filter/filter_impl.cpp)
|
||||||
#upx_compile_target_debug_with_O2(${t})
|
#upx_compile_target_debug_with_O2(${t})
|
||||||
|
@ -496,9 +510,10 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# ctest
|
# test
|
||||||
# make test
|
# ctest
|
||||||
# ninja test
|
# make test
|
||||||
|
# ninja test
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
|
|
||||||
if(NOT UPX_CONFIG_CMAKE_DISABLE_TEST)
|
if(NOT UPX_CONFIG_CMAKE_DISABLE_TEST)
|
||||||
|
@ -536,9 +551,10 @@ endif()
|
||||||
endif() # UPX_CONFIG_CMAKE_DISABLE_TEST
|
endif() # UPX_CONFIG_CMAKE_DISABLE_TEST
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# cmake --install .
|
# install
|
||||||
# make install
|
# cmake --install .
|
||||||
# ninja install
|
# make install
|
||||||
|
# ninja install
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
|
|
||||||
if(NOT UPX_CONFIG_CMAKE_DISABLE_INSTALL)
|
if(NOT UPX_CONFIG_CMAKE_DISABLE_INSTALL)
|
||||||
|
@ -563,13 +579,16 @@ endif()
|
||||||
endif() # UPX_CONFIG_CMAKE_DISABLE_INSTALL
|
endif() # UPX_CONFIG_CMAKE_DISABLE_INSTALL
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# finally print some info about the build configuration
|
# show summary
|
||||||
|
# print some info about the build configuration
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
|
|
||||||
function(print_var)
|
function(print_var)
|
||||||
foreach(var ${ARGV})
|
foreach(var ${ARGV})
|
||||||
if(${var})
|
if(DEFINED ${var} AND NOT ",${${var}}," STREQUAL ",,")
|
||||||
message(STATUS "${var} = ${${var}}")
|
if(${var})
|
||||||
|
message(STATUS "${var} = ${${var}}")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -56,7 +56,11 @@ build/%/all: $$(dir $$@)debug $$(dir $$@)release ;
|
||||||
#
|
#
|
||||||
|
|
||||||
# extra pre-defined build configurations and some utility; optional
|
# extra pre-defined build configurations and some utility; optional
|
||||||
|
ifneq ($(MAKEFILE_LIST),)
|
||||||
|
include $(dir $(lastword $(MAKEFILE_LIST)))/misc/make/Makefile-extra.mk
|
||||||
|
else
|
||||||
include ./misc/make/Makefile-extra.mk
|
include ./misc/make/Makefile-extra.mk
|
||||||
|
endif
|
||||||
|
|
||||||
# developer convenience
|
# developer convenience
|
||||||
ifneq ($(wildcard /usr/bin/env),) # needs bash, perl, xargs, etc.
|
ifneq ($(wildcard /usr/bin/env),) # needs bash, perl, xargs, etc.
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
|
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
|
||||||
#
|
#
|
||||||
|
|
||||||
|
ifeq ($(UPX_MAKEFILE_EXTRA_MK_INCLUDED),)
|
||||||
|
UPX_MAKEFILE_EXTRA_MK_INCLUDED := 1
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# extra builds: some pre-defined build configurations
|
# extra builds: some pre-defined build configurations
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
|
@ -131,14 +134,14 @@ build/extra/cross-linux-gnu-arm-eabihf/%: export CXX = arm-linux-gnueabihf-g++ -
|
||||||
# cross compiler: Windows x86 win32 MinGW (i386)
|
# cross compiler: Windows x86 win32 MinGW (i386)
|
||||||
build/extra/cross-windows-mingw32/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
build/extra/cross-windows-mingw32/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||||
build/extra/cross-windows-mingw32/release: PHONY; $(call run_config_and_build,$@,Release)
|
build/extra/cross-windows-mingw32/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||||
build/extra/cross-windows-mingw32/%: export CC = i686-w64-mingw32-gcc -static
|
build/extra/cross-windows-mingw32/%: export CC = i686-w64-mingw32-gcc -static -D_WIN32_WINNT=0x0400
|
||||||
build/extra/cross-windows-mingw32/%: export CXX = i686-w64-mingw32-g++ -static
|
build/extra/cross-windows-mingw32/%: export CXX = i686-w64-mingw32-g++ -static -D_WIN32_WINNT=0x0400
|
||||||
|
|
||||||
# cross compiler: Windows x64 win64 MinGW (amd64)
|
# cross compiler: Windows x64 win64 MinGW (amd64)
|
||||||
build/extra/cross-windows-mingw64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
build/extra/cross-windows-mingw64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||||
build/extra/cross-windows-mingw64/release: PHONY; $(call run_config_and_build,$@,Release)
|
build/extra/cross-windows-mingw64/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||||
build/extra/cross-windows-mingw64/%: export CC = x86_64-w64-mingw32-gcc -static
|
build/extra/cross-windows-mingw64/%: export CC = x86_64-w64-mingw32-gcc -static -D_WIN32_WINNT=0x0400
|
||||||
build/extra/cross-windows-mingw64/%: export CXX = x86_64-w64-mingw32-g++ -static
|
build/extra/cross-windows-mingw64/%: export CXX = x86_64-w64-mingw32-g++ -static -D_WIN32_WINNT=0x0400
|
||||||
|
|
||||||
# cross compiler: macOS arm64 (aarch64)
|
# cross compiler: macOS arm64 (aarch64)
|
||||||
build/extra/cross-darwin-arm64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
build/extra/cross-darwin-arm64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||||
|
@ -249,3 +252,5 @@ SUBMODULES = doctest lzma-sdk ucl valgrind zlib
|
||||||
|
|
||||||
dummy := $(foreach m,$(SUBMODULES),$(if $(wildcard vendor/$m/[CL]*),$m,\
|
dummy := $(foreach m,$(SUBMODULES),$(if $(wildcard vendor/$m/[CL]*),$m,\
|
||||||
$(error ERROR: missing git submodule '$m'; run 'git submodule update --init')))
|
$(error ERROR: missing git submodule '$m'; run 'git submodule update --init')))
|
||||||
|
|
||||||
|
endif # UPX_MAKEFILE_EXTRA_MK_INCLUDED
|
||||||
|
|
|
@ -106,7 +106,8 @@ TEST_CASE("noncopyable") {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// TriBool
|
// TriBool checks
|
||||||
|
// (modern compilers will optimize away most of this code)
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -855,8 +855,8 @@ int main_get_options(int argc, char **argv) {
|
||||||
{"fake-stub-version", 0x31, N, 542}, // for internal debugging
|
{"fake-stub-version", 0x31, N, 542}, // for internal debugging
|
||||||
{"fake-stub-year", 0x31, N, 543}, // for internal debugging
|
{"fake-stub-year", 0x31, N, 543}, // for internal debugging
|
||||||
{"disable-random-id", 0x90, N, 545}, // for internal debugging
|
{"disable-random-id", 0x90, N, 545}, // for internal debugging
|
||||||
{"debug-use-random-method", 0x90, N, 546}, // for internal debugging
|
{"debug-use-random-method", 0x90, N, 546}, // for internal debugging / fuzz testing
|
||||||
{"debug-use-random-filter", 0x90, N, 547}, // for internal debugging
|
{"debug-use-random-filter", 0x90, N, 547}, // for internal debugging / fuzz testing
|
||||||
|
|
||||||
// backup options
|
// backup options
|
||||||
{"backup", 0x10, N, 'k'},
|
{"backup", 0x10, N, 'k'},
|
||||||
|
|
|
@ -54,10 +54,12 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Options final {
|
struct Options final {
|
||||||
int cmd;
|
void reset() noexcept;
|
||||||
|
|
||||||
|
int cmd; // CMD_xxx
|
||||||
|
|
||||||
// compression options
|
// compression options
|
||||||
int method;
|
int method; // M_xxx
|
||||||
bool method_lzma_seen;
|
bool method_lzma_seen;
|
||||||
bool method_nrv2b_seen;
|
bool method_nrv2b_seen;
|
||||||
bool method_nrv2d_seen;
|
bool method_nrv2d_seen;
|
||||||
|
@ -90,6 +92,20 @@ struct Options final {
|
||||||
int verbose;
|
int verbose;
|
||||||
bool to_stdout;
|
bool to_stdout;
|
||||||
|
|
||||||
|
// overlay handling
|
||||||
|
enum { SKIP_OVERLAY = 0, COPY_OVERLAY = 1, STRIP_OVERLAY = 2 };
|
||||||
|
int overlay;
|
||||||
|
|
||||||
|
// CPU options for i086/i386
|
||||||
|
enum {
|
||||||
|
CPU_DEFAULT = 0,
|
||||||
|
CPU_8086 = 1,
|
||||||
|
CPU_286 = 2,
|
||||||
|
CPU_386 = 3,
|
||||||
|
CPU_486 = 4,
|
||||||
|
};
|
||||||
|
int cpu_x86;
|
||||||
|
|
||||||
// debug options
|
// debug options
|
||||||
struct {
|
struct {
|
||||||
int debug_level;
|
int debug_level;
|
||||||
|
@ -98,14 +114,10 @@ struct Options final {
|
||||||
char fake_stub_version[4 + 1]; // for internal debugging
|
char fake_stub_version[4 + 1]; // for internal debugging
|
||||||
char fake_stub_year[4 + 1]; // for internal debugging
|
char fake_stub_year[4 + 1]; // for internal debugging
|
||||||
bool getopt_throw_instead_of_exit; // for internal doctest checks
|
bool getopt_throw_instead_of_exit; // for internal doctest checks
|
||||||
bool use_random_method; // for internal debugging
|
bool use_random_method; // for internal debugging / fuzz testing
|
||||||
bool use_random_filter; // for internal debugging
|
bool use_random_filter; // for internal debugging / fuzz testing
|
||||||
} debug;
|
} debug;
|
||||||
|
|
||||||
// overlay handling
|
|
||||||
enum { SKIP_OVERLAY = 0, COPY_OVERLAY = 1, STRIP_OVERLAY = 2 };
|
|
||||||
int overlay;
|
|
||||||
|
|
||||||
// CRP - Compression Runtime Parameters (undocumented and subject to change)
|
// CRP - Compression Runtime Parameters (undocumented and subject to change)
|
||||||
struct {
|
struct {
|
||||||
lzma_compress_config_t crp_lzma;
|
lzma_compress_config_t crp_lzma;
|
||||||
|
@ -120,16 +132,6 @@ struct Options final {
|
||||||
}
|
}
|
||||||
} crp;
|
} crp;
|
||||||
|
|
||||||
// CPU options for i086/i386
|
|
||||||
enum {
|
|
||||||
CPU_DEFAULT = 0,
|
|
||||||
CPU_8086 = 1,
|
|
||||||
CPU_286 = 2,
|
|
||||||
CPU_386 = 3,
|
|
||||||
CPU_486 = 4,
|
|
||||||
};
|
|
||||||
int cpu_x86;
|
|
||||||
|
|
||||||
// options for various executable formats
|
// options for various executable formats
|
||||||
struct {
|
struct {
|
||||||
bool split_segments;
|
bool split_segments;
|
||||||
|
@ -173,8 +175,6 @@ struct Options final {
|
||||||
int strip_relocs;
|
int strip_relocs;
|
||||||
const char *keep_resource;
|
const char *keep_resource;
|
||||||
} win32_pe;
|
} win32_pe;
|
||||||
|
|
||||||
void reset() noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|
167
src/pefile.cpp
167
src/pefile.cpp
|
@ -49,8 +49,8 @@ static void xcheck(const void *p) {
|
||||||
throwCantUnpack("xcheck unexpected nullptr pointer; take care!");
|
throwCantUnpack("xcheck unexpected nullptr pointer; take care!");
|
||||||
}
|
}
|
||||||
static void xcheck(const void *p, size_t plen, const void *b, size_t blen) {
|
static void xcheck(const void *p, size_t plen, const void *b, size_t blen) {
|
||||||
const char *pp = (const char *) p;
|
const charptr pp = (const charptr) p;
|
||||||
const char *bb = (const char *) b;
|
const charptr bb = (const charptr) b;
|
||||||
if very_unlikely (pp < bb || pp > bb + blen || pp + plen > bb + blen)
|
if very_unlikely (pp < bb || pp > bb + blen || pp + plen > bb + blen)
|
||||||
throwCantUnpack("xcheck pointer out of range; take care!");
|
throwCantUnpack("xcheck pointer out of range; take care!");
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ bool PeFile::testUnpackVersion(int version) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PeFile::readFileHeader() {
|
int PeFile::readFileHeader() {
|
||||||
struct alignas(1) exe_header_t {
|
struct alignas(1) ExeHeader final {
|
||||||
LE16 mz;
|
LE16 mz;
|
||||||
LE16 m512;
|
LE16 m512;
|
||||||
LE16 p512;
|
LE16 p512;
|
||||||
|
@ -164,12 +164,12 @@ int PeFile::readFileHeader() {
|
||||||
LE32 nexepos;
|
LE32 nexepos;
|
||||||
};
|
};
|
||||||
|
|
||||||
COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 64)
|
COMPILE_TIME_ASSERT(sizeof(ExeHeader) == 64)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(exe_header_t)
|
COMPILE_TIME_ASSERT_ALIGNED1(ExeHeader)
|
||||||
COMPILE_TIME_ASSERT(sizeof(((exe_header_t *) nullptr)->_) == 18)
|
COMPILE_TIME_ASSERT(sizeof(((ExeHeader *) nullptr)->_) == 18)
|
||||||
COMPILE_TIME_ASSERT(sizeof(((exe_header_t *) nullptr)->__) == 34)
|
COMPILE_TIME_ASSERT(sizeof(((ExeHeader *) nullptr)->__) == 34)
|
||||||
|
|
||||||
exe_header_t h;
|
ExeHeader h;
|
||||||
int ic;
|
int ic;
|
||||||
pe_offset = 0;
|
pe_offset = 0;
|
||||||
|
|
||||||
|
@ -179,11 +179,11 @@ int PeFile::readFileHeader() {
|
||||||
|
|
||||||
if (h.mz == 'M' + 'Z' * 256) // dos exe
|
if (h.mz == 'M' + 'Z' * 256) // dos exe
|
||||||
{
|
{
|
||||||
if (h.nexepos && h.nexepos < sizeof(exe_header_t)) {
|
if (h.nexepos && h.nexepos < sizeof(ExeHeader)) {
|
||||||
// Overlapping MZ and PE headers by 'leanify', etc.
|
// Overlapping MZ and PE headers by 'leanify', etc.
|
||||||
char buf[64];
|
char buf[64];
|
||||||
snprintf(buf, sizeof(buf), "PE and MZ header overlap: %#x < %#x",
|
snprintf(buf, sizeof(buf), "PE and MZ header overlap: %#x < %#x",
|
||||||
(unsigned) h.nexepos, (unsigned) sizeof(exe_header_t));
|
(unsigned) h.nexepos, (unsigned) sizeof(ExeHeader));
|
||||||
throwCantPack(buf);
|
throwCantPack(buf);
|
||||||
}
|
}
|
||||||
const unsigned delta = (h.relocoffs >= 0x40)
|
const unsigned delta = (h.relocoffs >= 0x40)
|
||||||
|
@ -283,11 +283,11 @@ void PeFile::Interval::dump() const {
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct FixDeleter { // don't leak memory on exceptions
|
struct FixDeleter final { // helper so we don't leak memory on exceptions
|
||||||
LE32 **fix;
|
LE32 **fix;
|
||||||
size_t n;
|
size_t count;
|
||||||
~FixDeleter() noexcept {
|
~FixDeleter() noexcept {
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
delete[] fix[i];
|
delete[] fix[i];
|
||||||
fix[i] = nullptr;
|
fix[i] = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -492,7 +492,7 @@ void PeFile32::processRelocs() // pass1
|
||||||
FixDeleter fixdel{fix, 0}; // don't leak memory
|
FixDeleter fixdel{fix, 0}; // don't leak memory
|
||||||
for (ic = 0; ic < 4; ic++) {
|
for (ic = 0; ic < 4; ic++) {
|
||||||
fix[ic] = New(LE32, counts[ic]);
|
fix[ic] = New(LE32, counts[ic]);
|
||||||
fixdel.n += 1;
|
fixdel.count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned xcounts[4];
|
unsigned xcounts[4];
|
||||||
|
@ -594,7 +594,7 @@ void PeFile64::processRelocs() // pass1
|
||||||
FixDeleter fixdel{fix, 0}; // don't leak memory
|
FixDeleter fixdel{fix, 0}; // don't leak memory
|
||||||
for (ic = 0; ic < 16; ic++) {
|
for (ic = 0; ic < 16; ic++) {
|
||||||
fix[ic] = New(LE32, counts[ic]);
|
fix[ic] = New(LE32, counts[ic]);
|
||||||
fixdel.n += 1;
|
fixdel.count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned xcounts[16];
|
unsigned xcounts[16];
|
||||||
|
@ -686,16 +686,18 @@ const LE32 &PeFile::IDADDR(unsigned x) const { return iddirs[x].vaddr; }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PeFile::ImportLinker final : public ElfLinkerAMD64 {
|
class PeFile::ImportLinker final : public ElfLinkerAMD64 {
|
||||||
struct tstr : private ::noncopyable {
|
struct TStr final : private ::noncopyable { // temporary string owner, deletes on destruction
|
||||||
char *s = nullptr;
|
explicit TStr(char *str) noexcept : s(str) {}
|
||||||
explicit tstr(char *str) : s(str) {}
|
~TStr() noexcept { delete[] s; } // delete!
|
||||||
~tstr() noexcept { delete[] s; }
|
operator char *() noexcept { return s; }
|
||||||
operator char *() const { return s; }
|
operator const char *() const noexcept { return s; }
|
||||||
|
private:
|
||||||
|
char *s;
|
||||||
};
|
};
|
||||||
|
|
||||||
// encoding of dll and proc names are required, so that our special
|
// encoding of dll and proc names are required, so that our special
|
||||||
// control characters in the name of sections can work as intended
|
// control characters in the name of sections can work as intended
|
||||||
static void encode_name(const char *name, char *buf) {
|
static void encode_name(SPAN_P(const char) name, SPAN_S(char) buf) {
|
||||||
while (*name) {
|
while (*name) {
|
||||||
*buf++ = 'a' + ((*name >> 4) & 0xf);
|
*buf++ = 'a' + ((*name >> 4) & 0xf);
|
||||||
*buf++ = 'a' + (*name & 0xf);
|
*buf++ = 'a' + (*name & 0xf);
|
||||||
|
@ -705,27 +707,29 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *name_for_dll(const char *dll, char first_char) {
|
static char *name_for_dll(const char *dll, char first_char) {
|
||||||
assert(dll);
|
assert(dll != nullptr);
|
||||||
unsigned l = strlen(dll);
|
const unsigned l = strlen(dll);
|
||||||
assert(l > 0);
|
assert(l > 0);
|
||||||
|
const unsigned new_size = 1 + 3 * l + 1;
|
||||||
char *name = New(char, 3 * l + 2);
|
char *const new_name = New(char, new_size);
|
||||||
|
SPAN_S_VAR(char, const name, new_name, new_size);
|
||||||
name[0] = first_char;
|
name[0] = first_char;
|
||||||
char *n = name + 1 + 2 * l;
|
SPAN_S_VAR(char, n, name + (1 + 2 * l));
|
||||||
do {
|
do {
|
||||||
*n++ = tolower((uchar) *dll);
|
*n++ = tolower((uchar) *dll);
|
||||||
} while (*dll++);
|
} while (*dll++);
|
||||||
encode_name(name + 1 + 2 * l, name + 1);
|
encode_name(new_name + (1 + 2 * l), name + 1);
|
||||||
return name;
|
return new_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *name_for_proc(const char *dll, const char *proc, char first_char, char separator) {
|
static char *name_for_proc(const char *dll, const char *proc, char first_char, char separator) {
|
||||||
unsigned len = 1 + 2 * strlen(dll) + 1 + 2 * strlen(proc) + 1 + 1;
|
const unsigned new_size = 1 + 2 * strlen(dll) + 1 + 2 * strlen(proc) + 1 + 1;
|
||||||
tstr dlln(name_for_dll(dll, first_char));
|
TStr dll_name(name_for_dll(dll, first_char));
|
||||||
char *procn = New(char, len);
|
char *const new_name = New(char, new_size);
|
||||||
upx_safe_snprintf(procn, len, "%s%c", (const char *) dlln, separator);
|
SPAN_S_VAR(char, const name, new_name, new_size);
|
||||||
encode_name(proc, procn + strlen(procn));
|
upx_safe_snprintf(new_name, new_size, "%s%c", (const char *) dll_name, separator);
|
||||||
return procn;
|
encode_name(proc, name + strlen(name));
|
||||||
|
return new_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char zeros[sizeof(import_desc)];
|
static const char zeros[sizeof(import_desc)];
|
||||||
|
@ -747,8 +751,8 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 {
|
||||||
unsigned thunk_size; // 4 or 8 bytes
|
unsigned thunk_size; // 4 or 8 bytes
|
||||||
|
|
||||||
void add(const char *dll, const char *proc, unsigned ordinal) {
|
void add(const char *dll, const char *proc, unsigned ordinal) {
|
||||||
tstr sdll(name_for_dll(dll, dll_name_id));
|
TStr sdll(name_for_dll(dll, dll_name_id));
|
||||||
tstr desc_name(name_for_dll(dll, descriptor_id));
|
TStr desc_name(name_for_dll(dll, descriptor_id));
|
||||||
|
|
||||||
char tsep = thunk_separator;
|
char tsep = thunk_separator;
|
||||||
if (findSection(sdll, false) == nullptr) {
|
if (findSection(sdll, false) == nullptr) {
|
||||||
|
@ -759,7 +763,7 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 {
|
||||||
addSection(desc_name, zeros, sizeof(zeros), 0); // descriptor
|
addSection(desc_name, zeros, sizeof(zeros), 0); // descriptor
|
||||||
addRelocation(desc_name, offsetof(import_desc, dllname), "R_X86_64_32", sdll, 0);
|
addRelocation(desc_name, offsetof(import_desc, dllname), "R_X86_64_32", sdll, 0);
|
||||||
}
|
}
|
||||||
tstr thunk(proc == nullptr ? name_for_dll(dll, thunk_id)
|
TStr thunk(proc == nullptr ? name_for_dll(dll, thunk_id)
|
||||||
: name_for_proc(dll, proc, thunk_id, tsep));
|
: name_for_proc(dll, proc, thunk_id, tsep));
|
||||||
|
|
||||||
if (findSection(thunk, false) != nullptr)
|
if (findSection(thunk, false) != nullptr)
|
||||||
|
@ -769,7 +773,7 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 {
|
||||||
if (tsep == thunk_separator_first) {
|
if (tsep == thunk_separator_first) {
|
||||||
addRelocation(desc_name, offsetof(import_desc, iat), "R_X86_64_32", thunk, 0);
|
addRelocation(desc_name, offsetof(import_desc, iat), "R_X86_64_32", thunk, 0);
|
||||||
|
|
||||||
tstr last_thunk(name_for_proc(dll, "X", thunk_id, thunk_separator_last));
|
TStr last_thunk(name_for_proc(dll, "X", thunk_id, thunk_separator_last));
|
||||||
addSection(last_thunk, zeros, thunk_size, 0);
|
addSection(last_thunk, zeros, thunk_size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,7 +781,7 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 {
|
||||||
if (ordinal != 0u) {
|
if (ordinal != 0u) {
|
||||||
addRelocation(thunk, 0, reltype, "*UND*", ordinal | (1ull << (thunk_size * 8 - 1)));
|
addRelocation(thunk, 0, reltype, "*UND*", ordinal | (1ull << (thunk_size * 8 - 1)));
|
||||||
} else if (proc != nullptr) {
|
} else if (proc != nullptr) {
|
||||||
tstr proc_name(name_for_proc(dll, proc, proc_name_id, procname_separator));
|
TStr proc_name(name_for_proc(dll, proc, proc_name_id, procname_separator));
|
||||||
addSection(proc_name, zeros, 2, 1); // 2 bytes of word aligned "hint"
|
addSection(proc_name, zeros, 2, 1); // 2 bytes of word aligned "hint"
|
||||||
addSymbol(proc_name, proc_name, 0);
|
addSymbol(proc_name, proc_name, 0);
|
||||||
addRelocation(thunk, 0, reltype, proc_name, 0);
|
addRelocation(thunk, 0, reltype, proc_name, 0);
|
||||||
|
@ -806,7 +810,7 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 {
|
||||||
const Section *getThunk(const char *dll, const char *proc, char tsep) const {
|
const Section *getThunk(const char *dll, const char *proc, char tsep) const {
|
||||||
assert(dll);
|
assert(dll);
|
||||||
assert(proc);
|
assert(proc);
|
||||||
tstr thunk(name_for_proc(dll, proc, thunk_id, tsep));
|
TStr thunk(name_for_proc(dll, proc, thunk_id, tsep));
|
||||||
return findSection(thunk, false);
|
return findSection(thunk, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,7 +891,6 @@ public:
|
||||||
assert(ordinal > 0 && ordinal < 0x10000);
|
assert(ordinal > 0 && ordinal < 0x10000);
|
||||||
char ord[1 + 5 + 1];
|
char ord[1 + 5 + 1];
|
||||||
upx_safe_snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
|
upx_safe_snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
|
||||||
|
|
||||||
const Section *s = getThunk((const char *) dll, ord, thunk_separator_first);
|
const Section *s = getThunk((const char *) dll, ord, thunk_separator_first);
|
||||||
if (s == nullptr && (s = getThunk((const char *) dll, ord, thunk_separator)) == nullptr)
|
if (s == nullptr && (s = getThunk((const char *) dll, ord, thunk_separator)) == nullptr)
|
||||||
throwInternalError("entry not found");
|
throwInternalError("entry not found");
|
||||||
|
@ -897,18 +900,18 @@ public:
|
||||||
template <typename C>
|
template <typename C>
|
||||||
upx_uint64_t getAddress(const C *dll) const {
|
upx_uint64_t getAddress(const C *dll) const {
|
||||||
ACC_COMPILE_TIME_ASSERT(sizeof(C) == 1) // "char" or "byte"
|
ACC_COMPILE_TIME_ASSERT(sizeof(C) == 1) // "char" or "byte"
|
||||||
tstr sdll(name_for_dll((const char *) dll, dll_name_id));
|
TStr sdll(name_for_dll((const char *) dll, dll_name_id));
|
||||||
return findSection(sdll, true)->offset;
|
return findSection(sdll, true)->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
upx_uint64_t hasDll(const C *dll) const {
|
upx_uint64_t hasDll(const C *dll) const {
|
||||||
ACC_COMPILE_TIME_ASSERT(sizeof(C) == 1) // "char" or "byte"
|
ACC_COMPILE_TIME_ASSERT(sizeof(C) == 1) // "char" or "byte"
|
||||||
tstr sdll(name_for_dll((const char *) dll, dll_name_id));
|
TStr sdll(name_for_dll((const char *) dll, dll_name_id));
|
||||||
return findSection(sdll, false) != nullptr;
|
return findSection(sdll, false) != nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const char PeFile::ImportLinker::zeros[sizeof(import_desc)] = {0};
|
/*static*/ const char PeFile::ImportLinker::zeros[sizeof(import_desc)] = {0};
|
||||||
|
|
||||||
void PeFile::addKernelImport(const char *name) { ilinker->add(kernelDll(), name); }
|
void PeFile::addKernelImport(const char *name) { ilinker->add(kernelDll(), name); }
|
||||||
|
|
||||||
|
@ -923,10 +926,8 @@ void PeFile::addStubImports() {
|
||||||
void PeFile::processImports2(unsigned myimport, unsigned) // pass 2
|
void PeFile::processImports2(unsigned myimport, unsigned) // pass 2
|
||||||
{
|
{
|
||||||
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20)
|
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20)
|
||||||
|
if (ilinker == nullptr)
|
||||||
if (!ilinker)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ilinker->relocate_import(myimport);
|
ilinker->relocate_import(myimport);
|
||||||
int len;
|
int len;
|
||||||
oimpdlls = ilinker->getLoader(&len);
|
oimpdlls = ilinker->getLoader(&len);
|
||||||
|
@ -958,7 +959,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
||||||
if (dllnum > 4096) // just some arbitrary limit/sanity check
|
if (dllnum > 4096) // just some arbitrary limit/sanity check
|
||||||
throwCantPack("too many DLL imports %u", dllnum);
|
throwCantPack("too many DLL imports %u", dllnum);
|
||||||
|
|
||||||
struct udll {
|
struct UDll final {
|
||||||
const byte *name;
|
const byte *name;
|
||||||
const byte *shname;
|
const byte *shname;
|
||||||
unsigned ordinal;
|
unsigned ordinal;
|
||||||
|
@ -968,8 +969,8 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
||||||
bool isk32;
|
bool isk32;
|
||||||
|
|
||||||
static int __acc_cdecl_qsort compare(const void *aa, const void *bb) {
|
static int __acc_cdecl_qsort compare(const void *aa, const void *bb) {
|
||||||
const udll *a = *(const udll *const *) aa;
|
const UDll *a = *(const UDll *const *) aa;
|
||||||
const udll *b = *(const udll *const *) bb;
|
const UDll *b = *(const UDll *const *) bb;
|
||||||
if (a->original_position == b->original_position) // identical object, poor qsort()
|
if (a->original_position == b->original_position) // identical object, poor qsort()
|
||||||
return 0;
|
return 0;
|
||||||
if (a->isk32 != b->isk32)
|
if (a->isk32 != b->isk32)
|
||||||
|
@ -997,8 +998,8 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
||||||
};
|
};
|
||||||
|
|
||||||
// +1 for dllnum=0
|
// +1 for dllnum=0
|
||||||
Array(struct udll, dlls, dllnum + 1);
|
Array(UDll, dlls, dllnum + 1);
|
||||||
Array(struct udll *, idlls, dllnum + 1);
|
Array(UDll *, idlls, dllnum + 1);
|
||||||
|
|
||||||
soimport = 1024; // safety
|
soimport = 1024; // safety
|
||||||
|
|
||||||
|
@ -1036,7 +1037,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
||||||
mb_oimport.clear();
|
mb_oimport.clear();
|
||||||
oimport = mb_oimport;
|
oimport = mb_oimport;
|
||||||
|
|
||||||
upx_qsort(idlls, dllnum, sizeof(*idlls), udll::compare);
|
upx_qsort(idlls, dllnum, sizeof(*idlls), UDll::compare);
|
||||||
|
|
||||||
info("Processing imports: %d DLLs", dllnum);
|
info("Processing imports: %d DLLs", dllnum);
|
||||||
for (unsigned ic = 0; ic < dllnum; ic++) {
|
for (unsigned ic = 0; ic < dllnum; ic++) {
|
||||||
|
@ -1081,7 +1082,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
||||||
ppi += 8;
|
ppi += 8;
|
||||||
for (; *tarr; tarr++)
|
for (; *tarr; tarr++)
|
||||||
if (*tarr & ord_mask) {
|
if (*tarr & ord_mask) {
|
||||||
unsigned ord = *tarr & 0xffff;
|
const unsigned ord = *tarr & 0xffff;
|
||||||
if (idlls[ic]->isk32 && kernel32ordinal) {
|
if (idlls[ic]->isk32 && kernel32ordinal) {
|
||||||
*ppi++ = 0xfe; // signed + odd parity
|
*ppi++ = 0xfe; // signed + odd parity
|
||||||
set_le32(ppi, ilinker->getAddress(idlls[ic]->name, ord));
|
set_le32(ppi, ilinker->getAddress(idlls[ic]->name, ord));
|
||||||
|
@ -1101,7 +1102,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
|
||||||
}
|
}
|
||||||
ppi++;
|
ppi++;
|
||||||
|
|
||||||
unsigned esize = ptr_udiff_bytes(tarr, idlls[ic]->lookupt);
|
const unsigned esize = ptr_udiff_bytes(tarr, idlls[ic]->lookupt);
|
||||||
lookups.add(idlls[ic]->lookupt, esize);
|
lookups.add(idlls[ic]->lookupt, esize);
|
||||||
if (ptr_diff_bytes(ibuf.subref("bad import name %#x", idlls[ic]->iat, 1),
|
if (ptr_diff_bytes(ibuf.subref("bad import name %#x", idlls[ic]->iat, 1),
|
||||||
idlls[ic]->lookupt) != 0) {
|
idlls[ic]->lookupt) != 0) {
|
||||||
|
@ -1311,13 +1312,13 @@ void PeFile::processExports(Export *xport, unsigned newoffs) // pass2
|
||||||
// of course it was impossible to debug this ;-)
|
// of course it was impossible to debug this ;-)
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct PeFile::tls_traits<LE32> {
|
struct PeFile::tls_traits<LE32> final {
|
||||||
struct alignas(1) tls {
|
struct alignas(1) tls {
|
||||||
LE32 datastart; // VA tls init data start
|
LE32 datastart; // VA tls init data start
|
||||||
LE32 dataend; // VA tls init data end
|
LE32 dataend; // VA tls init data end
|
||||||
LE32 tlsindex; // VA tls index
|
LE32 tlsindex; // VA tls index
|
||||||
LE32 callbacks; // VA tls callbacks
|
LE32 callbacks; // VA tls callbacks
|
||||||
char _[8]; // zero init, characteristics
|
byte _[8]; // zero init, characteristics
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned sotls = 24;
|
static const unsigned sotls = 24;
|
||||||
|
@ -1328,13 +1329,13 @@ struct PeFile::tls_traits<LE32> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct PeFile::tls_traits<LE64> {
|
struct PeFile::tls_traits<LE64> final {
|
||||||
struct alignas(1) tls {
|
struct alignas(1) tls {
|
||||||
LE64 datastart; // VA tls init data start
|
LE64 datastart; // VA tls init data start
|
||||||
LE64 dataend; // VA tls init data end
|
LE64 dataend; // VA tls init data end
|
||||||
LE64 tlsindex; // VA tls index
|
LE64 tlsindex; // VA tls index
|
||||||
LE64 callbacks; // VA tls callbacks
|
LE64 callbacks; // VA tls callbacks
|
||||||
char _[8]; // zero init, characteristics
|
byte _[8]; // zero init, characteristics
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned sotls = 40;
|
static const unsigned sotls = 40;
|
||||||
|
@ -1545,7 +1546,7 @@ struct alignas(1) PeFile::Resource::res_dir_entry {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(1) PeFile::Resource::res_dir {
|
struct alignas(1) PeFile::Resource::res_dir {
|
||||||
char _[12]; // flags, timedate, version
|
byte _[12]; // flags, timedate, version
|
||||||
LE16 namedentr;
|
LE16 namedentr;
|
||||||
LE16 identr;
|
LE16 identr;
|
||||||
|
|
||||||
|
@ -1558,7 +1559,7 @@ struct alignas(1) PeFile::Resource::res_dir {
|
||||||
struct alignas(1) PeFile::Resource::res_data {
|
struct alignas(1) PeFile::Resource::res_data {
|
||||||
LE32 offset;
|
LE32 offset;
|
||||||
LE32 size;
|
LE32 size;
|
||||||
char _[8]; // codepage, reserved
|
byte _[8]; // codepage, reserved
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PeFile::Resource::upx_rnode {
|
struct PeFile::Resource::upx_rnode {
|
||||||
|
@ -1856,11 +1857,10 @@ static bool match(unsigned itype, const byte *ntype, unsigned iname, const byte
|
||||||
// typex and namex can be string or number
|
// typex and namex can be string or number
|
||||||
// hopefully resource names do not have '/' or ',' characters inside
|
// hopefully resource names do not have '/' or ',' characters inside
|
||||||
|
|
||||||
struct helper {
|
struct Helper final {
|
||||||
static bool match(unsigned num, const byte *unistr, const char *mkeep) {
|
static bool match(unsigned num, const byte *unistr, const char *mkeep) {
|
||||||
if (!unistr)
|
if (!unistr)
|
||||||
return (unsigned) atoi(mkeep) == num;
|
return (unsigned) atoi(mkeep) == num;
|
||||||
|
|
||||||
unsigned ic;
|
unsigned ic;
|
||||||
for (ic = 0; ic < get_le16(unistr); ic++)
|
for (ic = 0; ic < get_le16(unistr); ic++)
|
||||||
if (unistr[2 + ic * 2] != (byte) mkeep[ic])
|
if (unistr[2 + ic * 2] != (byte) mkeep[ic])
|
||||||
|
@ -1871,17 +1871,16 @@ static bool match(unsigned itype, const byte *ntype, unsigned iname, const byte
|
||||||
|
|
||||||
// FIXME this comparison is not too exact
|
// FIXME this comparison is not too exact
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char const *delim1 = strchr(keep, '/');
|
const char *delim1 = strchr(keep, '/');
|
||||||
char const *delim2 = strchr(keep, ',');
|
const char *delim2 = strchr(keep, ',');
|
||||||
if (helper::match(itype, ntype, keep)) {
|
if (Helper::match(itype, ntype, keep)) {
|
||||||
if (!delim1)
|
if (!delim1)
|
||||||
return true;
|
return true;
|
||||||
if (delim2 && delim2 < delim1)
|
if (delim2 && delim2 < delim1)
|
||||||
return true;
|
return true;
|
||||||
if (helper::match(iname, nname, delim1 + 1))
|
if (Helper::match(iname, nname, delim1 + 1))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delim2 == nullptr)
|
if (delim2 == nullptr)
|
||||||
break;
|
break;
|
||||||
keep = delim2 + 1;
|
keep = delim2 + 1;
|
||||||
|
@ -1967,13 +1966,15 @@ void PeFile::processResources(Resource *res) {
|
||||||
else if (rtype > 0 && rtype < RT_LAST)
|
else if (rtype > 0 && rtype < RT_LAST)
|
||||||
do_compress = opt->win32_pe.compress_rt[rtype] ? true : false;
|
do_compress = opt->win32_pe.compress_rt[rtype] ? true : false;
|
||||||
|
|
||||||
if (keep_icons)
|
if (do_compress && keep_icons)
|
||||||
do_compress &=
|
do_compress &=
|
||||||
!match(res->itype(), res->ntype(), res->iname(), res->nname(), keep_icons);
|
!match(res->itype(), res->ntype(), res->iname(), res->nname(), keep_icons);
|
||||||
do_compress &=
|
if (do_compress)
|
||||||
!match(res->itype(), res->ntype(), res->iname(), res->nname(), "TYPELIB,REGISTRY,16");
|
do_compress &= !match(res->itype(), res->ntype(), res->iname(), res->nname(),
|
||||||
do_compress &= !match(res->itype(), res->ntype(), res->iname(), res->nname(),
|
"TYPELIB,REGISTRY,16");
|
||||||
opt->win32_pe.keep_resource);
|
if (do_compress)
|
||||||
|
do_compress &= !match(res->itype(), res->ntype(), res->iname(), res->nname(),
|
||||||
|
opt->win32_pe.keep_resource);
|
||||||
|
|
||||||
if (do_compress) {
|
if (do_compress) {
|
||||||
csize += res->size();
|
csize += res->size();
|
||||||
|
@ -2042,22 +2043,22 @@ unsigned PeFile::stripDebug(unsigned overlaystart) {
|
||||||
if (IDADDR(PEDIR_DEBUG) == 0)
|
if (IDADDR(PEDIR_DEBUG) == 0)
|
||||||
return overlaystart;
|
return overlaystart;
|
||||||
|
|
||||||
struct alignas(1) debug_dir_t {
|
struct alignas(1) DebugDir final {
|
||||||
char _[16]; // flags, time/date, version, type
|
byte _[16]; // flags, time/date, version, type
|
||||||
LE32 size;
|
LE32 size;
|
||||||
char __[4]; // rva
|
byte __[4]; // rva
|
||||||
LE32 fpos;
|
LE32 fpos;
|
||||||
};
|
};
|
||||||
|
|
||||||
COMPILE_TIME_ASSERT(sizeof(debug_dir_t) == 28)
|
COMPILE_TIME_ASSERT(sizeof(DebugDir) == 28)
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(debug_dir_t)
|
COMPILE_TIME_ASSERT_ALIGNED1(DebugDir)
|
||||||
COMPILE_TIME_ASSERT(sizeof(((debug_dir_t *) nullptr)->_) == 16)
|
COMPILE_TIME_ASSERT(sizeof(((DebugDir *) nullptr)->_) == 16)
|
||||||
COMPILE_TIME_ASSERT(sizeof(((debug_dir_t *) nullptr)->__) == 4)
|
COMPILE_TIME_ASSERT(sizeof(((DebugDir *) nullptr)->__) == 4)
|
||||||
|
|
||||||
const unsigned skip = IDADDR(PEDIR_DEBUG);
|
const unsigned skip = IDADDR(PEDIR_DEBUG);
|
||||||
const unsigned take = IDSIZE(PEDIR_DEBUG);
|
const unsigned take = IDSIZE(PEDIR_DEBUG);
|
||||||
const debug_dir_t *dd = (const debug_dir_t *) ibuf.subref("bad debug %#x", skip, take);
|
const DebugDir *dd = (const DebugDir *) ibuf.subref("bad debug %#x", skip, take);
|
||||||
for (unsigned ic = 0; ic < IDSIZE(PEDIR_DEBUG) / sizeof(debug_dir_t); ic++, dd++)
|
for (unsigned ic = 0; ic < IDSIZE(PEDIR_DEBUG) / sizeof(DebugDir); ic++, dd++)
|
||||||
if (overlaystart == dd->fpos)
|
if (overlaystart == dd->fpos)
|
||||||
overlaystart += dd->size;
|
overlaystart += dd->size;
|
||||||
ibuf.fill(IDADDR(PEDIR_DEBUG), IDSIZE(PEDIR_DEBUG), FILLVAL);
|
ibuf.fill(IDADDR(PEDIR_DEBUG), IDSIZE(PEDIR_DEBUG), FILLVAL);
|
||||||
|
@ -2770,7 +2771,7 @@ struct VPtr final { // "virtual pointer" pointing before a buffer
|
||||||
SPAN_S(T) base;
|
SPAN_S(T) base;
|
||||||
size_t x;
|
size_t x;
|
||||||
// return base + (n - x)
|
// return base + (n - x)
|
||||||
auto operator+(size_t n) const { return base + mem_size_get_n(sizeof(T), n - x); }
|
SPAN_S(T) operator+(size_t n) const { return base + mem_size_get_n(sizeof(T), n - x); }
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// UPX only uses the very basic Windows API
|
||||||
#if !defined(WIN32_LEAN_AND_MEAN)
|
#if !defined(WIN32_LEAN_AND_MEAN)
|
||||||
#define WIN32_LEAN_AND_MEAN 1
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(_WIN32_WINNT)
|
||||||
|
#define _WIN32_WINNT 0x0400 // _WIN32_WINNT_NT4 aka Windows NT 4
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1000 && _MSC_VER < 1200)) && !defined(__clang__)
|
#if (defined(_MSC_VER) && (_MSC_VER >= 1000 && _MSC_VER < 1200)) && !defined(__clang__)
|
||||||
/* avoid -W4 warnings in <conio.h> */
|
/* avoid -W4 warnings in <conio.h> */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user