mirror of
https://github.com/upx/upx.git
synced 2024-11-26 22:20:52 +00:00
CI updates and minor cleanups
This commit is contained in:
parent
70b20d7d89
commit
24f3824524
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -3,6 +3,10 @@
|
|||||||
#
|
#
|
||||||
# HINT: check settings with
|
# HINT: check settings with
|
||||||
# git ls-files | git check-attr --stdin --all
|
# git ls-files | git check-attr --stdin --all
|
||||||
|
# git ls-files --eol
|
||||||
|
|
||||||
|
# disable all line ending conversions
|
||||||
|
* -text
|
||||||
|
|
||||||
#
|
#
|
||||||
# tell diff tools that these files are generated automatically
|
# tell diff tools that these files are generated automatically
|
||||||
|
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
@ -16,8 +16,9 @@ env:
|
|||||||
UPX_CMAKE_BUILD_FLAGS: --verbose
|
UPX_CMAKE_BUILD_FLAGS: --verbose
|
||||||
UPX_CMAKE_CONFIG_FLAGS: -Wdev --warn-uninitialized
|
UPX_CMAKE_CONFIG_FLAGS: -Wdev --warn-uninitialized
|
||||||
UPX_DEBUG_TEST_FLOAT_DIVISION_BY_ZERO: 1
|
UPX_DEBUG_TEST_FLOAT_DIVISION_BY_ZERO: 1
|
||||||
# 2024-03-29
|
UPX_DEBUG_TEST_LIBC_QSORT: 1
|
||||||
ZIG_DIST_VERSION: 0.12.0-dev.3484+7aa42f47b
|
# 2024-04-01
|
||||||
|
ZIG_DIST_VERSION: 0.12.0-dev.3508+a6ed3e6d2
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
job-rebuild-and-verify-stubs:
|
job-rebuild-and-verify-stubs:
|
||||||
@ -183,7 +184,7 @@ jobs:
|
|||||||
job-macos-cmake: # uses cmake + make
|
job-macos-cmake: # uses cmake + make
|
||||||
if: true
|
if: true
|
||||||
needs: [ job-rebuild-and-verify-stubs ]
|
needs: [ job-rebuild-and-verify-stubs ]
|
||||||
name: ${{ format('{0} {1}', matrix.os, matrix.xcode_version) }}
|
name: ${{ format('{0} {1}{2}', matrix.os, matrix.xcode_version && 'xcode-' || '', matrix.xcode_version) }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@ -193,8 +194,8 @@ jobs:
|
|||||||
# NOTE: macos-11 does not have "readlink -f"; only on macos >= 12 or with brew coreutils
|
# NOTE: macos-11 does not have "readlink -f"; only on macos >= 12 or with brew coreutils
|
||||||
- { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true }
|
- { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true }
|
||||||
- { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true }
|
- { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true }
|
||||||
- { os: macos-13, gcc: gcc-12, gxx: 'g++-12', testsuite: true, xcode_version: 14.3.1 }
|
|
||||||
- { os: macos-13, testsuite: true } # use default Xcode-15
|
- { os: macos-13, testsuite: true } # use default Xcode-15
|
||||||
|
- { os: macos-13, gcc: gcc-12, gxx: 'g++-12', testsuite: true, xcode_version: 14.3.1 }
|
||||||
# { os: macos-14, gcc: gcc-13, gxx: 'g++-13', testsuite: true } # gcc-13: INTERNAL ERROR in ld64
|
# { os: macos-14, gcc: gcc-13, gxx: 'g++-13', testsuite: true } # gcc-13: INTERNAL ERROR in ld64
|
||||||
# { os: macos-14, gcc: gcc-13, gxx: 'g++-13', testsuite: true, xcode_version: 14.3.1 } # gcc-13: MISSING HEADER FILES
|
# { os: macos-14, gcc: gcc-13, gxx: 'g++-13', testsuite: true, xcode_version: 14.3.1 } # gcc-13: MISSING HEADER FILES
|
||||||
- { os: macos-14, gcc: gcc-12, gxx: 'g++-12', testsuite: true } # => use gcc-12 for now
|
- { os: macos-14, gcc: gcc-12, gxx: 'g++-12', testsuite: true } # => use gcc-12 for now
|
||||||
@ -465,16 +466,18 @@ jobs:
|
|||||||
- { zig_target: aarch64-windows-gnu }
|
- { zig_target: aarch64-windows-gnu }
|
||||||
- { zig_target: arm-linux-musleabihf, qemu: qemu-arm }
|
- { zig_target: arm-linux-musleabihf, qemu: qemu-arm }
|
||||||
# { zig_target: arm-linux-musleabihf, qemu: qemu-arm, zig_pic: -fPIE }
|
# { zig_target: arm-linux-musleabihf, qemu: qemu-arm, zig_pic: -fPIE }
|
||||||
- { zig_target: i386-linux-musl, qemu: qemu-i386 }
|
- { zig_target: i386-linux-gnu.2.3.4, zig_flags: -march=i586 }
|
||||||
# { zig_target: i386-linux-musl, qemu: qemu-i386, zig_pic: -fPIE }
|
- { zig_target: i386-linux-musl, zig_flags: -march=i586, qemu: qemu-i386 }
|
||||||
|
# { zig_target: i386-linux-musl, zig_flags: -march=i586, qemu: qemu-i386, zig_pic: -fPIE }
|
||||||
- { zig_target: i386-windows-gnu }
|
- { zig_target: i386-windows-gnu }
|
||||||
# mips and mipsel: bad hard-float code generation(??); or QEMU bug; or UPX bug; see https://github.com/upx/upx/issues/788
|
# mips and mipsel: bad hard-float code generation(??); or QEMU bug; or UPX bug; see https://github.com/upx/upx/issues/788
|
||||||
- { zig_target: mips-linux-musl, zig_flags: -msoft-float, qemu: qemu-mips }
|
- { zig_target: mips-linux-musl, zig_flags: -msoft-float, qemu: qemu-mips }
|
||||||
- { zig_target: mipsel-linux-musl, zig_flags: -msoft-float, qemu: qemu-mipsel }
|
- { zig_target: mipsel-linux-musl, zig_flags: -msoft-float, qemu: qemu-mipsel }
|
||||||
- { zig_target: powerpc-linux-musl, qemu: qemu-ppc }
|
- { zig_target: powerpc-linux-musl, qemu: qemu-ppc }
|
||||||
# powerpc64: obscure problem with C++ exceptions in doctest checks when *NOT* using -fstack-protector
|
# powerpc64: obscure problem with C++ exceptions in UPX doctest checks when *NOT* using -fstack-protector
|
||||||
- { zig_target: powerpc64-linux-musl, zig_flags: -fstack-protector, qemu: qemu-ppc64 }
|
- { zig_target: powerpc64-linux-musl, zig_flags: -fstack-protector, qemu: qemu-ppc64 }
|
||||||
- { zig_target: powerpc64le-linux-musl, qemu: qemu-ppc64le }
|
- { zig_target: powerpc64le-linux-musl, qemu: qemu-ppc64le }
|
||||||
|
- { zig_target: x86_64-linux-gnu.2.3.4 }
|
||||||
- { zig_target: x86_64-linux-musl, qemu: qemu-x86_64 }
|
- { zig_target: x86_64-linux-musl, qemu: qemu-x86_64 }
|
||||||
# { zig_target: x86_64-linux-musl, qemu: qemu-x86_64, zig_pic: -fPIE }
|
# { zig_target: x86_64-linux-musl, qemu: qemu-x86_64, zig_pic: -fPIE }
|
||||||
# { zig_target: x86_64-macos-none }
|
# { zig_target: x86_64-macos-none }
|
||||||
|
@ -516,7 +516,7 @@ if(Threads_FOUND)
|
|||||||
elseif(UPX_CONFIG_REQUIRE_THREADS)
|
elseif(UPX_CONFIG_REQUIRE_THREADS)
|
||||||
message(FATAL_ERROR "ERROR: WITH_THREADS required")
|
message(FATAL_ERROR "ERROR: WITH_THREADS required")
|
||||||
elseif(UPX_CONFIG_EXPECT_THREADS AND NOT UPX_CONFIG_DISABLE_THREADS)
|
elseif(UPX_CONFIG_EXPECT_THREADS AND NOT UPX_CONFIG_DISABLE_THREADS)
|
||||||
message(FATAL_ERROR "ERROR: WITH_THREADS expected")
|
message(FATAL_ERROR "ERROR: WITH_THREADS expected; set UPX_CONFIG_EXPECT_THREADS=OFF to disable")
|
||||||
endif()
|
endif()
|
||||||
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|None|Release)$")
|
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|None|Release)$")
|
||||||
message(WARNING "WARNING: unsupported CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}; please use \"Debug\" or \"Release\"")
|
message(WARNING "WARNING: unsupported CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}; please use \"Debug\" or \"Release\"")
|
||||||
|
@ -236,8 +236,8 @@ build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/c
|
|||||||
build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-zstd/$$(notdir $$@)
|
build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-zstd/$$(notdir $$@)
|
||||||
|
|
||||||
# OLD names [deprecated]
|
# OLD names [deprecated]
|
||||||
build/extra/scan-build/debug: build/analyze/clang-analyzer/debug
|
build/extra/scan-build/debug: build/analyze/clang-analyzer/debug PHONY
|
||||||
build/extra/scan-build/release: build/analyze/clang-analyzer/release
|
build/extra/scan-build/release: build/analyze/clang-analyzer/release PHONY
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# advanced: generic eXtra target
|
# advanced: generic eXtra target
|
||||||
|
@ -33,10 +33,6 @@ debug+test release+test all+test: PHONY; $(MAKE) -C $(top_srcd
|
|||||||
|
|
||||||
test:: build/all+test PHONY
|
test:: build/all+test PHONY
|
||||||
|
|
||||||
# OLD target names [deprecated]
|
|
||||||
$(top_srcdir)/build/debug: build/debug PHONY
|
|
||||||
$(top_srcdir)/build/release: build/release PHONY
|
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# make run-testsuite
|
# make run-testsuite
|
||||||
# git clone https://github.com/upx/upx-testsuite.git
|
# git clone https://github.com/upx/upx-testsuite.git
|
||||||
|
40
src/bele.h
40
src/bele.h
@ -785,6 +785,26 @@ inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN(unsigned(a),
|
|||||||
// misc support
|
// misc support
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
// for use with qsort()
|
||||||
|
extern "C" {
|
||||||
|
int __acc_cdecl_qsort be16_compare(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort be24_compare(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort be32_compare(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort be64_compare(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort le16_compare(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort le24_compare(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort le32_compare(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort le64_compare(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort be16_compare_signed(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort be24_compare_signed(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort be32_compare_signed(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort be64_compare_signed(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort le16_compare_signed(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort le24_compare_signed(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort le32_compare_signed(const void *, const void *);
|
||||||
|
int __acc_cdecl_qsort le64_compare_signed(const void *, const void *);
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
// <type_traits> upx_is_integral; see conf.h
|
// <type_traits> upx_is_integral; see conf.h
|
||||||
#define TT_UPX_IS_INTEGRAL(T) \
|
#define TT_UPX_IS_INTEGRAL(T) \
|
||||||
template <> \
|
template <> \
|
||||||
@ -826,26 +846,6 @@ typedef LE64 NE64;
|
|||||||
#define ne64_compare_signed le64_compare_signed
|
#define ne64_compare_signed le64_compare_signed
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// for use with qsort()
|
|
||||||
extern "C" {
|
|
||||||
int __acc_cdecl_qsort be16_compare(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort be24_compare(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort be32_compare(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort be64_compare(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort le16_compare(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort le24_compare(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort le32_compare(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort le64_compare(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort be16_compare_signed(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort be24_compare_signed(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort be32_compare_signed(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort be64_compare_signed(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort le16_compare_signed(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort le24_compare_signed(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort le32_compare_signed(const void *, const void *);
|
|
||||||
int __acc_cdecl_qsort le64_compare_signed(const void *, const void *);
|
|
||||||
} // extern "C"
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// Provide namespaces and classes to abstract endianness policies.
|
// Provide namespaces and classes to abstract endianness policies.
|
||||||
//
|
//
|
||||||
|
@ -92,9 +92,9 @@ private:
|
|||||||
#define C const noexcept override
|
#define C const noexcept override
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct BEPolicy
|
struct BEPolicy final
|
||||||
#if defined(BELE_RTP)
|
#if defined(BELE_RTP)
|
||||||
final : public AbstractPolicy
|
: public AbstractPolicy
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
explicit inline BEPolicy() noexcept {}
|
explicit inline BEPolicy() noexcept {}
|
||||||
@ -151,9 +151,9 @@ private:
|
|||||||
UPX_CXX_DISABLE_NEW_DELETE(BEPolicy)
|
UPX_CXX_DISABLE_NEW_DELETE(BEPolicy)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LEPolicy
|
struct LEPolicy final
|
||||||
#if defined(BELE_RTP)
|
#if defined(BELE_RTP)
|
||||||
final : public AbstractPolicy
|
: public AbstractPolicy
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
explicit inline LEPolicy() noexcept {}
|
explicit inline LEPolicy() noexcept {}
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
<markus@oberhumer.com>
|
<markus@oberhumer.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// doctest checks, and various tests to catch toolchain/qemu/sanitizer/valgrind/wine/etc
|
||||||
|
// problems; grown historically
|
||||||
|
|
||||||
#include "../util/system_headers.h"
|
#include "../util/system_headers.h"
|
||||||
#include <cmath> // std::isinf std::isnan
|
#include <cmath> // std::isinf std::isnan
|
||||||
#include "../conf.h"
|
#include "../conf.h"
|
||||||
@ -376,6 +379,7 @@ struct TestFloat {
|
|||||||
static noinline Float add_div_x(Int a, Int b) { return Float(a + b) / Float(X); }
|
static noinline Float add_div_x(Int a, Int b) { return Float(a + b) / Float(X); }
|
||||||
static noinline Float sub_div_x(Int a, Int b) { return Float(a - b) / Float(X); }
|
static noinline Float sub_div_x(Int a, Int b) { return Float(a - b) / Float(X); }
|
||||||
static noinline void check() noexcept {
|
static noinline void check() noexcept {
|
||||||
|
assert_noexcept(div(2 * X, Float(X)) == Float(2));
|
||||||
assert_noexcept(add_div(X, X, Float(X)) == Float(2));
|
assert_noexcept(add_div(X, X, Float(X)) == Float(2));
|
||||||
assert_noexcept(add_div_x(X, X) == Float(2));
|
assert_noexcept(add_div_x(X, X) == Float(2));
|
||||||
assert_noexcept(sub_div(3 * X, X, Float(X)) == Float(2));
|
assert_noexcept(sub_div(3 * X, X, Float(X)) == Float(2));
|
||||||
@ -391,6 +395,7 @@ struct TestFloat {
|
|||||||
#else
|
#else
|
||||||
assert_noexcept(std::isnan(div(0, Float(0))));
|
assert_noexcept(std::isnan(div(0, Float(0))));
|
||||||
assert_noexcept(std::isinf(div(1, Float(0))));
|
assert_noexcept(std::isinf(div(1, Float(0))));
|
||||||
|
assert_noexcept(std::isinf(div(Int(-1), Float(0))));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,6 +437,19 @@ void upx_compiler_sanity_check(void) noexcept {
|
|||||||
|
|
||||||
check_basic_floating_point();
|
check_basic_floating_point();
|
||||||
|
|
||||||
|
// check_basic_decltype()
|
||||||
|
{
|
||||||
|
auto a = +0;
|
||||||
|
constexpr auto b = -0;
|
||||||
|
const auto &c = -1;
|
||||||
|
COMPILE_TIME_ASSERT((std::is_same<int, decltype(a)>::value))
|
||||||
|
COMPILE_TIME_ASSERT((std::is_same<const int, decltype(b)>::value))
|
||||||
|
COMPILE_TIME_ASSERT((std::is_same<const int &, decltype(c)>::value))
|
||||||
|
UNUSED(a);
|
||||||
|
UNUSED(b);
|
||||||
|
UNUSED(c);
|
||||||
|
}
|
||||||
|
|
||||||
#define ACC_WANT_ACC_CHK_CH 1
|
#define ACC_WANT_ACC_CHK_CH 1
|
||||||
#undef ACCCHK_ASSERT
|
#undef ACCCHK_ASSERT
|
||||||
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
|
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
|
||||||
@ -646,7 +664,7 @@ void upx_compiler_sanity_check(void) noexcept {
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
TEST_CASE("assert_noexcept") {
|
TEST_CASE("assert_noexcept") {
|
||||||
// just to make sure that our own assert() macros don't generate any warnings
|
// just to make sure that our own assert() macros do not trigger any compiler warnings
|
||||||
byte dummy = 0;
|
byte dummy = 0;
|
||||||
byte *ptr1 = &dummy;
|
byte *ptr1 = &dummy;
|
||||||
const byte *const ptr2 = &dummy;
|
const byte *const ptr2 = &dummy;
|
||||||
@ -668,10 +686,13 @@ TEST_CASE("acc_vget") {
|
|||||||
CHECK_EQ(acc_vget_long(1, -1), 1);
|
CHECK_EQ(acc_vget_long(1, -1), 1);
|
||||||
CHECK_EQ(acc_vget_acc_int64l_t(2, 1), 2);
|
CHECK_EQ(acc_vget_acc_int64l_t(2, 1), 2);
|
||||||
CHECK_EQ(acc_vget_acc_hvoid_p(nullptr, 0), nullptr);
|
CHECK_EQ(acc_vget_acc_hvoid_p(nullptr, 0), nullptr);
|
||||||
|
if (acc_vget_int(1, 0) > 0)
|
||||||
|
return;
|
||||||
|
assert_noexcept(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ptr_invalidate_and_poison") {
|
TEST_CASE("ptr_invalidate_and_poison") {
|
||||||
int *ip = nullptr;
|
int *ip = nullptr; // initialized
|
||||||
ptr_invalidate_and_poison(ip);
|
ptr_invalidate_and_poison(ip);
|
||||||
assert(ip != nullptr);
|
assert(ip != nullptr);
|
||||||
(void) ip;
|
(void) ip;
|
||||||
@ -751,11 +772,13 @@ TEST_CASE("libc snprintf") {
|
|||||||
CHECK_EQ(strcmp(buf, "0X1A 0x1b 0x1c "), 0);
|
CHECK_EQ(strcmp(buf, "0X1A 0x1b 0x1c "), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
TEST_CASE("libc qsort") {
|
TEST_CASE("libc qsort") {
|
||||||
// runtime check that libc qsort() never compares identical objects
|
// runtime check that libc qsort() never compares identical objects
|
||||||
// UPDATE: while only poor implementations of qsort() would actually do
|
// UPDATE: while only poor implementations of qsort() would actually do this
|
||||||
// this, it is probably allowed by the standard; so skip this test case
|
// it is probably allowed by the standard, so skip this test by default
|
||||||
|
if (!is_envvar_true("UPX_DEBUG_TEST_LIBC_QSORT"))
|
||||||
|
return;
|
||||||
|
|
||||||
struct Elem {
|
struct Elem {
|
||||||
upx_uint16_t id;
|
upx_uint16_t id;
|
||||||
upx_uint16_t value;
|
upx_uint16_t value;
|
||||||
@ -765,8 +788,8 @@ TEST_CASE("libc qsort") {
|
|||||||
assert_noexcept(a->id != b->id); // check not IDENTICAL
|
assert_noexcept(a->id != b->id); // check not IDENTICAL
|
||||||
return a->value < b->value ? -1 : (a->value == b->value ? 0 : 1);
|
return a->value < b->value ? -1 : (a->value == b->value ? 0 : 1);
|
||||||
}
|
}
|
||||||
static bool check_sort(upx_sort_func_t sort, Elem *e, size_t n) {
|
static noinline bool check_sort(upx_sort_func_t sort, Elem *e, size_t n) {
|
||||||
upx_uint32_t x = 5381 + n + ((upx_uintptr_t) e & 0xff);
|
upx_uint32_t x = 5381 + n + (upx_rand() & 0xff);
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
e[i].id = (upx_uint16_t) i;
|
e[i].id = (upx_uint16_t) i;
|
||||||
x = x * 33 + 1 + (i & 255);
|
x = x * 33 + 1 + (i & 255);
|
||||||
@ -782,18 +805,19 @@ TEST_CASE("libc qsort") {
|
|||||||
constexpr size_t N = 4096;
|
constexpr size_t N = 4096;
|
||||||
Elem e[N];
|
Elem e[N];
|
||||||
for (size_t n = 0; n <= N; n = 2 * n + 1) {
|
for (size_t n = 0; n <= N; n = 2 * n + 1) {
|
||||||
// CHECK(Elem::check_sort(qsort, e, n)); // libc qsort()
|
// system sort functions
|
||||||
CHECK(Elem::check_sort(upx_gnomesort, e, n));
|
CHECK(Elem::check_sort(::qsort, e, n)); // libc qsort()
|
||||||
CHECK(Elem::check_sort(upx_shellsort_memswap, e, n));
|
|
||||||
CHECK(Elem::check_sort(upx_shellsort_memcpy, e, n));
|
|
||||||
#if UPX_CONFIG_USE_STABLE_SORT
|
#if UPX_CONFIG_USE_STABLE_SORT
|
||||||
upx_sort_func_t wrap_stable_sort = [](void *aa, size_t nn, size_t, upx_compare_func_t cc) {
|
upx_sort_func_t wrap_stable_sort = [](void *aa, size_t nn, size_t, upx_compare_func_t cc) {
|
||||||
upx_std_stable_sort<sizeof(Elem)>(aa, nn, cc);
|
upx_std_stable_sort<sizeof(Elem)>(aa, nn, cc);
|
||||||
};
|
};
|
||||||
CHECK(Elem::check_sort(wrap_stable_sort, e, n));
|
CHECK(Elem::check_sort(wrap_stable_sort, e, n)); // std::stable_sort()
|
||||||
#endif
|
#endif
|
||||||
|
// UPX sort functions
|
||||||
|
CHECK(Elem::check_sort(upx_gnomesort, e, n));
|
||||||
|
CHECK(Elem::check_sort(upx_shellsort_memswap, e, n));
|
||||||
|
CHECK(Elem::check_sort(upx_shellsort_memcpy, e, n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
@ -27,24 +27,8 @@
|
|||||||
// lots of tests (and probably quite a number of redundant tests)
|
// lots of tests (and probably quite a number of redundant tests)
|
||||||
// modern compilers will optimize away much of this code
|
// modern compilers will optimize away much of this code
|
||||||
|
|
||||||
#if 0 // TODO later
|
|
||||||
// libc++ hardenining
|
|
||||||
#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ + 0 >= 18)
|
|
||||||
#if DEBUG
|
|
||||||
#define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEBUG
|
|
||||||
#else
|
|
||||||
#define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_EXTENSIVE
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ + 0 < 18)
|
|
||||||
#if DEBUG
|
|
||||||
#define _LIBCPP_ENABLE_ASSERTIONS 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif // TODO later
|
|
||||||
|
|
||||||
#include "../util/system_headers.h"
|
#include "../util/system_headers.h"
|
||||||
#include <vector>
|
#include <vector> // std::vector
|
||||||
#include "../conf.h"
|
#include "../conf.h"
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -125,7 +109,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz"))
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
TEST_CASE("libc++") {
|
TEST_CASE("std::vector") {
|
||||||
constexpr size_t N = 16;
|
constexpr size_t N = 16;
|
||||||
std::vector<int> v(N);
|
std::vector<int> v(N);
|
||||||
CHECK(v.end() - v.begin() == N);
|
CHECK(v.end() - v.begin() == N);
|
||||||
@ -298,7 +282,7 @@ TEST_CASE("upx::ObjectDeleter 2") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("upx::ptr_static_cast") {
|
TEST_CASE("upx::ptr_static_cast") {
|
||||||
// check that we don't trigger any -Wcast-align warnings
|
// check that we do not trigger any -Wcast-align warnings
|
||||||
using upx::ptr_static_cast;
|
using upx::ptr_static_cast;
|
||||||
void *vp = nullptr;
|
void *vp = nullptr;
|
||||||
byte *bp = nullptr;
|
byte *bp = nullptr;
|
||||||
|
11
src/conf.h
11
src/conf.h
@ -162,7 +162,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(upx_charptr_unit_type) == 1)
|
|||||||
typedef upx_int64_t upx_off_t;
|
typedef upx_int64_t upx_off_t;
|
||||||
#undef off_t
|
#undef off_t
|
||||||
#if 0
|
#if 0
|
||||||
// TODO cleanup: at some future point we can do this:
|
// TODO later cleanup: at some future point we can do this:
|
||||||
#define off_t DO_NOT_USE_off_t
|
#define off_t DO_NOT_USE_off_t
|
||||||
#else
|
#else
|
||||||
#define off_t upx_off_t
|
#define off_t upx_off_t
|
||||||
@ -230,12 +230,6 @@ typedef upx_int64_t upx_off_t;
|
|||||||
#undef sopen
|
#undef sopen
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_DUP) && (HAVE_DUP + 0 == 0)
|
|
||||||
// TODO later: add upx_fd_dup() util
|
|
||||||
#undef dup
|
|
||||||
#define dup(x) (-1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef STDIN_FILENO
|
#ifndef STDIN_FILENO
|
||||||
#define STDIN_FILENO (fileno(stdin))
|
#define STDIN_FILENO (fileno(stdin))
|
||||||
#endif
|
#endif
|
||||||
@ -338,7 +332,7 @@ typedef upx_int64_t upx_off_t;
|
|||||||
// TODO later: check __MINGW_PRINTF_FORMAT
|
// TODO later: check __MINGW_PRINTF_FORMAT
|
||||||
#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
|
#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
|
||||||
#define attribute_format(a, b) __attribute__((__format__(__gnu_printf__, a, b)))
|
#define attribute_format(a, b) __attribute__((__format__(__gnu_printf__, a, b)))
|
||||||
#elif (ACC_CC_CLANG || ACC_CC_GNUC)
|
#elif defined(__clang__) || defined(__GNUC__)
|
||||||
#define attribute_format(a, b) __attribute__((__format__(__printf__, a, b)))
|
#define attribute_format(a, b) __attribute__((__format__(__printf__, a, b)))
|
||||||
#else
|
#else
|
||||||
#define attribute_format(a, b) /*empty*/
|
#define attribute_format(a, b) /*empty*/
|
||||||
@ -442,6 +436,7 @@ inline void mem_clear(T *object) noexcept {
|
|||||||
static_assert(size >= 1 && size <= UPX_RSIZE_MAX_MEM);
|
static_assert(size >= 1 && size <= UPX_RSIZE_MAX_MEM);
|
||||||
memset((void *) object, 0, size);
|
memset((void *) object, 0, size);
|
||||||
}
|
}
|
||||||
|
// disable some overloads
|
||||||
#if defined(__clang__) || __GNUC__ != 7
|
#if defined(__clang__) || __GNUC__ != 7
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void mem_clear(T (&array)[]) noexcept DELETED_FUNCTION;
|
inline void mem_clear(T (&array)[]) noexcept DELETED_FUNCTION;
|
||||||
|
@ -203,7 +203,7 @@ const char *prettyName(const char *n) noexcept {
|
|||||||
n++;
|
n++;
|
||||||
else if (*n == ' ')
|
else if (*n == ' ')
|
||||||
n++;
|
n++;
|
||||||
else if (strncmp(n, "class ", 6) == 0) // Visual C++ (msvc)
|
else if (strncmp(n, "class ", 6) == 0) // Visual C++ (MSVC)
|
||||||
n += 6;
|
n += 6;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
19
src/file.cpp
19
src/file.cpp
@ -40,6 +40,7 @@
|
|||||||
#else
|
#else
|
||||||
UNUSED(name);
|
UNUSED(name);
|
||||||
UNUSED(mode);
|
UNUSED(mode);
|
||||||
|
// no error
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,7 @@ bool FileBase::do_sopen() {
|
|||||||
else {
|
else {
|
||||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||||
_fd = ::open(_name, _flags | _shflags, _mode);
|
_fd = ::open(_name, _flags | _shflags, _mode);
|
||||||
#elif defined(__MINT__)
|
#elif (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
|
||||||
_fd = ::open(_name, _flags | (_shflags & O_SHMODE), _mode);
|
_fd = ::open(_name, _flags | (_shflags & O_SHMODE), _mode);
|
||||||
#elif defined(SH_DENYRW)
|
#elif defined(SH_DENYRW)
|
||||||
_fd = ::sopen(_name, _flags, _shflags, _mode);
|
_fd = ::sopen(_name, _flags, _shflags, _mode);
|
||||||
@ -98,6 +99,7 @@ bool FileBase::do_sopen() {
|
|||||||
}
|
}
|
||||||
if (_fd < 0)
|
if (_fd < 0)
|
||||||
return false;
|
return false;
|
||||||
|
st.st_size = 0;
|
||||||
if (::fstat(_fd, &st) != 0)
|
if (::fstat(_fd, &st) != 0)
|
||||||
throwIOException(_name, errno);
|
throwIOException(_name, errno);
|
||||||
_length = st.st_size;
|
_length = st.st_size;
|
||||||
@ -212,6 +214,20 @@ upx_off_t InputFile::seek(upx_off_t off, int whence) {
|
|||||||
|
|
||||||
upx_off_t InputFile::st_size_orig() const { return _length_orig; }
|
upx_off_t InputFile::st_size_orig() const { return _length_orig; }
|
||||||
|
|
||||||
|
int InputFile::dup() may_throw {
|
||||||
|
if (!isOpen())
|
||||||
|
throwIOException("bad dup");
|
||||||
|
#if defined(HAVE_DUP) && (HAVE_DUP + 0 == 0)
|
||||||
|
errno = ENOSYS;
|
||||||
|
int r = -1;
|
||||||
|
#else
|
||||||
|
int r = ::dup(getFd());
|
||||||
|
#endif
|
||||||
|
if (r < 0)
|
||||||
|
throwIOException("dup", errno);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// OutputFile
|
// OutputFile
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@ -333,6 +349,7 @@ void OutputFile::set_extent(upx_off_t offset, upx_off_t length) {
|
|||||||
super::set_extent(offset, length);
|
super::set_extent(offset, length);
|
||||||
bytes_written = 0;
|
bytes_written = 0;
|
||||||
if (0 == offset && 0xffffffffLL == length) { // TODO: check all callers of this method
|
if (0 == offset && 0xffffffffLL == length) { // TODO: check all callers of this method
|
||||||
|
st.st_size = 0;
|
||||||
if (::fstat(_fd, &st) != 0)
|
if (::fstat(_fd, &st) != 0)
|
||||||
throwIOException(_name, errno);
|
throwIOException(_name, errno);
|
||||||
_length = st.st_size - offset;
|
_length = st.st_size - offset;
|
||||||
|
@ -88,6 +88,8 @@ public:
|
|||||||
virtual upx_off_t seek(upx_off_t off, int whence) override;
|
virtual upx_off_t seek(upx_off_t off, int whence) override;
|
||||||
upx_off_t st_size_orig() const;
|
upx_off_t st_size_orig() const;
|
||||||
|
|
||||||
|
noinline int dup() may_throw;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
upx_off_t _length_orig = 0;
|
upx_off_t _length_orig = 0;
|
||||||
};
|
};
|
||||||
|
@ -60,7 +60,7 @@ ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a
|
|||||||
: name(nullptr), output(nullptr), size(s), offset(0), p2align(a), next(nullptr) {
|
: name(nullptr), output(nullptr), size(s), offset(0), p2align(a), next(nullptr) {
|
||||||
name = strdup(n);
|
name = strdup(n);
|
||||||
assert(name != nullptr);
|
assert(name != nullptr);
|
||||||
input = malloc(s + 1);
|
input = ::malloc(s + 1);
|
||||||
assert(input != nullptr);
|
assert(input != nullptr);
|
||||||
if (s != 0) {
|
if (s != 0) {
|
||||||
assert(i != nullptr);
|
assert(i != nullptr);
|
||||||
@ -70,8 +70,8 @@ ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a
|
|||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::Section::~Section() noexcept {
|
ElfLinker::Section::~Section() noexcept {
|
||||||
free(name);
|
::free(name);
|
||||||
free(input);
|
::free(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -85,7 +85,7 @@ ElfLinker::Symbol::Symbol(const char *n, Section *s, upx_uint64_t o)
|
|||||||
assert(section != nullptr);
|
assert(section != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::Symbol::~Symbol() noexcept { free(name); }
|
ElfLinker::Symbol::~Symbol() noexcept { ::free(name); }
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// Relocation
|
// Relocation
|
||||||
@ -110,13 +110,13 @@ ElfLinker::~ElfLinker() noexcept {
|
|||||||
unsigned ic;
|
unsigned ic;
|
||||||
for (ic = 0; ic < nsections; ic++)
|
for (ic = 0; ic < nsections; ic++)
|
||||||
delete sections[ic];
|
delete sections[ic];
|
||||||
free(sections);
|
::free(sections);
|
||||||
for (ic = 0; ic < nsymbols; ic++)
|
for (ic = 0; ic < nsymbols; ic++)
|
||||||
delete symbols[ic];
|
delete symbols[ic];
|
||||||
free(symbols);
|
::free(symbols);
|
||||||
for (ic = 0; ic < nrelocations; ic++)
|
for (ic = 0; ic < nrelocations; ic++)
|
||||||
delete relocations[ic];
|
delete relocations[ic];
|
||||||
free(relocations);
|
::free(relocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfLinker::init(const void *pdata_v, int plen, unsigned pxtra) {
|
void ElfLinker::init(const void *pdata_v, int plen, unsigned pxtra) {
|
||||||
@ -425,7 +425,7 @@ int ElfLinker::addLoader(const char *sname) {
|
|||||||
}
|
}
|
||||||
sect += strlen(sect) + 1;
|
sect += strlen(sect) + 1;
|
||||||
}
|
}
|
||||||
free(begin);
|
::free(begin);
|
||||||
return outputlen;
|
return outputlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,7 +923,7 @@ int main_get_options(int argc, char **argv) {
|
|||||||
// atari/tos
|
// atari/tos
|
||||||
{"split-segments", 0x90, N, 650},
|
{"split-segments", 0x90, N, 650},
|
||||||
// darwin/macho
|
// darwin/macho
|
||||||
{"force-macos", 0x90, N, 690}, // undocumented temporary until we fix macOS 13+
|
{"force-macos", 0x90, N, 690}, // undocumented temporary option until we do fix macOS 13+
|
||||||
// djgpp2/coff
|
// djgpp2/coff
|
||||||
{"coff", 0x90, N, 610}, // produce COFF output
|
{"coff", 0x90, N, 610}, // produce COFF output
|
||||||
// dos/exe
|
// dos/exe
|
||||||
@ -1355,9 +1355,9 @@ int __acc_cdecl_main main(int argc, char *argv[]) /*noexcept*/ {
|
|||||||
#endif
|
#endif
|
||||||
acc_wildargv(&argc, &argv);
|
acc_wildargv(&argc, &argv);
|
||||||
#if defined(__wasi__)
|
#if defined(__wasi__)
|
||||||
srand((int) time(nullptr));
|
::srand((unsigned) time(nullptr));
|
||||||
#else
|
#else
|
||||||
srand((int) clock());
|
::srand((unsigned) clock());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// info: main() is implicitly "noexcept", so we need a try block
|
// info: main() is implicitly "noexcept", so we need a try block
|
||||||
|
@ -28,9 +28,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct Options;
|
struct Options;
|
||||||
extern Options *opt; // global options, see class PackMaster for per-file local options
|
|
||||||
#define options_t Options // old name
|
#define options_t Options // old name
|
||||||
|
|
||||||
|
extern Options *opt; // global options, see class PackMaster for per-file local options
|
||||||
|
|
||||||
#if WITH_THREADS
|
#if WITH_THREADS
|
||||||
extern std::mutex opt_lock_mutex;
|
extern std::mutex opt_lock_mutex;
|
||||||
#endif
|
#endif
|
||||||
@ -177,6 +178,9 @@ struct Options final {
|
|||||||
int strip_relocs;
|
int strip_relocs;
|
||||||
const char *keep_resource;
|
const char *keep_resource;
|
||||||
} win32_pe;
|
} win32_pe;
|
||||||
|
|
||||||
|
private: // UPX conventions
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE(Options)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
@ -267,7 +267,7 @@ int PackVmlinuzI386::decompressKernel()
|
|||||||
fd_pos = -1;
|
fd_pos = -1;
|
||||||
// open
|
// open
|
||||||
fi->seek(gzoff, SEEK_SET);
|
fi->seek(gzoff, SEEK_SET);
|
||||||
fd = dup(fi->getFd());
|
fd = fi->dup();
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
break;
|
break;
|
||||||
gzFile zf = gzdopen(fd, "rb");
|
gzFile zf = gzdopen(fd, "rb");
|
||||||
@ -849,7 +849,7 @@ int PackVmlinuzARMEL::decompressKernel()
|
|||||||
fd_pos = -1;
|
fd_pos = -1;
|
||||||
// open
|
// open
|
||||||
fi->seek(gzoff, SEEK_SET);
|
fi->seek(gzoff, SEEK_SET);
|
||||||
fd = dup(fi->getFd());
|
fd = fi->dup();
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
break;
|
break;
|
||||||
gzFile zf = gzdopen(fd, "rb");
|
gzFile zf = gzdopen(fd, "rb");
|
||||||
|
@ -743,6 +743,7 @@ tribool PackWcle::canUnpack() {
|
|||||||
return readPackHeader(len) ? 1 : -1;
|
return readPackHeader(len) ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*static*/
|
||||||
void PackWcle::virt2rela(const le_object_table_entry_t *entr, unsigned *objn, unsigned *addr) {
|
void PackWcle::virt2rela(const le_object_table_entry_t *entr, unsigned *objn, unsigned *addr) {
|
||||||
for (; *objn > 1; objn[0]--) {
|
for (; *objn > 1; objn[0]--) {
|
||||||
if (entr[*objn - 1].my_base_address > *addr)
|
if (entr[*objn - 1].my_base_address > *addr)
|
||||||
|
@ -495,7 +495,7 @@ unsigned Packer::getRandomId() const {
|
|||||||
#endif
|
#endif
|
||||||
id ^= (unsigned) fi->st.st_ino;
|
id ^= (unsigned) fi->st.st_ino;
|
||||||
id ^= (unsigned) fi->st.st_atime;
|
id ^= (unsigned) fi->st.st_atime;
|
||||||
id ^= (unsigned) rand();
|
id ^= (unsigned) upx_rand();
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -947,7 +947,7 @@ int Packer::prepareMethods(int *methods, int ph_method, const int *all_methods)
|
|||||||
}
|
}
|
||||||
// debug
|
// debug
|
||||||
if (opt->debug.use_random_method && nmethods >= 2) {
|
if (opt->debug.use_random_method && nmethods >= 2) {
|
||||||
int method = methods[rand() % nmethods];
|
int method = methods[upx_rand() % nmethods];
|
||||||
methods[0] = method;
|
methods[0] = method;
|
||||||
nmethods = 1;
|
nmethods = 1;
|
||||||
NO_printf("\nuse_random_method = %d\n", method);
|
NO_printf("\nuse_random_method = %d\n", method);
|
||||||
@ -1015,7 +1015,7 @@ done:
|
|||||||
filters[nfilters++] = 0;
|
filters[nfilters++] = 0;
|
||||||
// debug
|
// debug
|
||||||
if (opt->debug.use_random_filter && nfilters >= 3 && filters[nfilters - 1] == 0) {
|
if (opt->debug.use_random_filter && nfilters >= 3 && filters[nfilters - 1] == 0) {
|
||||||
int filter_id = filters[rand() % (nfilters - 1)];
|
int filter_id = filters[upx_rand() % (nfilters - 1)];
|
||||||
if (filter_id > 0) {
|
if (filter_id > 0) {
|
||||||
filters[0] = filter_id;
|
filters[0] = filter_id;
|
||||||
filters[1] = 0;
|
filters[1] = 0;
|
||||||
|
@ -84,10 +84,14 @@ struct PackHeader final {
|
|||||||
|
|
||||||
// info fields set by Packer::compressWithFilters()
|
// info fields set by Packer::compressWithFilters()
|
||||||
unsigned overlap_overhead;
|
unsigned overlap_overhead;
|
||||||
|
|
||||||
|
private: // UPX conventions
|
||||||
|
UPX_CXX_DISABLE_ADDRESS(PackHeader)
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE(PackHeader)
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// ph default util functions
|
// PackHeader ph util functions
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
bool ph_is_forced_method(int method) noexcept; // predicate
|
bool ph_is_forced_method(int method) noexcept; // predicate
|
||||||
|
@ -59,6 +59,11 @@ private:
|
|||||||
// setup local options for each file
|
// setup local options for each file
|
||||||
Options local_options;
|
Options local_options;
|
||||||
Options *saved_opt = nullptr;
|
Options *saved_opt = nullptr;
|
||||||
|
|
||||||
|
private: // UPX conventions
|
||||||
|
UPX_CXX_DISABLE_ADDRESS(PackMaster)
|
||||||
|
UPX_CXX_DISABLE_COPY_MOVE(PackMaster)
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE(PackMaster)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
@ -215,7 +215,7 @@ int PeFile::readFileHeader() {
|
|||||||
|
|
||||||
PeFile::Interval::Interval(SPAN_P(byte) b) : base(b) {}
|
PeFile::Interval::Interval(SPAN_P(byte) b) : base(b) {}
|
||||||
|
|
||||||
PeFile::Interval::~Interval() noexcept { free(ivarr); }
|
PeFile::Interval::~Interval() noexcept { ::free(ivarr); }
|
||||||
|
|
||||||
int __acc_cdecl_qsort PeFile::Interval::compare(const void *p1, const void *p2) {
|
int __acc_cdecl_qsort PeFile::Interval::compare(const void *p1, const void *p2) {
|
||||||
const interval *i1 = (const interval *) p1;
|
const interval *i1 = (const interval *) p1;
|
||||||
@ -1175,14 +1175,14 @@ PeFile::Export::Export(char *_base) : base(_base), iv((byte *) _base) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PeFile::Export::~Export() noexcept {
|
PeFile::Export::~Export() noexcept {
|
||||||
free(ename);
|
::free(ename);
|
||||||
delete[] functionptrs;
|
delete[] functionptrs;
|
||||||
delete[] ordinals;
|
delete[] ordinals;
|
||||||
if (names) {
|
if (names) {
|
||||||
const unsigned limit = edir.names + edir.functions;
|
const unsigned limit = edir.names + edir.functions;
|
||||||
for (unsigned ic = 0; ic < limit; ic++)
|
for (unsigned ic = 0; ic < limit; ic++)
|
||||||
if (names[ic])
|
if (names[ic])
|
||||||
free(names[ic]); // allocated by strdup()
|
::free(names[ic]); // allocated by strdup()
|
||||||
delete[] names;
|
delete[] names;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
src/ui.h
4
src/ui.h
@ -104,6 +104,10 @@ protected:
|
|||||||
static unsigned update_u_len;
|
static unsigned update_u_len;
|
||||||
static unsigned update_fc_len;
|
static unsigned update_fc_len;
|
||||||
static unsigned update_fu_len;
|
static unsigned update_fu_len;
|
||||||
|
|
||||||
|
private: // UPX conventions
|
||||||
|
UPX_CXX_DISABLE_ADDRESS(UiPacker)
|
||||||
|
UPX_CXX_DISABLE_COPY_MOVE(UiPacker)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
@ -427,7 +427,7 @@ template <class T>
|
|||||||
inline void owner_free(OwningPointer(T)(&object)) noexcept {
|
inline void owner_free(OwningPointer(T)(&object)) noexcept {
|
||||||
static_assert(!std::is_class_v<T>); // UPX convention
|
static_assert(!std::is_class_v<T>); // UPX convention
|
||||||
if (object != nullptr) {
|
if (object != nullptr) {
|
||||||
free((T *) object);
|
::free((T *) object);
|
||||||
object = nullptr;
|
object = nullptr;
|
||||||
}
|
}
|
||||||
assert_noexcept((T *) object == nullptr);
|
assert_noexcept((T *) object == nullptr);
|
||||||
|
@ -128,7 +128,7 @@ int upx_safe_vasprintf(char **ptr, const char *format, va_list ap) {
|
|||||||
va_end(ap_copy);
|
va_end(ap_copy);
|
||||||
|
|
||||||
if (len >= 0) {
|
if (len >= 0) {
|
||||||
*ptr = (char *) malloc(len + 1);
|
*ptr = (char *) ::malloc(len + 1);
|
||||||
assert(*ptr != nullptr);
|
assert(*ptr != nullptr);
|
||||||
if (*ptr == nullptr)
|
if (*ptr == nullptr)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
#define _LIBCPP_ENABLE_ASSERTIONS 1
|
#define _LIBCPP_ENABLE_ASSERTIONS 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif // clang >= 18
|
||||||
#endif // TODO later
|
#endif // TODO later
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
@ -254,17 +254,19 @@ TEST_CASE("ptr_check_no_overlap 3") {
|
|||||||
// stdlib
|
// stdlib
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
int upx_rand(void) noexcept { return ::rand(); }
|
||||||
|
|
||||||
void *upx_calloc(size_t n, size_t element_size) may_throw {
|
void *upx_calloc(size_t n, size_t element_size) may_throw {
|
||||||
size_t bytes = mem_size(element_size, n); // assert size
|
size_t bytes = mem_size(element_size, n); // assert size
|
||||||
void *p = malloc(bytes);
|
void *p = ::malloc(bytes);
|
||||||
if (p != nullptr)
|
if (p != nullptr)
|
||||||
memset(p, 0, bytes);
|
memset(p, 0, bytes);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simple unoptimized memswap()
|
// simple unoptimized memswap()
|
||||||
void upx_memswap(void *a, void *b, size_t n) noexcept {
|
void upx_memswap(void *a, void *b, size_t bytes) noexcept {
|
||||||
if (a != b && n != 0) {
|
if (a != b && bytes != 0) {
|
||||||
byte *x = (byte *) a;
|
byte *x = (byte *) a;
|
||||||
byte *y = (byte *) b;
|
byte *y = (byte *) b;
|
||||||
do {
|
do {
|
||||||
@ -273,16 +275,16 @@ void upx_memswap(void *a, void *b, size_t n) noexcept {
|
|||||||
byte tmp = *x; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning
|
byte tmp = *x; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning
|
||||||
*x++ = *y;
|
*x++ = *y;
|
||||||
*y++ = tmp;
|
*y++ = tmp;
|
||||||
} while (--n != 0);
|
} while (--bytes != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// much better memswap(), optimized for our use case in sort functions below
|
// much better memswap(), optimized for our use case in sort functions below
|
||||||
static void memswap_no_overlap(byte *a, byte *b, size_t n) noexcept {
|
static inline void memswap_no_overlap(byte *a, byte *b, size_t bytes) noexcept {
|
||||||
#if defined(__clang__) && __clang_major__ < 15
|
#if defined(__clang__) && __clang_major__ < 15
|
||||||
// work around a clang < 15 ICE (Internal Compiler Error)
|
// work around a clang < 15 ICE (Internal Compiler Error)
|
||||||
// @COMPILER_BUG @CLANG_BUG
|
// @COMPILER_BUG @CLANG_BUG
|
||||||
upx_memswap(a, b, n);
|
upx_memswap(a, b, bytes);
|
||||||
#else // clang bug
|
#else // clang bug
|
||||||
upx_alignas_max byte tmp_buf[16];
|
upx_alignas_max byte tmp_buf[16];
|
||||||
#define SWAP(x) \
|
#define SWAP(x) \
|
||||||
@ -294,15 +296,15 @@ static void memswap_no_overlap(byte *a, byte *b, size_t n) noexcept {
|
|||||||
b += x; \
|
b += x; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
for (; n >= 16; n -= 16)
|
for (; bytes >= 16; bytes -= 16)
|
||||||
SWAP(16);
|
SWAP(16);
|
||||||
if (n & 8)
|
if (bytes & 8)
|
||||||
SWAP(8);
|
SWAP(8);
|
||||||
if (n & 4)
|
if (bytes & 4)
|
||||||
SWAP(4);
|
SWAP(4);
|
||||||
if (n & 2)
|
if (bytes & 2)
|
||||||
SWAP(2);
|
SWAP(2);
|
||||||
if (n & 1) {
|
if (bytes & 1) {
|
||||||
byte tmp = *a;
|
byte tmp = *a;
|
||||||
*a = *b;
|
*a = *b;
|
||||||
*b = tmp;
|
*b = tmp;
|
||||||
@ -347,7 +349,7 @@ void upx_shellsort_memcpy(void *array, size_t n, size_t element_size, upx_compar
|
|||||||
upx_alignas_max byte tmp_buf[MAX_INLINE_ELEMENT_SIZE]; // buffer for one element
|
upx_alignas_max byte tmp_buf[MAX_INLINE_ELEMENT_SIZE]; // buffer for one element
|
||||||
byte *tmp = tmp_buf;
|
byte *tmp = tmp_buf;
|
||||||
if (element_size > MAX_INLINE_ELEMENT_SIZE) {
|
if (element_size > MAX_INLINE_ELEMENT_SIZE) {
|
||||||
tmp = (byte *) malloc(element_size);
|
tmp = (byte *) ::malloc(element_size);
|
||||||
assert(tmp != nullptr);
|
assert(tmp != nullptr);
|
||||||
}
|
}
|
||||||
size_t gap = 0; // 0, 1, 4, 13, 40, 121, 364, 1093, ...
|
size_t gap = 0; // 0, 1, 4, 13, 40, 121, 364, 1093, ...
|
||||||
@ -368,7 +370,7 @@ void upx_shellsort_memcpy(void *array, size_t n, size_t element_size, upx_compar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (element_size > MAX_INLINE_ELEMENT_SIZE)
|
if (element_size > MAX_INLINE_ELEMENT_SIZE)
|
||||||
free(tmp);
|
::free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrap std::stable_sort()
|
// wrap std::stable_sort()
|
||||||
@ -391,9 +393,10 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if UPX_CONFIG_USE_STABLE_SORT
|
#if UPX_CONFIG_USE_STABLE_SORT
|
||||||
// instantiate function templates for all element sizes we need; efficient run time, but code size
|
// instantiate function templates for all element sizes we need; efficient
|
||||||
// bloat (about 4KiB code size for each function with my current libstdc++); not really needed as
|
// run-time, but code size bloat (about 4KiB code size for each function
|
||||||
// libc qsort() is good enough for our use cases
|
// with my current libstdc++); not really needed as libc qsort() is
|
||||||
|
// good enough for our use cases
|
||||||
template void upx_std_stable_sort<1>(void *, size_t, upx_compare_func_t);
|
template void upx_std_stable_sort<1>(void *, size_t, upx_compare_func_t);
|
||||||
template void upx_std_stable_sort<2>(void *, size_t, upx_compare_func_t);
|
template void upx_std_stable_sort<2>(void *, size_t, upx_compare_func_t);
|
||||||
template void upx_std_stable_sort<4>(void *, size_t, upx_compare_func_t);
|
template void upx_std_stable_sort<4>(void *, size_t, upx_compare_func_t);
|
||||||
@ -405,7 +408,7 @@ template void upx_std_stable_sort<56>(void *, size_t, upx_compare_func_t);
|
|||||||
template void upx_std_stable_sort<72>(void *, size_t, upx_compare_func_t);
|
template void upx_std_stable_sort<72>(void *, size_t, upx_compare_func_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(DOCTEST_CONFIG_DISABLE) && DEBUG >= 1
|
#if !defined(DOCTEST_CONFIG_DISABLE) && DEBUG
|
||||||
#if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations
|
#if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations
|
||||||
namespace {
|
namespace {
|
||||||
template <class ElementType, upx_compare_func_t CompareFunc>
|
template <class ElementType, upx_compare_func_t CompareFunc>
|
||||||
@ -588,7 +591,7 @@ int find(const void *buf, int blen, const void *what, int wlen) noexcept {
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
const byte *b = (const byte *) buf;
|
const byte *b = (const byte *) buf;
|
||||||
byte first_byte = *(const byte *) what;
|
const byte first_byte = *(const byte *) what;
|
||||||
|
|
||||||
blen -= wlen;
|
blen -= wlen;
|
||||||
for (int i = 0; i <= blen; i++, b++)
|
for (int i = 0; i <= blen; i++, b++)
|
||||||
@ -769,8 +772,8 @@ int fn_strcmp(const char *n1, const char *n2) {
|
|||||||
// misc
|
// misc
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
// UPX convention: any environment variable that is set and is not strictly equal to "0" is true
|
||||||
bool is_envvar_true(const char *envvar, const char *alternate_name) noexcept {
|
bool is_envvar_true(const char *envvar, const char *alternate_name) noexcept {
|
||||||
// UPX convention: any environment variable that is set and is not strictly equal to "0" is true
|
|
||||||
const char *e = getenv(envvar);
|
const char *e = getenv(envvar);
|
||||||
if (e != nullptr && e[0])
|
if (e != nullptr && e[0])
|
||||||
return strcmp(e, "0") != 0;
|
return strcmp(e, "0") != 0;
|
||||||
|
@ -143,9 +143,11 @@ inline void ptr_invalidate_and_poison(T *(&ptr)) noexcept {
|
|||||||
// stdlib
|
// stdlib
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void *upx_calloc(size_t n, size_t element_size) may_throw;
|
noinline void *upx_calloc(size_t n, size_t element_size) may_throw;
|
||||||
|
|
||||||
void upx_memswap(void *a, void *b, size_t n) noexcept;
|
void upx_memswap(void *a, void *b, size_t bytes) noexcept;
|
||||||
|
|
||||||
|
noinline int upx_rand(void) noexcept;
|
||||||
|
|
||||||
typedef int(__acc_cdecl_qsort *upx_compare_func_t)(const void *, const void *);
|
typedef int(__acc_cdecl_qsort *upx_compare_func_t)(const void *, const void *);
|
||||||
typedef void (*upx_sort_func_t)(void *array, size_t n, size_t element_size, upx_compare_func_t);
|
typedef void (*upx_sort_func_t)(void *array, size_t n, size_t element_size, upx_compare_func_t);
|
||||||
@ -165,7 +167,7 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare);
|
|||||||
upx_std_stable_sort<(element_size)>((a), (n), (compare))
|
upx_std_stable_sort<(element_size)>((a), (n), (compare))
|
||||||
#else
|
#else
|
||||||
// use libc qsort(); good enough for our use cases
|
// use libc qsort(); good enough for our use cases
|
||||||
#define upx_qsort qsort
|
#define upx_qsort ::qsort
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
// of class PackerBase which then does the actual work.
|
// of class PackerBase which then does the actual work.
|
||||||
// And see p_com.cpp for a simple executable format.
|
// And see p_com.cpp for a simple executable format.
|
||||||
//
|
//
|
||||||
// This file also has the burden to deal with all those pesky low-level
|
// And this file also has the burden to deal with all those pesky low-level
|
||||||
// file handling issues.
|
// file handling issues.
|
||||||
|
|
||||||
#define WANT_WINDOWS_LEAN_H 1 // _get_osfhandle, GetFileTime, SetFileTime
|
#define WANT_WINDOWS_LEAN_H 1 // _get_osfhandle, GetFileTime, SetFileTime
|
||||||
@ -47,7 +47,7 @@
|
|||||||
#include "util/membuffer.h"
|
#include "util/membuffer.h"
|
||||||
|
|
||||||
#if USE_UTIMENSAT && defined(AT_FDCWD)
|
#if USE_UTIMENSAT && defined(AT_FDCWD)
|
||||||
#elif (defined(_WIN32) || defined(__CYGWIN__)) && 1
|
#elif defined(_WIN32) || defined(__CYGWIN__)
|
||||||
#define USE_SETFILETIME 1
|
#define USE_SETFILETIME 1
|
||||||
#elif (ACC_OS_DOS32) && defined(__DJGPP__)
|
#elif (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||||
#define USE_FTIME 1
|
#define USE_FTIME 1
|
||||||
|
Loading…
Reference in New Issue
Block a user