From 15484aa296075fcba23aac5c7aae3597233dc3e8 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sat, 18 Mar 2023 21:27:34 +0100 Subject: [PATCH] all: more cleanups Changes include: - extract headers.h from conf.h - use "byte" in some more places - unify "const" coding style - pefile.cpp: make sort order deterministic - simplify some other pefile.cpp code - CI updates --- .github/CODEOWNERS | 11 ++ .github/typos_config.toml | 1 + .github/workflows/ci.yml | 4 +- .github/workflows/minimal-ci.yml | 9 +- .github/workflows/scan-build.yml | 20 +-- CMakeLists.txt | 4 +- THANKS => doc/THANKS.txt | 0 src/bele.h | 6 + src/conf.h | 102 +------------ src/filter/ctojr.h | 20 +-- src/filter/ctok.h | 4 +- src/filter/filter_impl.cpp | 2 +- src/headers.h | 116 +++++++++++++++ src/lefile.h | 26 ++-- src/linker.cpp | 4 +- src/msg.cpp | 2 + src/p_djgpp2.h | 16 +-- src/p_exe.h | 4 +- src/p_ps1.h | 4 +- src/p_tmt.h | 6 +- src/p_wcle.cpp | 2 +- src/packer.cpp | 8 +- src/packer_f.cpp | 12 +- src/pefile.cpp | 159 ++++++++++----------- src/pefile.h | 28 ++-- src/stub/src/i386-dos32.djgpp2-stubify.asm | 2 +- src/util/util.cpp | 60 +++++--- src/util/util.h | 6 +- 28 files changed, 351 insertions(+), 287 deletions(-) create mode 100644 .github/CODEOWNERS rename THANKS => doc/THANKS.txt (100%) create mode 100644 src/headers.h diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..cf8d874e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,11 @@ +* @markus-oberhumer @jreiser + +/src/p_elf* @jreiser +/src/p_lx_* @jreiser +/src/p_mach* @jreiser +/src/p_unix* @jreiser +/src/p_vmlin* @jreiser + +/src/stub/src/*bsd.* @jreiser +/src/stub/src/*darwin.* @jreiser +/src/stub/src/*linux.* @jreiser diff --git a/.github/typos_config.toml b/.github/typos_config.toml index c968c19f..34b8b0ce 100644 --- a/.github/typos_config.toml +++ b/.github/typos_config.toml @@ -9,6 +9,7 @@ extend-exclude = ["LICENSE"] [default.extend-identifiers] # misc variable names & symbols acc_spawnve = "acc_spawnve" +ba = "ba" fo = "fo" fof = "fof" sidelen = "sidelen" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 601d521e..c001e52b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -377,8 +377,8 @@ jobs: - { zig_target: x86_64-macos.13-none } - { zig_target: x86_64-windows-gnu } env: - # 2023-03-14 - ZIG_DIST_VERSION: 0.11.0-dev.1970+962299157 + # 2023-03-18 + ZIG_DIST_VERSION: 0.11.0-dev.2157+f56f3c582 # for zig-cc wrapper scripts (see below): ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING ZIG_FLAGS: ${{ matrix.zig_flags }} diff --git a/.github/workflows/minimal-ci.yml b/.github/workflows/minimal-ci.yml index 41420801..0420ad15 100644 --- a/.github/workflows/minimal-ci.yml +++ b/.github/workflows/minimal-ci.yml @@ -5,22 +5,25 @@ name: 'CI - Minimal CI with Alpine Linux' on: [workflow_dispatch] jobs: job-alpine-cmake: - strategy: {matrix: {container: ['alpine:3.12','alpine:3.17','alpine:edge']}} + strategy: + fail-fast: false + matrix: {container: ['alpine:3.12','alpine:3.17','alpine:edge','i386/alpine:edge']} name: ${{ format('container {0}', matrix.container) }} runs-on: ubuntu-latest container: ${{ matrix.container }} steps: - name: ${{ format('Install packages {0}', matrix.container) }} run: 'apk update && apk upgrade && apk add bash clang cmake g++ git make' - - name: ${{ format('Check out code upx-{0}', github.ref_name) }} + - name: ${{ format('Check out UPX {0} source code', github.ref_name) }} run: | git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx git -C upx submodule update --init - echo "artifact_name=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-minimal-ci-${{ matrix.container }}" | sed 's/[:,; ]/-/g' >> $GITHUB_ENV + echo "artifact_name=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-minimal-ci-${{ matrix.container }}" | sed 's/[^=0-9a-zA-Z_.-]/-/g' >> $GITHUB_ENV - { name: 'Build clang', run: 'make -C upx UPX_XTARGET=clang-static CC="clang -static" CXX="clang++ -static"' } - { name: 'Build gcc', run: 'make -C upx UPX_XTARGET=gcc-static CC="gcc -static" CXX="g++ -static"' } - { name: 'Strip release binaries', run: 'strip -p --strip-unneeded upx/build/*/*/release/upx' } - name: ${{ format('Upload artifact {0}', env.artifact_name) }} + if: ${{ !startsWith(matrix.container, 'i386/alpine') }} # missing nodejs uses: actions/upload-artifact@v3 with: name: ${{ env.artifact_name }} diff --git a/.github/workflows/scan-build.yml b/.github/workflows/scan-build.yml index b320abbc..c132344f 100644 --- a/.github/workflows/scan-build.yml +++ b/.github/workflows/scan-build.yml @@ -7,16 +7,20 @@ on: jobs: analyze: - name: Analyze + strategy: + fail-fast: false + matrix: {container: ['alpine:3.16','alpine:3.17','alpine:edge','i386/alpine:edge']} + name: ${{ format('Analyze {0}', matrix.container) }} runs-on: ubuntu-latest - container: 'alpine:edge' + container: ${{ matrix.container }} steps: - - name: 'Install packages' + - name: ${{ format('Install packages {0}', matrix.container) }} run: 'apk update && apk upgrade && apk add bash clang clang-analyzer cmake g++ git make' - - name: 'Check out code' - uses: actions/checkout@v3 - with: { submodules: true } + - name: ${{ format('Check out UPX {0} source code', github.ref_name) }} + run: | + git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx + git -C upx submodule update --init - name: 'Perform scan-build Analysis Debug' - run: 'make build/extra/scan-build/debug' + run: 'make -C upx build/extra/scan-build/debug' - name: 'Perform scan-build Analysis Release' - run: 'make build/extra/scan-build/release' + run: 'make -C upx build/extra/scan-build/release' diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b808241..ec68b290 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) # CMake >= 3.20.0 is recommended +cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) # CMake >= 3.20 is recommended # compilation config options if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") @@ -331,7 +331,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 README doc/THANKS.txt doc/upx-doc.html doc/upx-doc.txt DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}" ) install(FILES doc/upx.1 DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man1") diff --git a/THANKS b/doc/THANKS.txt similarity index 100% rename from THANKS rename to doc/THANKS.txt diff --git a/src/bele.h b/src/bele.h index 28c0e533..ff31a7ad 100644 --- a/src/bele.h +++ b/src/bele.h @@ -675,6 +675,9 @@ typedef BE64 NE64; #define ne16_compare be16_compare #define ne32_compare be32_compare #define ne64_compare be64_compare +#define ne16_compare_signed be16_compare_signed +#define ne32_compare_signed be32_compare_signed +#define ne64_compare_signed be64_compare_signed #else typedef LE16 NE16; typedef LE32 NE32; @@ -682,6 +685,9 @@ typedef LE64 NE64; #define ne16_compare le16_compare #define ne32_compare le32_compare #define ne64_compare le64_compare +#define ne16_compare_signed le16_compare_signed +#define ne32_compare_signed le32_compare_signed +#define ne64_compare_signed le64_compare_signed #endif /************************************************************************* diff --git a/src/conf.h b/src/conf.h index 1cb81126..3291ec93 100644 --- a/src/conf.h +++ b/src/conf.h @@ -26,43 +26,14 @@ */ #pragma once -#ifndef UPX_CONF_H__ -#define UPX_CONF_H__ 1 - -#if !(__cplusplus+0 >= 201703L) -# error "C++ 17 is required" -#endif - -#include "version.h" - -#if !defined(_FILE_OFFSET_BITS) -# define _FILE_OFFSET_BITS 64 -#endif -#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) -# if !defined(_USE_MINGW_ANSI_STDIO) -# define _USE_MINGW_ANSI_STDIO 1 -# endif -#endif - /************************************************************************* -// ACC and system includes +// init **************************************************************************/ -#ifndef ACC_CFG_USE_NEW_STYLE_CASTS -#define ACC_CFG_USE_NEW_STYLE_CASTS 1 -#endif -#define ACC_CFG_PREFER_TYPEOF_ACC_INT32E_T ACC_TYPEOF_INT -#define ACC_CFG_PREFER_TYPEOF_ACC_INT64E_T ACC_TYPEOF_LONG_LONG -#include "miniacc.h" -#if !(ACC_CC_CLANG || ACC_CC_GNUC || ACC_CC_MSC) - // other compilers may work, but we're NOT interested into supporting them -# error "only clang, gcc and msvc are officially supported" -#endif -// UPX sanity checks for a sane compiler -#if !defined(UINT_MAX) || (UINT_MAX != 0xffffffffL) -# error "UINT_MAX" -#endif +#include "headers.h" +#include "version.h" + ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_BIT == 8) ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2) ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) @@ -101,43 +72,10 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char #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 -#endif - -#undef snprintf -#undef vsnprintf -#define HAVE_STDINT_H 1 -#define ACC_WANT_ACC_INCD_H 1 -#define ACC_WANT_ACC_INCE_H 1 -#define ACC_WANT_ACC_LIB_H 1 -#define ACC_WANT_ACC_CXX_H 1 -#include "miniacc.h" -#if (ACC_CC_MSC) -# include -#endif - -// C++ system headers -#include -#include -#include -#include - // multithreading (UPX currently does not use multithreading) -#ifndef WITH_THREADS -# define WITH_THREADS 0 -#endif -#if __STDC_NO_ATOMICS__ -# undef WITH_THREADS -#endif #if (WITH_THREADS) #define upx_thread_local thread_local -#include #define upx_std_atomic(Type) std::atomic -#include #define upx_std_once_flag std::once_flag #define upx_std_call_once std::call_once #else @@ -150,29 +88,6 @@ inline void upx_std_call_once(upx_std_once_flag &flag, NoexceptCallable &&f) { } #endif // WITH_THREADS -// C++ submodule headers -#include -#if WITH_BOOST_PFR -# include -# include -#endif -#if WITH_RANGELESS_FN -# include -#endif -#ifndef WITH_VALGRIND -# define WITH_VALGRIND 1 -#endif -#if defined(__SANITIZE_ADDRESS__) || defined(_WIN32) || !defined(__GNUC__) -# undef WITH_VALGRIND -#endif -#if (WITH_VALGRIND) -# include -#endif - -// IMPORTANT: unconditionally enable assertions -#undef NDEBUG -#include - // C++20 std::is_bounded_array template struct upx_std_is_bounded_array : public std::false_type {}; @@ -195,7 +110,6 @@ inline constexpr bool upx_is_integral_v = upx_is_integral::value; #define alignas(x) upx_fake_alignas__(x) #endif - /************************************************************************* // core **************************************************************************/ @@ -922,12 +836,4 @@ int upx_test_overlap ( const upx_bytep buf, #include "util/xspan.h" -#if (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64) -# if defined(INVALID_HANDLE_VALUE) || defined(MAKEWORD) || defined(RT_CURSOR) -# error "something pulled in " -# endif -#endif - -#endif /* already included */ - /* vim:set ts=4 sw=4 et: */ diff --git a/src/filter/ctojr.h b/src/filter/ctojr.h index b1bfa6bb..36220b43 100644 --- a/src/filter/ctojr.h +++ b/src/filter/ctojr.h @@ -67,8 +67,8 @@ f80_jcc2(Filter const *f) // Adaptively remember recent destinations. static void update_mru( - unsigned const jc, // destination address - int const kh, // mru[kh] is slot where found + const unsigned jc, // destination address + const int kh, // mru[kh] is slot where found unsigned mru[N_MRU], // circular buffer of most recent destinations int &hand, // mru[hand] is most recent destination int &tail // mru[tail] is beyond oldest destination ("cold cache" startup) @@ -77,7 +77,7 @@ update_mru( if (0 > --hand) { hand = N_MRU -1; } - unsigned const t = mru[hand]; // entry which will be overwritten by jc + const unsigned t = mru[hand]; // entry which will be overwritten by jc if (0!=t) { // have seen at least N_MRU destinations mru[kh] = t; } @@ -85,7 +85,7 @@ update_mru( if (0 > --tail) { tail = N_MRU -1; } - unsigned const t2 = mru[tail]; + const unsigned t2 = mru[tail]; mru[tail] = 0; mru[kh] = t2; } @@ -111,9 +111,9 @@ static int F(Filter *f) unsigned wtally[3]; memset(wtally, 0, sizeof(wtally)); #ifdef U //{ - unsigned const f_call = f80_call(f); - unsigned const f_jmp1 = f80_jmp1(f); - unsigned const f_jcc2 = f80_jcc2(f); + const unsigned f_call = f80_call(f); + const unsigned f_jmp1 = f80_jmp1(f); + const unsigned f_jcc2 = f80_jcc2(f); int hand = 0, tail = 0; unsigned mru[N_MRU]; @@ -273,9 +273,9 @@ static int U(Filter *f) const unsigned cto = (unsigned)f->cto << 24; unsigned lastcall = 0; int hand = 0, tail = 0; - unsigned const f_call = f80_call(f); - unsigned const f_jmp1 = f80_jmp1(f); - unsigned const f_jcc2 = f80_jcc2(f); + const unsigned f_call = f80_call(f); + const unsigned f_jmp1 = f80_jmp1(f); + const unsigned f_jcc2 = f80_jcc2(f); unsigned mru[N_MRU]; memset(&mru[0], 0, sizeof(mru)); diff --git a/src/filter/ctok.h b/src/filter/ctok.h index bb228688..9631960d 100644 --- a/src/filter/ctok.h +++ b/src/filter/ctok.h @@ -46,7 +46,7 @@ static int F(Filter *f) #endif const unsigned addvalue = f->addvalue; const unsigned size = f->buf_len; - unsigned const id = f->id; + const unsigned id = f->id; unsigned ic, jc, kc; unsigned calls = 0, noncalls = 0, noncalls2 = 0; @@ -145,7 +145,7 @@ static int U(Filter *f) const unsigned size5 = f->buf_len - 5; const unsigned addvalue = f->addvalue; const unsigned cto = (unsigned)f->cto << 24; - unsigned const id = f->id; + const unsigned id = f->id; unsigned lastcall = 0; unsigned ic, jc; diff --git a/src/filter/filter_impl.cpp b/src/filter/filter_impl.cpp index 8a4f730b..f3b21f3e 100644 --- a/src/filter/filter_impl.cpp +++ b/src/filter/filter_impl.cpp @@ -30,7 +30,7 @@ #include "../filter.h" static unsigned -umin(unsigned const a, unsigned const b) +umin(const unsigned a, const unsigned b) { return (a<=b) ? a : b; } diff --git a/src/headers.h b/src/headers.h new file mode 100644 index 00000000..e2e0b2a5 --- /dev/null +++ b/src/headers.h @@ -0,0 +1,116 @@ +/* headers.h -- include system headers + + This file is part of the UPX executable compressor. + + Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer + 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 + + */ + +#pragma once + +#if !(__cplusplus + 0 >= 201703L) +#error "C++ 17 is required" +#endif + +#if !defined(_FILE_OFFSET_BITS) +#define _FILE_OFFSET_BITS 64 +#endif +#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) +#if !defined(_USE_MINGW_ANSI_STDIO) +#define _USE_MINGW_ANSI_STDIO 1 +#endif +#endif + +// ACC and C system headers +#ifndef ACC_CFG_USE_NEW_STYLE_CASTS +#define ACC_CFG_USE_NEW_STYLE_CASTS 1 +#endif +#define ACC_CFG_PREFER_TYPEOF_ACC_INT32E_T ACC_TYPEOF_INT +#define ACC_CFG_PREFER_TYPEOF_ACC_INT64E_T ACC_TYPEOF_LONG_LONG +#include "miniacc.h" + +// disable some pedantic warnings +#if (ACC_CC_MSC) +#pragma warning(disable : 4244) // -Wconversion +#pragma warning(disable : 4267) // -Wconversion +#pragma warning(disable : 4820) // padding added after data member +#endif + +#undef snprintf +#undef vsnprintf +#define HAVE_STDINT_H 1 +#define ACC_WANT_ACC_INCD_H 1 +#define ACC_WANT_ACC_INCE_H 1 +#define ACC_WANT_ACC_LIB_H 1 +#define ACC_WANT_ACC_CXX_H 1 +#include "miniacc.h" +#if (ACC_CC_MSC) +#include +#endif + +// C++ system headers +#include +#include +#include + +// C++ multithreading (UPX currently does not use multithreading) +#ifndef WITH_THREADS +#define WITH_THREADS 0 +#endif +#if __STDC_NO_ATOMICS__ +#undef WITH_THREADS +#endif +#if WITH_THREADS +#include +#include +#endif + +// C++ submodule headers +#include +#if WITH_BOOST_PFR +#include +#include +#endif +#if WITH_RANGELESS_FN +#include +#endif +#ifndef WITH_VALGRIND +#define WITH_VALGRIND 1 +#endif +#if defined(__SANITIZE_ADDRESS__) || defined(_WIN32) || !defined(__GNUC__) +#undef WITH_VALGRIND +#endif +#if WITH_VALGRIND +#include +#endif + +// IMPORTANT: unconditionally enable assertions +#undef NDEBUG +#include + +#if (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || \ + ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64) +#if defined(INVALID_HANDLE_VALUE) || defined(MAKEWORD) || defined(RT_CURSOR) +#error "something pulled in " +#endif +#endif + +/* vim:set ts=4 sw=4 et: */ diff --git a/src/lefile.h b/src/lefile.h index e42f2535..90767473 100644 --- a/src/lefile.h +++ b/src/lefile.h @@ -49,13 +49,13 @@ protected: struct alignas(1) le_header_t { // 0x00 - char _[2]; // signature: 'LE' || 'LX' - char byte_order; // 0 little endian - char word_order; // 0 little endian + byte _[2]; // signature: 'LE' || 'LX' + byte byte_order; // 0 little endian + byte word_order; // 0 little endian LE32 exe_format_level; // 0 LE16 cpu_type; // 1->286..4->586 LE16 target_os; // 1->OS2 - char _0[4]; // module_version = 0 + byte _0[4]; // module_version = 0 // 0x10 LE32 module_type; // 0x200->compatible with PM windowing LE32 memory_pages; @@ -68,21 +68,21 @@ protected: LE32 bytes_on_last_page; // 0x30 LE32 fixup_size; - char _1[4]; // fixup_checksum = 0 + byte _1[4]; // fixup_checksum = 0 LE32 loader_size; - char _2[4]; // loader_checksum = 0 + byte _2[4]; // loader_checksum = 0 // 0x40 LE32 object_table_offset; LE32 object_table_entries; LE32 object_pagemap_offset; LE32 object_iterate_data_map_offset; // 0x50 - char _3[4]; // resource_offset + byte _3[4]; // resource_offset LE32 resource_entries; LE32 resident_names_offset; LE32 entry_table_offset; // 0x60 - char _4[4]; // module_directives_table_offset = 0 + byte _4[4]; // module_directives_table_offset = 0 LE32 module_directives_entries; LE32 fixup_page_table_offset; LE32 fixup_record_table_offset; @@ -90,17 +90,17 @@ protected: LE32 imported_modules_name_table_offset; LE32 imported_modules_count; LE32 imported_procedures_name_table_offset; - char _5[4]; // per_page_checksum_table_offset = 0 + byte _5[4]; // per_page_checksum_table_offset = 0 // 0x80 LE32 data_pages_offset; - char _6[4]; // preload_page_count = 0 + byte _6[4]; // preload_page_count = 0 LE32 non_resident_name_table_offset; LE32 non_resident_name_table_length; // 0x90 - char _7[4]; // non_resident_names_checksum + byte _7[4]; // non_resident_names_checksum LE32 automatic_data_object; #if 1 - char _8[44]; + byte _8[44]; #else LE32 debug_info_offset; LE32 debug_info_length; @@ -108,7 +108,7 @@ protected: LE32 preload_instance_pages; LE32 demand_instance_pages; LE32 extra_heap_alloc; - char reserved[12]; + byte reserved[12]; LE32 versioninfo; LE32 unknown; // 0xC0 diff --git a/src/linker.cpp b/src/linker.cpp index 4bae3d06..bc9d7b13 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -404,8 +404,8 @@ int ElfLinker::addLoader(const char *sname) { assert(tail); assert(tail != section); // .p2align must be < 32 - unsigned const v = ~0u << section->p2align; - if (unsigned const l = ~v & (0u - (unsigned) (tail->offset + tail->size))) { + const unsigned v = ~0u << section->p2align; + if (const unsigned l = ~v & (0u - (unsigned) (tail->offset + tail->size))) { alignCode(l); tail->size += l; } diff --git a/src/msg.cpp b/src/msg.cpp index cf7e0827..4615306b 100644 --- a/src/msg.cpp +++ b/src/msg.cpp @@ -25,6 +25,8 @@ */ +#include "headers.h" +#include #include "conf.h" /************************************************************************* diff --git a/src/p_djgpp2.h b/src/p_djgpp2.h index 1e46b5d0..e1d29a51 100644 --- a/src/p_djgpp2.h +++ b/src/p_djgpp2.h @@ -65,32 +65,32 @@ protected: unsigned coff_offset; struct alignas(1) external_scnhdr_t { - char _[12]; // name, paddr + byte _[12]; // name, paddr LE32 vaddr; LE32 size; LE32 scnptr; - char misc[12]; // relptr, lnnoptr, nreloc, nlnno - char __[4]; // flags + byte misc[12]; // relptr, lnnoptr, nreloc, nlnno + byte __[4]; // flags }; struct alignas(1) coff_header_t { // ext_file_hdr LE16 f_magic; LE16 f_nscns; - char _[4]; // f_timdat + byte _[4]; // f_timdat LE32 f_symptr; LE32 f_nsyms; - char __[2]; // f_opthdr + byte __[2]; // f_opthdr LE16 f_flags; // aout_hdr LE16 a_magic; - char ___[2]; // a_vstamp + byte ___[2]; // a_vstamp LE32 a_tsize; LE32 a_dsize; - char ____[4]; // a_bsize + byte ____[4]; // a_bsize LE32 a_entry; - char _____[8]; // a_text_start a_data_start + byte _____[8]; // a_text_start a_data_start // section headers external_scnhdr_t sh[3]; diff --git a/src/p_exe.h b/src/p_exe.h index 958262b1..90312ce1 100644 --- a/src/p_exe.h +++ b/src/p_exe.h @@ -80,11 +80,11 @@ protected: LE16 max; LE16 ss; LE16 sp; - char _[2]; // checksum + byte _[2]; // checksum LE16 ip; LE16 cs; LE16 relocoffs; - char __[2]; // overlnum + byte __[2]; // overlnum LE32 firstreloc; }; diff --git a/src/p_ps1.h b/src/p_ps1.h index 6a9b6127..029ffcb0 100644 --- a/src/p_ps1.h +++ b/src/p_ps1.h @@ -68,7 +68,7 @@ protected: struct alignas(1) ps1_exe_t { // ident string - char id[8]; + byte id[8]; // is nullptr LE32 text; // is nullptr @@ -86,7 +86,7 @@ protected: // saved regs on execution LE32 sp, fp, gp0, ra, k0; // origin Jap/USA/Europe - char origin[60]; + byte origin[60]; // backup of the original header (epc - is_len) // id & the upx header ... }; diff --git a/src/p_tmt.h b/src/p_tmt.h index 2ffe0671..60598f71 100644 --- a/src/p_tmt.h +++ b/src/p_tmt.h @@ -65,11 +65,11 @@ protected: int big_relocs = 0; struct alignas(1) tmt_header_t { - char _[16]; // signature,linkerversion,minversion,exesize,imagestart + byte _[16]; // signature,linkerversion,minversion,exesize,imagestart LE32 imagesize; - char __[4]; // initial memory + byte __[4]; // initial memory LE32 entry; - char ___[12]; // esp,numfixups,flags + byte ___[12]; // esp,numfixups,flags LE32 relocsize; }; tmt_header_t ih, oh; diff --git a/src/p_wcle.cpp b/src/p_wcle.cpp index a81bdb7c..b3170df4 100644 --- a/src/p_wcle.cpp +++ b/src/p_wcle.cpp @@ -527,7 +527,7 @@ void PackWcle::decodeFixups() { SPAN_S_VAR(const byte, p, oimage + soimage); MemBuffer mb_relocs; - unsigned const fixupn = unoptimizeReloc(p, mb_relocs, oimage, soimage, 32, true); + const unsigned fixupn = unoptimizeReloc(p, mb_relocs, oimage, soimage, 32, true); MemBuffer wrkmem(8 * fixupn + 8); unsigned ic, jc, o, r; diff --git a/src/packer.cpp b/src/packer.cpp index fab36042..5a28eb23 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -1092,13 +1092,13 @@ done: } void Packer::compressWithFilters(byte *i_ptr, - unsigned const i_len, // written and restored by filters + const unsigned i_len, // written and restored by filters byte *const o_ptr, // where to put compressed output byte *f_ptr, - unsigned const f_len, // subset of [*i_ptr, +i_len) - byte *const hdr_ptr, unsigned const hdr_len, + const unsigned f_len, // subset of [*i_ptr, +i_len) + byte *const hdr_ptr, const unsigned hdr_len, Filter *const parm_ft, // updated - unsigned const overlap_range, + const unsigned overlap_range, upx_compress_config_t const *const cconf, int filter_strategy, // in+out for prepareFilters bool const inhibit_compression_check) { diff --git a/src/packer_f.cpp b/src/packer_f.cpp index e3564cd9..f2b20d00 100644 --- a/src/packer_f.cpp +++ b/src/packer_f.cpp @@ -91,11 +91,11 @@ void Packer::addFilter32(int filter_id) { } 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; + const unsigned 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); + const unsigned f_call = f80_call(filter_id); + const unsigned f_jmp1 = f80_jmp1(filter_id); + const unsigned f_jcc2 = f80_jcc2(filter_id); if (NOFILT != f_jcc2) { addLoader("LXJCC010"); @@ -296,9 +296,9 @@ void Packer::defineFilterSymbols(const Filter *ft) { #if 0 if (0x80 == (ft->id & 0xF0)) { - int const mru = ph.n_mru ? 1 + ph.n_mru : 0; + const int mru = ph.n_mru ? 1 + ph.n_mru : 0; if (mru && mru != 256) { - unsigned const is_pwr2 = (0 == ((mru - 1) & mru)); + const unsigned is_pwr2 = (0 == ((mru - 1) & mru)); // patch_le32(0x80 + (char *) loader, lsize - 0x80, "NMRU", mru - is_pwr2); } } diff --git a/src/pefile.cpp b/src/pefile.cpp index 8f3a0b23..abd2749d 100644 --- a/src/pefile.cpp +++ b/src/pefile.cpp @@ -178,7 +178,7 @@ int PeFile::readFileHeader() { (unsigned) h.nexepos, (unsigned) sizeof(exe_header_t)); throwCantPack(buf); } - unsigned const delta = (h.relocoffs >= 0x40) + const unsigned delta = (h.relocoffs >= 0x40) ? h.nexepos // new format exe : (h.p512 * 512 + h.m512 - h.m512 ? 512 : h.nexepos); @@ -367,8 +367,8 @@ void PeFile32::processRelocs() // pass1 { big_relocs = 0; - unsigned const take1 = IDSIZE(PEDIR_RELOC); - unsigned const skip1 = IDADDR(PEDIR_RELOC); + const unsigned skip1 = IDADDR(PEDIR_RELOC); + const unsigned take1 = IDSIZE(PEDIR_RELOC); Reloc rel(ibuf.subref("bad reloc %#x", skip1, take1), take1); const unsigned *counts = rel.getcounts(); unsigned relocnum = 0; @@ -465,8 +465,8 @@ void PeFile64::processRelocs() // pass1 { big_relocs = 0; - unsigned const take = IDSIZE(PEDIR_RELOC); - unsigned const skip = IDADDR(PEDIR_RELOC); + const unsigned skip = IDADDR(PEDIR_RELOC); + const unsigned take = IDSIZE(PEDIR_RELOC); Reloc rel(ibuf.subref("bad reloc %#x", skip, take), take); const unsigned *counts = rel.getcounts(); unsigned relocnum = 0; @@ -598,15 +598,13 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 { // encoding of dll and proc names are required, so that our special // control characters in the name of sections can work as intended - static char *encode_name(const char *name, char *buf) { - char *b = buf; + static void encode_name(const char *name, char *buf) { while (*name) { - *b++ = 'a' + ((*name >> 4) & 0xf); - *b++ = 'a' + (*name & 0xf); + *buf++ = 'a' + ((*name >> 4) & 0xf); + *buf++ = 'a' + (*name & 0xf); name++; } - *b = 0; - return buf; + *buf = 0; } static char *name_for_dll(const char *dll, char first_char) { @@ -615,13 +613,13 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 { assert(l > 0); char *name = New(char, 3 * l + 2); - assert(name); name[0] = first_char; char *n = name + 1 + 2 * l; do { - *n++ = tolower(*dll); + *n++ = tolower((uchar) *dll); } while (*dll++); - return encode_name(name + 1 + 2 * l, name + 1) - 1; + encode_name(name + 1 + 2 * l, name + 1); + return name; } static char *name_for_proc(const char *dll, const char *proc, char first_char, char separator) { @@ -696,7 +694,10 @@ class PeFile::ImportLinker final : public ElfLinkerAMD64 { static int __acc_cdecl_qsort compare(const void *p1, const void *p2) { const Section *s1 = *(const Section *const *) p1; const Section *s2 = *(const Section *const *) p2; - return strcmp(s1->name, s2->name); + int rc = strcmp(s1->name, s2->name); + if (rc != 0) + return rc; + return s1 < s2 ? -1 : 1; // make sort order deterministic/stable } virtual void alignCode(unsigned len) override { alignWithByte(len, 0); } @@ -841,26 +842,26 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 } unsigned dllnum = 0; - unsigned const take = IDSIZE(PEDIR_IMPORT); - unsigned const skip = IDADDR(PEDIR_IMPORT); - import_desc *im = (import_desc *) ibuf.subref("bad import %#x", skip, take); - import_desc *const im_save = im; - if (IDADDR(PEDIR_IMPORT)) { - for (;; ++dllnum, ++im) { - unsigned const skip2 = ptr_udiff_bytes(im, ibuf); + const unsigned skip = IDADDR(PEDIR_IMPORT); + const unsigned take = IDSIZE(PEDIR_IMPORT); + import_desc *const im_start = (import_desc *) ibuf.subref("bad import %#x", skip, take); + if (IDADDR(PEDIR_IMPORT) != 0) { + for (const import_desc *im = im_start;; ++dllnum, ++im) { + const unsigned skip2 = ptr_udiff_bytes(im, ibuf); (void) ibuf.subref("bad import %#x", skip2, sizeof(*im)); - if (!im->dllname) + if (im->dllname == 0) break; } - im = im_save; } + if (dllnum > 4096) // just some arbitrary limit/sanity check + throwCantPack("too many DLL imports %u", dllnum); struct udll { const byte *name; const byte *shname; unsigned ordinal; unsigned iat; - LEXX *lookupt; + const LEXX *lookupt; unsigned original_position; bool isk32; @@ -872,16 +873,20 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 if ((*u1->lookupt != 0) != (*u2->lookupt != 0)) return (*u1->lookupt != 0) ? -1 : 1; int rc = strcasecmp(u1->name, u2->name); - if (rc) + if (rc != 0) return rc; if ((u1->ordinal != 0) != (u2->ordinal != 0)) return (u1->ordinal != 0) ? -1 : 1; - if ((u1->shname != nullptr) != (u2->shname != nullptr)) + if (u1->shname && u2->shname) { + rc = (int) (upx_safe_strlen(u1->shname) - upx_safe_strlen(u2->shname)); + if (rc != 0) + return rc; + rc = strcmp(u1->shname, u2->shname); + if (rc != 0) + return rc; + } else if ((u1->shname != nullptr) != (u2->shname != nullptr)) return (u1->shname != nullptr) ? -1 : 1; - rc = (int) (upx_safe_strlen(u1->shname) - upx_safe_strlen(u2->shname)); - if (rc) - return rc; - return strcmp(u1->shname, u2->shname); + return u1 < u2 ? -1 : 1; // make sort order deterministic/stable } }; @@ -891,14 +896,14 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 soimport = 1024; // safety - unsigned ic; - for (ic = 0; dllnum && im->dllname; ic++, im++) { + for (unsigned ic = 0; ic < dllnum; ic++) { + const import_desc *const im = im_start + ic; idlls[ic] = dlls + ic; dlls[ic].name = ibuf.subref("bad dllname %#x", im->dllname, 1); dlls[ic].shname = nullptr; dlls[ic].ordinal = 0; dlls[ic].iat = im->iat; - unsigned const skip2 = (im->oft ? im->oft : im->iat); + const unsigned skip2 = (im->oft ? im->oft : im->iat); dlls[ic].lookupt = (LEXX *) ibuf.subref("bad dll lookupt %#x", skip2, sizeof(LEXX)); dlls[ic].original_position = ic; dlls[ic].isk32 = strcasecmp(kernelDll(), dlls[ic].name) == 0; @@ -912,11 +917,11 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 dlls[ic].ordinal = *tarr & 0xffff; } else { // it's an import by name - IPTR_VAR(const byte, const name, ibuf + *tarr + 2); + IPTR_VAR(const 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; + dlls[ic].shname = ibuf + (*tarr + 2); } soimport++; // separator } @@ -928,7 +933,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 qsort(idlls, dllnum, sizeof(*idlls), udll::compare); info("Processing imports: %d DLLs", dllnum); - for (ic = 0; ic < dllnum; ic++) { + for (unsigned ic = 0; ic < dllnum; ic++) { info(" DLL %3d %s %s", ic, idlls[ic]->name, idlls[ic]->shname); } @@ -936,7 +941,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 // create the new import table addStubImports(); - for (ic = 0; ic < dllnum; ic++) { + for (unsigned ic = 0; ic < dllnum; ic++) { if (idlls[ic]->isk32) { // for kernel32.dll we need to put all the imported // ordinals into the output import table, as on @@ -944,7 +949,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 if (strcasecmp(idlls[ic]->name, "kernel32.dll")) continue; if (idlls[ic]->ordinal) - for (LEXX *tarr = idlls[ic]->lookupt; *tarr; tarr++) + for (const LEXX *tarr = idlls[ic]->lookupt; *tarr; tarr++) if (*tarr & ord_mask) { ilinker->add(kernelDll(), *tarr & 0xffff); kernel32ordinal = true; @@ -963,8 +968,8 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 // create the preprocessed data SPAN_S_VAR(byte, ppi, oimport); // preprocessed imports - for (ic = 0; ic < dllnum; ic++) { - LEXX *tarr = idlls[ic]->lookupt; + for (unsigned ic = 0; ic < dllnum; ic++) { + const LEXX *tarr = idlls[ic]->lookupt; set_le32(ppi, ilinker->getAddress(idlls[ic]->name)); set_le32(ppi + 4, idlls[ic]->iat - rvamin); ppi += 8; @@ -982,8 +987,8 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 } } else { *ppi++ = 1; - unsigned const skip2 = 2 + *tarr; - unsigned const take2 = 1 + strlen(ibuf.subref("bad import name %#x", skip2, 1)); + const unsigned skip2 = 2 + *tarr; + const unsigned take2 = 1 + strlen(ibuf.subref("bad import name %#x", skip2, 1)); memcpy(ppi, ibuf.subref("bad import name %#x", skip2, take2), take2); ppi += take2; names.add(*tarr, 2 + take2); @@ -993,7 +998,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 unsigned esize = ptr_udiff_bytes(tarr, idlls[ic]->lookupt); lookups.add(idlls[ic]->lookupt, esize); if (ptr_diff_bytes(ibuf.subref("bad import name %#x", idlls[ic]->iat, 1), - (char *) idlls[ic]->lookupt) != 0) { + idlls[ic]->lookupt) != 0) { memcpy(ibuf.subref("bad import name %#x", idlls[ic]->iat, esize), idlls[ic]->lookupt, esize); iats.add(idlls[ic]->iat, esize); @@ -1022,13 +1027,13 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 names.dump(); #endif // do some work for the unpacker - im = im_save; - for (ic = 0; ic < dllnum; ic++, im++) { + for (unsigned ic = 0; ic < dllnum; ic++) { + import_desc *const im = im_start + ic; memset(im, FILLVAL, sizeof(*im)); - im->dllname = ptr_diff_bytes(dlls[idlls[ic]->original_position].name, ibuf); + im->dllname = ptr_udiff_bytes(dlls[idlls[ic]->original_position].name, ibuf); } } else { - iats.add(im_save, sizeof(import_desc) * dllnum); + iats.add(im_start, sizeof(import_desc) * dllnum); // zero unneeded data iats.clear(); lookups.clear(); @@ -1038,7 +1043,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 iats.add(&names); iats.add(&lookups); iats.flatten(); - for (ic = 0; ic < iats.ivnum; ic++) + for (unsigned ic = 0; ic < iats.ivnum; ic++) ilen += iats.ivarr[ic].len; info("Imports: original size: %u bytes, preprocessed size: %u bytes", ilen, soimport); @@ -1063,7 +1068,7 @@ PeFile::Export::~Export() { delete[] functionptrs; delete[] ordinals; if (names) { - unsigned const limit = edir.names + edir.functions; + const unsigned limit = edir.names + edir.functions; for (unsigned ic = 0; ic < limit; ic++) if (names[ic]) free(names[ic]); // allocated by strdup() @@ -1247,12 +1252,11 @@ void PeFile::processTls1(Interval *iv, typename tls_traits::cb_value_t ima if (isefi && IDSIZE(PEDIR_TLS)) throwCantPack("TLS not supported on EFI"); - unsigned const take = ALIGN_UP(IDSIZE(PEDIR_TLS), 4u); + const unsigned take = ALIGN_UP(IDSIZE(PEDIR_TLS), 4u); sotls = take; if (!sotls) return; - - unsigned const skip = IDADDR(PEDIR_TLS); + const unsigned skip = IDADDR(PEDIR_TLS); const tls *const tlsp = (const tls *) ibuf.subref("bad tls %#x", skip, sizeof(tls)); // note: TLS callbacks are not implemented in Windows 95/98/ME @@ -1286,8 +1290,8 @@ void PeFile::processTls1(Interval *iv, typename tls_traits::cb_value_t ima const unsigned tlsdataend = tlsp->dataend - imagebase; // now some ugly stuff: find the relocation entries in the tls data area - unsigned const take2 = IDSIZE(PEDIR_RELOC); - unsigned const skip2 = IDADDR(PEDIR_RELOC); + const unsigned skip2 = IDADDR(PEDIR_RELOC); + const unsigned take2 = IDSIZE(PEDIR_RELOC); Reloc rel(ibuf.subref("bad tls reloc %#x", skip2, take2), take2); unsigned pos, type; while (rel.next(pos, type)) @@ -1305,11 +1309,11 @@ void PeFile::processTls1(Interval *iv, typename tls_traits::cb_value_t ima mb_otls.alloc(aligned_sotls); mb_otls.clear(); otls = mb_otls; // => otls now is a SPAN_S - unsigned const take1 = sizeof(tls); - unsigned const skip1 = IDADDR(PEDIR_TLS); + const unsigned skip1 = IDADDR(PEDIR_TLS); + const unsigned take1 = sizeof(tls); memcpy(otls, ibuf.subref("bad tls %#x", skip1, take1), take1); // WARNING: this can access data in BSS - unsigned const take3 = sotls - sizeof(tls); + const unsigned take3 = sotls - sizeof(tls); memcpy(otls + sizeof(tls), ibuf.subref("bad tls %#x", tlsdatastart, take3), take3); tlsindex = tlsp->tlsindex - imagebase; // NEW: subtract two dwords if TLS callbacks are used - Stefan Widmann @@ -1392,14 +1396,14 @@ void PeFile::processLoadConf(Interval *iv) // pass 1 soloadconf = get_le32(loadconf); if (soloadconf == 0) return; - static unsigned const MAX_SOLOADCONF = 256; // XXX FIXME: Why? + static const unsigned MAX_SOLOADCONF = 256; // XXX FIXME: Why? if (soloadconf > MAX_SOLOADCONF) info("Load Configuration directory %u > %u", soloadconf, MAX_SOLOADCONF); // if there were relocation entries referring to the load config table // then we need them for the copy of the table too - unsigned const take = IDSIZE(PEDIR_RELOC); - unsigned const skip = IDADDR(PEDIR_RELOC); + const unsigned skip = IDADDR(PEDIR_RELOC); + const unsigned take = IDSIZE(PEDIR_RELOC); Reloc rel(ibuf.subref("bad reloc %#x", skip, take), take); unsigned pos, type; while (rel.next(pos, type)) @@ -1876,7 +1880,7 @@ void PeFile::processResources(Resource *res) { set_le32(ores, res->offs()); // save original offset ores += 4; - unsigned const take = res->size(); + const unsigned take = res->size(); ICHECK(ibuf + res->offs(), take); memcpy(ores, ibuf.subref("bad resoff %#x", res->offs(), take), take); ibuf.fill(res->offs(), take, FILLVAL); @@ -1944,8 +1948,8 @@ unsigned PeFile::stripDebug(unsigned overlaystart) { COMPILE_TIME_ASSERT(sizeof(((debug_dir_t *) nullptr)->_) == 16) COMPILE_TIME_ASSERT(sizeof(((debug_dir_t *) nullptr)->__) == 4) - unsigned const take = IDSIZE(PEDIR_DEBUG); - unsigned const skip = IDADDR(PEDIR_DEBUG); + const unsigned skip = IDADDR(PEDIR_DEBUG); + const unsigned take = IDSIZE(PEDIR_DEBUG); const debug_dir_t *dd = (const debug_dir_t *) ibuf.subref("bad debug %#x", skip, take); for (unsigned ic = 0; ic < IDSIZE(PEDIR_DEBUG) / sizeof(debug_dir_t); ic++, dd++) if (overlaystart == dd->fpos) @@ -1971,7 +1975,7 @@ void PeFile::readSectionHeaders(unsigned objs, unsigned sizeof_ih) { fi->seek(pe_offset + sizeof_ih, SEEK_SET); fi->readx(isection, sizeof(pe_section_t) * objs); rvamin = isection[0].vaddr; - unsigned const rvalast = isection[-1 + objs].vsize + isection[-1 + objs].vaddr; + const unsigned rvalast = isection[-1 + objs].vsize + isection[-1 + objs].vaddr; for (unsigned j = 0; j < objs; ++j) { // expect: first is min, last is max unsigned lo = isection[j].vaddr, hi = isection[j].vsize + lo; if (hi < lo) { // this checks first and last sections, too! @@ -2649,11 +2653,12 @@ void PeFile::rebuildTls() { namespace { template -struct VPtr { +struct VPtr { // "virtual pointer" pointing before a buffer static_assert(sizeof(T) == 1); - SPAN_S(T) ptr; - size_t vaddr; - auto operator+(size_t n) const { return ptr + mem_size(sizeof(T), n - vaddr); } + SPAN_S(T) base; + size_t x; + // return base + (n - x) + auto operator+(size_t n) const { return base + mem_size_get_n(sizeof(T), n - x); } }; } // namespace @@ -2726,20 +2731,10 @@ void PeFile::rebuildImports(SPAN_S(byte) & extra_info, ord_mask_t ord_mask, bool // INFO: use VPtr for "virtual pointer" pointing before a buffer //// byte *const Obuf = obuf.raw_bytes(0) - rvamin; VPtr const Obuf{obuf, rvamin}; -#if 0 - import_desc * const im0 = (import_desc*) (Obuf + ODADDR(PEDIR_IMPORT)); - import_desc *im = im0; - byte *dllnames = Obuf + inamespos; - byte *importednames = dllnames + sdllnames; - byte * const importednames_start = importednames; -#else - SPAN_S_VAR(import_desc, const im0, (import_desc *) raw_bytes(Obuf + ODADDR(PEDIR_IMPORT), 0), - obuf); - SPAN_S_VAR(import_desc, im, im0); + SPAN_S_VAR(import_desc, im, (import_desc *) raw_bytes(Obuf + ODADDR(PEDIR_IMPORT), 0), obuf); SPAN_0_VAR(byte, dllnames, inamespos ? raw_bytes(Obuf + inamespos, 0) : nullptr, obuf); - SPAN_0_VAR(byte, importednames, inamespos ? dllnames + sdllnames : nullptr); - SPAN_0_VAR(byte, const importednames_start, importednames); -#endif + SPAN_0_VAR(byte, const importednames_start, inamespos ? dllnames + sdllnames : nullptr); + SPAN_0_VAR(byte, importednames, importednames_start); for (p = imdata; get_le32(p) != 0; ++p) { // restore the name of the dll diff --git a/src/pefile.h b/src/pefile.h index 1655a500..06487cf3 100644 --- a/src/pefile.h +++ b/src/pefile.h @@ -184,7 +184,7 @@ protected: struct alignas(1) import_desc { LE32 oft; // orig first thunk - char _[8]; + byte _[8]; LE32 dllname; LE32 iat; // import address table }; @@ -195,7 +195,7 @@ protected: LE32 vaddr; LE32 size; LE32 rawdataptr; - char _[12]; + byte _[12]; LE32 flags; }; @@ -433,9 +433,9 @@ protected: class Export : private noncopyable { struct alignas(1) export_dir_t { - char _[12]; // flags, timedate, version + byte _[12]; // flags, timedate, version LE32 name; - char __[4]; // ordinal base + byte __[4]; // ordinal base LE32 functions; LE32 names; LE32 addrtable; @@ -483,16 +483,16 @@ protected: struct alignas(1) pe_header_t { // 0x00 - char _[4]; // pemagic + byte _[4]; // pemagic // 0x04 IMAGE_FILE_HEADER LE16 cpu; // IMAGE_FILE_MACHINE_xxx LE16 objects; // NumberOfSections - char __[12]; // timestamp + reserved + byte __[12]; // timestamp + reserved LE16 opthdrsize; // SizeOfOptionalHeader LE16 flags; // Characteristics // 0x18 IMAGE_OPTIONAL_HEADER32 LE16 coffmagic; // NEW: Stefan Widmann - char ___[2]; // linkerversion + byte ___[2]; // linkerversion LE32 codesize; // 0x20 LE32 datasize; @@ -506,7 +506,7 @@ protected: LE32 objectalign; LE32 filealign; // should set to 0x200 ? // 0x40 - char ____[16]; // versions + byte ____[16]; // versions // 0x50 LE32 imagesize; LE32 headersize; @@ -514,7 +514,7 @@ protected: LE16 subsystem; // IMAGE_SUBSYSTEM_xxx LE16 dllflags; // IMAGE_DLLCHARACTERISTICS_xxx // 0x60 - char _____[20]; // stack + heap sizes + byte _____[20]; // stack + heap sizes // 0x74 LE32 ddirsentries; // usually 16 // 0x78 @@ -544,16 +544,16 @@ protected: struct alignas(1) pe_header_t { // 0x00 - char _[4]; // pemagic + byte _[4]; // pemagic // 0x04 IMAGE_FILE_HEADER LE16 cpu; // IMAGE_FILE_MACHINE_xxx LE16 objects; // NumberOfSections - char __[12]; // timestamp + reserved + byte __[12]; // timestamp + reserved LE16 opthdrsize; // SizeOfOptionalHeader LE16 flags; // Characteristics // 0x18 IMAGE_OPTIONAL_HEADER64 LE16 coffmagic; // NEW: Stefan Widmann - char ___[2]; // linkerversion + byte ___[2]; // linkerversion LE32 codesize; // 0x20 LE32 datasize; @@ -567,7 +567,7 @@ protected: LE32 objectalign; LE32 filealign; // should set to 0x200 ? // 0x40 - char ____[16]; // versions + byte ____[16]; // versions // 0x50 LE32 imagesize; LE32 headersize; @@ -575,7 +575,7 @@ protected: LE16 subsystem; // IMAGE_SUBSYSTEM_xxx LE16 dllflags; // IMAGE_DLLCHARACTERISTICS_xxx // 0x60 - char _____[36]; // stack + heap sizes + loader flag + byte _____[36]; // stack + heap sizes + loader flag // 0x84 LE32 ddirsentries; // usually 16 // 0x88 diff --git a/src/stub/src/i386-dos32.djgpp2-stubify.asm b/src/stub/src/i386-dos32.djgpp2-stubify.asm index 3557f1d9..0dbc5e13 100644 --- a/src/stub/src/i386-dos32.djgpp2-stubify.asm +++ b/src/stub/src/i386-dos32.djgpp2-stubify.asm @@ -46,7 +46,7 @@ ; Revision history: ; ; 93/12/05 DJ Delorie Initial version v2.00, requires DPMI 0.9 -; 94/10/13 CW Sandmann v2.01, accumlated changes: 60K load bug, limits, cwsdpmi, optimization +; 94/10/13 CW Sandmann v2.01, accumulated changes: 60K load bug, limits, cwsdpmi, optimization ; 94/10/29 CW Sandmann v2.03, M Welinder changes; cwsdpmi load anywhere, size decrease ; .copyright "The STUB.EXE stub loader is Copyright (C) 1993-1995 DJ Delorie. " diff --git a/src/util/util.cpp b/src/util/util.cpp index 9e295e20..491fc12a 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -25,8 +25,9 @@ */ +#include "../headers.h" +#include #include "../conf.h" -#include "util.h" #define ACC_WANT_ACC_INCI_H 1 #include "../miniacc.h" @@ -173,6 +174,7 @@ void uintptr_check_no_overlap(upx_uintptr_t a, size_t a_size, upx_uintptr_t b, s throwCantPack("ptr_check_no_overlap-bc"); } +#if DEBUG TEST_CASE("ptr_check_no_overlap 2") { byte p[4] = {}; @@ -243,6 +245,7 @@ TEST_CASE("ptr_check_no_overlap 3") { check_throws_(0, 4, 3, 0, 1, 0); check_throws_(0, 4, 4, 0, 1, 0); } +#endif // DEBUG /************************************************************************* // bele.h @@ -270,31 +273,34 @@ void *upx_calloc(size_t n, size_t element_size) { return p; } -// extremely simple stable sort: Gnomesort -// WARNING: O(n**2) !!!!! -void upx_stable_sort(void *base, size_t n, size_t element_size, - int(__acc_cdecl_qsort *compare)(const void *, const void *)) { - (void) mem_size(element_size, n); // assert size - for (size_t i = 1; i < n;) { - char *a = (char *) base + element_size * i; // a = &array[i] - if (i == 0 || (compare(a - element_size, a) <= 0)) { - i += 1; - } else { - i -= 1; - // swap elements a[-1] <=> a[0] - // upx_memswap(a - element_size, a, element_size); - size_t j = element_size; - do { - char tmp = *(a - element_size); - *(a - element_size) = *a; - *a++ = tmp; - } while (--j != 0); +// simple unoptimized memswap() +void upx_memswap(void *a, void *b, size_t n) { + if (a != b && n != 0) { + char *x = (char *) a; + char *y = (char *) b; + do { + char tmp = *x; + *x++ = *y; + *y++ = tmp; + } while (--n != 0); + } +} + +// extremely simple (and beautiful) stable sort: Gnomesort +// WARNING: O(n^2) and thus very inefficient for large n +void upx_stable_sort(void *array, size_t n, size_t element_size, + int (*compare)(const void *, const void *)) { + for (size_t i = 1; i < n; i++) { + char *a = (char *) array + element_size * i; // a = &array[i] + if (i != 0 && compare(a - element_size, a) > 0) { + upx_memswap(a - element_size, a, element_size); // swap elements a[-1] <=> a[0] + i -= 2; } } } +#if DEBUG TEST_CASE("upx_stable_sort") { - // TODO C++20: use std::next_permutation() to test all permutations { unsigned a[] = {0, 1}; upx_stable_sort(a, 2, sizeof(*a), ne32_compare); @@ -310,7 +316,19 @@ TEST_CASE("upx_stable_sort") { upx_stable_sort(a, 3, sizeof(*a), ne32_compare); CHECK((a[0] == 0 && a[1] == 1 && a[2] == 2)); } +#if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations + { + upx_uint16_t perm[5] = {0, 1, 2, 3, 4}; // 120 permutations + do { + upx_uint16_t a[5] = {}; + memcpy(a, perm, sizeof(perm)); + upx_stable_sort(a, 5, sizeof(*a), ne16_compare); + CHECK((a[0] == 0 && a[1] == 1 && a[2] == 2 && a[3] == 3 && a[4] == 4)); + } while (std::next_permutation(perm, perm + 5)); + } +#endif } +#endif // DEBUG /************************************************************************* // qsort() util diff --git a/src/util/util.h b/src/util/util.h index 81433f16..ef9a484e 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -133,8 +133,10 @@ forceinline void ptr_check_no_overlap(const void *a, size_t a_size, const void * void *upx_calloc(size_t n, size_t element_size); -void upx_stable_sort(void *base, size_t n, size_t element_size, - int(__acc_cdecl_qsort *compare)(const void *, const void *)); +void upx_memswap(void *a, void *b, size_t n); + +void upx_stable_sort(void *array, size_t n, size_t element_size, + int (*compare)(const void *, const void *)); /************************************************************************* // misc. support functions