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:
commit
f68ac8155b
11
.github/CODEOWNERS
vendored
Normal file
11
.github/CODEOWNERS
vendored
Normal 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
|
1
.github/typos_config.toml
vendored
1
.github/typos_config.toml
vendored
|
@ -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"
|
||||
|
|
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -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 }}
|
||||
|
|
9
.github/workflows/minimal-ci.yml
vendored
9
.github/workflows/minimal-ci.yml
vendored
|
@ -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 }}
|
||||
|
|
20
.github/workflows/scan-build.yml
vendored
20
.github/workflows/scan-build.yml
vendored
|
@ -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'
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
/*************************************************************************
|
||||
|
|
102
src/conf.h
102
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 <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: */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
116
src/headers.h
Normal 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: */
|
26
src/lefile.h
26
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "headers.h"
|
||||
#include <typeinfo>
|
||||
#include "conf.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];
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 ...
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
157
src/pefile.cpp
157
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))
|
||||
return (u1->shname != nullptr) ? -1 : 1;
|
||||
if (u1->shname && u2->shname) {
|
||||
rc = (int) (upx_safe_strlen(u1->shname) - upx_safe_strlen(u2->shname));
|
||||
if (rc)
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
return strcmp(u1->shname, u2->shname);
|
||||
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;
|
||||
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
|
||||
|
|
28
src/pefile.h
28
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
|
||||
|
|
|
@ -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. "
|
||||
|
|
|
@ -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;
|
||||
// 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 = *(a - element_size);
|
||||
*(a - element_size) = *a;
|
||||
*a++ = tmp;
|
||||
} while (--j != 0);
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user