all: assorted updates and cleanups
This commit is contained in:
parent
163377d1a0
commit
b8d9c2b755
@ -18,6 +18,8 @@ AttributeMacros:
|
||||
- __acc_noinline
|
||||
- __acc_static_noinline
|
||||
- __acc_static_forceinline
|
||||
- DELETED_FUNCTION
|
||||
- XSPAN_DELETED_FUNCTION
|
||||
- forceinline
|
||||
- noinline
|
||||
EmptyLineBeforeAccessModifier: Leave
|
||||
|
||||
26
.github/workflows/ci.yml
vendored
26
.github/workflows/ci.yml
vendored
@ -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
|
||||
|
||||
2
.github/workflows/close-stale-issues.yml
vendored
2
.github/workflows/close-stale-issues.yml
vendored
@ -13,7 +13,7 @@
|
||||
name: 'GitHub - Close inactive issues'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 6 * * 4'
|
||||
- cron: '10 4 * * 3'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
close-issues:
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -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:
|
||||
|
||||
2
.github/workflows/minimal-ci.yml
vendored
2
.github/workflows/minimal-ci.yml
vendored
@ -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']}}
|
||||
|
||||
2
.github/workflows/scan-build.yml
vendored
2
.github/workflows/scan-build.yml
vendored
@ -2,7 +2,7 @@ name: 'Static Analyzer - scan-build'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '40 1 * * 3'
|
||||
- cron: '40 4 * * 3'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
108
CMakeLists.txt
108
CMakeLists.txt
@ -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()
|
||||
|
||||
|
||||
8
Makefile
8
Makefile
@ -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)
|
||||
|
||||
@ -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 -*-
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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))
|
||||
|
||||
24
src/conf.h
24
src/conf.h
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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: */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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: */
|
||||
|
||||
@ -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() {
|
||||
|
||||
113
src/p_com.cpp
113
src/p_com.cpp
@ -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: */
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* p_exe.h --
|
||||
/* p_exe.h -- dos/exe executable format
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#define ALLOW_INT_PLUS_MEMBUFFER 1
|
||||
#include "conf.h"
|
||||
|
||||
#include "file.h"
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#define ALLOW_INT_PLUS_MEMBUFFER 1
|
||||
#include "conf.h"
|
||||
|
||||
#include "file.h"
|
||||
|
||||
@ -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: */
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#define ALLOW_INT_PLUS_MEMBUFFER 1
|
||||
#include "conf.h"
|
||||
|
||||
#include "p_elf.h"
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
class InputFile;
|
||||
class OutputFile;
|
||||
class Packer;
|
||||
class PackMaster;
|
||||
class UiPacker;
|
||||
class Filter;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
380
src/packer_f.cpp
380
src/packer_f.cpp
@ -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
|
||||
|
||||
@ -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));
|
||||
|
||||
17
src/ui.cpp
17
src/ui.cpp
@ -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();
|
||||
|
||||
|
||||
155
src/util/bptr.h
155
src/util/bptr.h
@ -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: */
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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: */
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
**************************************************************************/
|
||||
|
||||
@ -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
|
||||
**************************************************************************/
|
||||
|
||||
@ -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: */
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user