1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

Merge branch 'devel' into devel4

This commit is contained in:
Markus F.X.J. Oberhumer 2023-03-18 21:52:17 +01:00
commit f68ac8155b
28 changed files with 351 additions and 287 deletions

11
.github/CODEOWNERS vendored Normal file
View File

@ -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

View File

@ -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"

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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'

View File

@ -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")

View File

@ -683,6 +683,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;
@ -690,6 +693,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
/*************************************************************************

View File

@ -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 <intrin.h>
#endif
// C++ system headers
#include <exception>
#include <new>
#include <type_traits>
#include <typeinfo>
// 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 <atomic>
#define upx_std_atomic(Type) std::atomic<Type>
#include <mutex>
#define upx_std_once_flag std::once_flag
#define upx_std_call_once std::call_once
#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 <doctest/doctest/parts/doctest_fwd.h>
#if WITH_BOOST_PFR
# include <sstream>
# include <boost/pfr/io.hpp>
#endif
#if WITH_RANGELESS_FN
# include <rangeless/include/fn.hpp>
#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 <valgrind/include/valgrind/memcheck.h>
#endif
// IMPORTANT: unconditionally enable assertions
#undef NDEBUG
#include <assert.h>
// <type_traits> C++20 std::is_bounded_array
template <class T>
struct upx_std_is_bounded_array : public std::false_type {};
@ -195,7 +110,6 @@ inline constexpr bool upx_is_integral_v = upx_is_integral<T>::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 <windows.h>"
# endif
#endif
#endif /* already included */
/* vim:set ts=4 sw=4 et: */

View File

@ -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));

View File

@ -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;

View File

@ -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;
}

116
src/headers.h Normal file
View File

@ -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
<markus@oberhumer.com>
*/
#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 <intrin.h>
#endif
// C++ system headers
#include <exception>
#include <new>
#include <type_traits>
// 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 <atomic>
#include <mutex>
#endif
// C++ submodule headers
#include <doctest/doctest/parts/doctest_fwd.h>
#if WITH_BOOST_PFR
#include <sstream>
#include <boost/pfr/io.hpp>
#endif
#if WITH_RANGELESS_FN
#include <rangeless/include/fn.hpp>
#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 <valgrind/include/valgrind/memcheck.h>
#endif
// IMPORTANT: unconditionally enable assertions
#undef NDEBUG
#include <assert.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 <windows.h>"
#endif
#endif
/* vim:set ts=4 sw=4 et: */

View File

@ -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

View File

@ -406,8 +406,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;
}

View File

@ -25,6 +25,8 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
#include "headers.h"
#include <typeinfo>
#include "conf.h"
/*************************************************************************

View File

@ -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];

View File

@ -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;
};

View File

@ -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 ...
};

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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<LEXX>::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<LEXX>::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<LEXX>::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 <class T>
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<byte> 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

View File

@ -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

View File

@ -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. "

View File

@ -25,8 +25,9 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
#include "../headers.h"
#include <algorithm>
#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

View File

@ -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