mirror of
https://github.com/upx/upx.git
synced 2024-11-23 04:39:59 +00:00
src: introduce upx::atomic_exchange; cleanups
This commit is contained in:
parent
e5546bc8b0
commit
3d82f0cfe1
8
Makefile
8
Makefile
@ -59,10 +59,10 @@ CTEST = ctest
|
||||
CTEST_JOBS ?= 8
|
||||
CTEST_FLAGS = --output-on-failure --parallel $(CTEST_JOBS)
|
||||
|
||||
build/debug+test: $$(dir $$@)debug PHONY; cd "$(dir $@)debug" && $(CTEST) -C Debug $(CTEST_FLAGS)
|
||||
build/%/debug+test: $$(dir $$@)debug PHONY; cd "$(dir $@)debug" && $(CTEST) -C Debug $(CTEST_FLAGS)
|
||||
build/release+test: $$(dir $$@)release PHONY; cd "$(dir $@)release" && $(CTEST) -C Release $(CTEST_FLAGS)
|
||||
build/%/release+test: $$(dir $$@)release PHONY; cd "$(dir $@)release" && $(CTEST) -C Release $(CTEST_FLAGS)
|
||||
build/debug+test: $$(dir $$@)debug PHONY; cd "$(dir $@)debug" && $(CTEST) $(CTEST_FLAGS) -C Debug
|
||||
build/%/debug+test: $$(dir $$@)debug PHONY; cd "$(dir $@)debug" && $(CTEST) $(CTEST_FLAGS) -C Debug
|
||||
build/release+test: $$(dir $$@)release PHONY; cd "$(dir $@)release" && $(CTEST) $(CTEST_FLAGS) -C Release
|
||||
build/%/release+test: $$(dir $$@)release PHONY; cd "$(dir $@)release" && $(CTEST) $(CTEST_FLAGS) -C Release
|
||||
build/%/all+test: $$(dir $$@)debug+test $$(dir $$@)release+test PHONY ;
|
||||
|
||||
# shortcuts
|
||||
|
@ -24,7 +24,7 @@ upx_print_var(CMAKE_APPLE_SILICON_PROCESSOR CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OS
|
||||
upx_print_Var(CMAKE_CROSSCOMPILING CMAKE_CROSSCOMPILING_EMULATOR)
|
||||
|
||||
# binutils
|
||||
upx_print_var(CMAKE_AR CMAKE_OBJCOPY CMAKE_RANLIB)
|
||||
upx_print_var(CMAKE_AR CMAKE_RANLIB)
|
||||
|
||||
# compilers
|
||||
foreach(lang IN ITEMS ASM C CXX)
|
||||
|
@ -19,7 +19,7 @@ RUN dpkg --add-architecture i386 \
|
||||
libzstd-dev lsb-release lz4 lzip lzop minify mksh moreutils musl neovim ninja-build \
|
||||
p7zip parallel patch patchelf patchutils pax-utils proot \
|
||||
python3 python3-pyasn1 python3-pycryptodome python3-pycurl python3-toml python3-yaml python3-zstd \
|
||||
re2c ripgrep rsync screen universal-ctags unzip yash yq \
|
||||
re2c ripgrep rsync screen strace universal-ctags unzip valgrind yash yq \
|
||||
zip zlib1g-dev zoxide zsh zstd \
|
||||
# extra packages for compiling with "gcc -m32" and "gcc -mx32":
|
||||
g++-multilib gcc-multilib \
|
||||
@ -83,8 +83,11 @@ RUN useradd upx -U --uid 2000 --shell /bin/bash -m \
|
||||
&& echo "alias rd=rmdir" >> .bashrc \
|
||||
&& echo 'mdd() { mkdir "$1" && cd "$1"; }' >> .bashrc \
|
||||
&& echo 'm() { make "$@"; }' >> .bashrc \
|
||||
&& echo 'tn() { time nice "$@"; }' >> .bashrc \
|
||||
&& echo 'tnm() { time nice make "$@"; }' >> .bashrc \
|
||||
&& echo 'tnmm() { time nice make -j "$@"; }' >> .bashrc \
|
||||
&& echo 'source /usr/share/bash-completion/completions/make' >> .bashrc \
|
||||
&& echo 'complete -F _make m' >> .bashrc \
|
||||
&& echo 'complete -F _make m tnm tnmm' >> .bashrc \
|
||||
&& echo 'eval "$(zoxide init bash)"' >> .bashrc \
|
||||
&& echo "alias zz=zi\nalias y=z\nalias yy=zi" >> .bashrc \
|
||||
&& echo "alias cd..='cd ..'" >> .bashrc \
|
||||
|
10
misc/podman/rebuild-stubs/packages.txt
generated
10
misc/podman/rebuild-stubs/packages.txt
generated
@ -109,6 +109,7 @@ ii libbz2-1.0:amd64 1.0.8-5.1 amd64
|
||||
ii libbzip3-0:amd64 1.4.0-1 amd64 better, faster and stronger spiritual successor to bzip2 - runtime
|
||||
ii libc-bin 2.39-0ubuntu8.1 amd64 GNU C Library: Binaries
|
||||
ii libc-dev-bin 2.39-0ubuntu8.1 amd64 GNU C Library: Development binaries
|
||||
ii libc6-dbg:amd64 2.39-0ubuntu8.1 amd64 GNU C Library: detached debugging symbols
|
||||
ii libc6-dev-i386 2.39-0ubuntu8.1 amd64 GNU C Library: 32-bit development libraries for AMD64
|
||||
ii libc6-dev-x32 2.39-0ubuntu8.1 amd64 GNU C Library: X32 ABI Development Libraries for AMD64
|
||||
ii libc6-dev:amd64 2.39-0ubuntu8.1 amd64 GNU C Library: Development Libraries and Header Files
|
||||
@ -246,6 +247,7 @@ ii libuchardet0:amd64 0.0.8-1build1 amd64
|
||||
ii libudev1:amd64 255.4-1ubuntu8 amd64 libudev shared library
|
||||
ii libunibilium4:amd64 2.1.0-3 amd64 simple, self-contained terminfo library
|
||||
ii libunistring5:amd64 1.1-2build1 amd64 Unicode string library for C
|
||||
ii libunwind8:amd64 1.6.2-3build1 amd64 library to determine the call-chain of a program - runtime
|
||||
ii liburing2:amd64 2.5-1build1 amd64 Linux kernel io_uring access library - shared library
|
||||
ii libutempter0:amd64 1.2.1-3build1 amd64 privileged helper for utmp/wtmp updates (runtime)
|
||||
ii libuuid1:amd64 2.39.3-9ubuntu6 amd64 Universally Unique ID library
|
||||
@ -330,6 +332,7 @@ ii rsync 3.2.7-1ubuntu1 amd64
|
||||
ii screen 4.9.1-1build1 amd64 terminal multiplexer with VT100/ANSI terminal emulation
|
||||
ii sed 4.9-2build1 amd64 GNU stream editor for filtering/transforming text
|
||||
ii sensible-utils 0.0.22 all Utilities for sensible alternative selection
|
||||
ii strace 6.8-0ubuntu2 amd64 System call tracer
|
||||
ii sysstat 12.6.1-2 amd64 system performance tools for Linux
|
||||
ii sysvinit-utils 3.08-6ubuntu3 amd64 System-V-like utilities
|
||||
ii tar 1.35+dfsg-3build1 amd64 GNU version of the tar archiving utility
|
||||
@ -340,6 +343,7 @@ ii ucf 3.0043+nmu1 all
|
||||
ii universal-ctags 5.9.20210829.0-1 amd64 build tag file indexes of source code definitions
|
||||
ii unzip 6.0-28ubuntu4 amd64 De-archiver for .zip files
|
||||
ii util-linux 2.39.3-9ubuntu6 amd64 miscellaneous system utilities
|
||||
ii valgrind 1:3.22.0-0ubuntu3 amd64 instrumentation framework for building dynamic analysis tools
|
||||
ii wget 1.21.4-1ubuntu4 amd64 retrieves files from the web
|
||||
ii xz-utils 5.6.1+really5.4.5-1 amd64 XZ-format compression utilities
|
||||
ii yash 2.55-2 amd64 yet another shell
|
||||
@ -357,7 +361,8 @@ ii zstd 1.5.5+dfsg2-2build1 amd64
|
||||
||/ Name Version Architecture Description
|
||||
|
||||
Packages sorted by Installed-Size:
|
||||
874252 ===== TOTAL (351 packages)
|
||||
964659 ===== TOTAL (355 packages)
|
||||
76943 valgrind amd64
|
||||
72249 gcc-13-x86-64-linux-gnu amd64
|
||||
37841 g++-13-x86-64-linux-gnu amd64
|
||||
36493 cmake amd64
|
||||
@ -378,6 +383,7 @@ Packages sorted by Installed-Size:
|
||||
12003 libc6-x32 amd64
|
||||
11992 libc6-i386 amd64
|
||||
11569 binutils-x86-64-linux-gnu amd64
|
||||
11174 libc6-dbg amd64
|
||||
10984 cmake-data all
|
||||
10764 libasan8 amd64
|
||||
9665 libx32asan8 amd64
|
||||
@ -438,6 +444,7 @@ Packages sorted by Installed-Size:
|
||||
2191 ht amd64
|
||||
2182 libc-bin amd64
|
||||
2161 git-man all
|
||||
2103 strace amd64
|
||||
2078 libxml2 amd64
|
||||
2032 libisl23 amd64
|
||||
2009 universal-ctags amd64
|
||||
@ -586,6 +593,7 @@ Packages sorted by Installed-Size:
|
||||
197 libgcc-s1 amd64
|
||||
196 libxcb1 amd64
|
||||
196 libelf1t64 amd64
|
||||
187 libunwind8 amd64
|
||||
187 dash amd64
|
||||
185 libgpg-error0 amd64
|
||||
184 libx32gcc-s1 amd64
|
||||
|
@ -66,13 +66,14 @@ set_cmake_bool_vars() {
|
||||
}
|
||||
|
||||
set -x
|
||||
if [[ "${emu[0]}" == *valgrind* ]]; then true; # valgrind is SLOW
|
||||
[[ -n $UPX_CONFIG_DISABLE_EXHAUSTIVE_TESTS ]] || UPX_CONFIG_DISABLE_EXHAUSTIVE_TESTS=ON
|
||||
fi
|
||||
set_cmake_bool_vars OFF UPX_CONFIG_DISABLE_SELF_PACK_TEST
|
||||
set_cmake_bool_vars OFF UPX_CONFIG_DISABLE_EXHAUSTIVE_TESTS
|
||||
set_cmake_bool_vars OFF UPX_CONFIG_DISABLE_RUN_UNPACKED_TEST
|
||||
set_cmake_bool_vars OFF UPX_CONFIG_DISABLE_RUN_PACKED_TEST
|
||||
if [[ "${emu[0]}" == *valgrind* ]]; then # valgrind is SLOW
|
||||
set_cmake_bool_vars ON UPX_CONFIG_DISABLE_EXHAUSTIVE_TESTS
|
||||
else
|
||||
set_cmake_bool_vars OFF UPX_CONFIG_DISABLE_EXHAUSTIVE_TESTS
|
||||
fi
|
||||
|
||||
export UPX="--prefer-ucl --no-color --no-progress"
|
||||
export UPX_DEBUG_DISABLE_GITREV_WARNING=1
|
||||
|
@ -250,39 +250,85 @@ struct Z2_X2 : public X2 {
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("upx::atomic_exchange") {
|
||||
{
|
||||
upx_int8_t x = -1;
|
||||
upx_int8_t y = upx::atomic_exchange(&x, (upx_int8_t) 2);
|
||||
CHECK_EQ(x, 2);
|
||||
CHECK_EQ(y, -1);
|
||||
}
|
||||
{
|
||||
upx_int16_t x = -1;
|
||||
upx_int16_t y = upx::atomic_exchange(&x, (upx_int16_t) 2);
|
||||
CHECK_EQ(x, 2);
|
||||
CHECK_EQ(y, -1);
|
||||
}
|
||||
{
|
||||
upx_int32_t x = -1;
|
||||
upx_int32_t y = upx::atomic_exchange(&x, (upx_int32_t) 2);
|
||||
CHECK_EQ(x, 2);
|
||||
CHECK_EQ(y, -1);
|
||||
}
|
||||
{
|
||||
size_t x = (size_t) 0 - 1;
|
||||
size_t y = upx::atomic_exchange(&x, (size_t) 2);
|
||||
CHECK_EQ(x, 2);
|
||||
CHECK_EQ(y, (size_t) 0 - 1);
|
||||
}
|
||||
{
|
||||
int dummy = -1;
|
||||
int *x = &dummy;
|
||||
int *y = upx::atomic_exchange(&x, (int *) nullptr);
|
||||
CHECK_EQ(x, nullptr);
|
||||
CHECK_EQ(y, &dummy);
|
||||
CHECK_EQ(dummy, -1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("upx::ObjectDeleter 1") {
|
||||
LE16 *o = nullptr; // object
|
||||
LE32 *a = nullptr; // array
|
||||
LE64 *m = nullptr; // malloc
|
||||
{
|
||||
upx::ObjectDeleter<LE16 **> o_deleter{&o, 1};
|
||||
auto o_deleter = upx::ObjectDeleter(&o, 1);
|
||||
o = new LE16;
|
||||
assert(o != nullptr);
|
||||
upx::ArrayDeleter<LE32 **> a_deleter{&a, 1};
|
||||
auto a_deleter = upx::ArrayDeleter(&a, 1);
|
||||
a = New(LE32, 1);
|
||||
assert(a != nullptr);
|
||||
auto m_deleter = upx::MallocDeleter(&m, 1);
|
||||
m = (LE64 *) ::malloc(sizeof(LE64));
|
||||
assert(m != nullptr);
|
||||
}
|
||||
assert(o == nullptr);
|
||||
assert(a == nullptr);
|
||||
assert(m == nullptr);
|
||||
// test "const" versions
|
||||
{
|
||||
const upx::ObjectDeleter<LE16 **const> o_deleter{&o, 1};
|
||||
const auto o_deleter = upx::ObjectDeleter(&o, 1);
|
||||
o = new LE16;
|
||||
assert(o != nullptr);
|
||||
const upx::ArrayDeleter<LE32 **const> a_deleter{&a, 1};
|
||||
const auto a_deleter = upx::ArrayDeleter(&a, 1);
|
||||
a = New(LE32, 1);
|
||||
assert(a != nullptr);
|
||||
const auto m_deleter = upx::MallocDeleter(&m, 1);
|
||||
m = (LE64 *) ::malloc(sizeof(LE64));
|
||||
assert(m != nullptr);
|
||||
}
|
||||
assert(o == nullptr);
|
||||
assert(a == nullptr);
|
||||
assert(m == nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("upx::ObjectDeleter 2") {
|
||||
constexpr size_t N = 2;
|
||||
BE16 *o[N]; // multiple objects
|
||||
BE32 *a[N]; // multiple arrays
|
||||
BE64 *m[N]; // multiple mallocs
|
||||
{
|
||||
upx::ObjectDeleter<BE16 **> o_deleter{o, 0};
|
||||
upx::ArrayDeleter<BE32 **> a_deleter{a, 0};
|
||||
auto o_deleter = upx::ObjectDeleter(o, 0);
|
||||
auto a_deleter = upx::ArrayDeleter(a, 0);
|
||||
auto m_deleter = upx::MallocDeleter(m, 0);
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
o[i] = new BE16;
|
||||
assert(o[i] != nullptr);
|
||||
@ -290,11 +336,15 @@ TEST_CASE("upx::ObjectDeleter 2") {
|
||||
a[i] = New(BE32, 1 + i);
|
||||
assert(a[i] != nullptr);
|
||||
a_deleter.count += 1;
|
||||
m[i] = (BE64 *) ::malloc(sizeof(BE64));
|
||||
assert(m[i] != nullptr);
|
||||
m_deleter.count += 1;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
assert(o[i] == nullptr);
|
||||
assert(a[i] == nullptr);
|
||||
assert(m[i] == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
static unsigned hex(uchar c) { return (c & 0xf) + (c > '9' ? 9 : 0); }
|
||||
|
||||
static bool update_capacity(unsigned size, unsigned *capacity) {
|
||||
static bool grow_capacity(unsigned size, unsigned *capacity) {
|
||||
if (size < *capacity)
|
||||
return false;
|
||||
if (*capacity == 0)
|
||||
@ -41,16 +41,20 @@ static bool update_capacity(unsigned size, unsigned *capacity) {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static noinline T **realloc_array(T **array, size_t capacity) {
|
||||
static T **realloc_array(T **array, size_t capacity) may_throw {
|
||||
assert_noexcept(capacity > 0);
|
||||
// NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
|
||||
void *p = realloc(array, mem_size(sizeof(T *), capacity));
|
||||
assert_noexcept(p != nullptr);
|
||||
return static_cast<T **>(p);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static noinline void free_array(T **array, size_t count) {
|
||||
for (size_t i = 0; i < count; i++)
|
||||
delete array[i];
|
||||
static void free_array(T **array, size_t count) noexcept {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
T *item = upx::atomic_exchange(&array[i], (T *) nullptr);
|
||||
delete item;
|
||||
}
|
||||
::free(array); // NOLINT(bugprone-multi-level-implicit-pointer-conversion)
|
||||
}
|
||||
|
||||
@ -61,11 +65,11 @@ static noinline void free_array(T **array, size_t count) {
|
||||
ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a)
|
||||
: name(nullptr), output(nullptr), size(s), offset(0), p2align(a), next(nullptr) {
|
||||
name = strdup(n);
|
||||
assert(name != nullptr);
|
||||
assert_noexcept(name != nullptr);
|
||||
input = ::malloc(s + 1);
|
||||
assert(input != nullptr);
|
||||
assert_noexcept(input != nullptr);
|
||||
if (s != 0) {
|
||||
assert(i != nullptr);
|
||||
assert_noexcept(i != nullptr);
|
||||
memcpy(input, i, s);
|
||||
}
|
||||
((char *) input)[s] = 0;
|
||||
@ -83,8 +87,8 @@ ElfLinker::Section::~Section() noexcept {
|
||||
ElfLinker::Symbol::Symbol(const char *n, Section *s, upx_uint64_t o)
|
||||
: name(nullptr), section(s), offset(o) {
|
||||
name = strdup(n);
|
||||
assert(name != nullptr);
|
||||
assert(section != nullptr);
|
||||
assert_noexcept(name != nullptr);
|
||||
assert_noexcept(section != nullptr);
|
||||
}
|
||||
|
||||
ElfLinker::Symbol::~Symbol() noexcept { ::free(name); }
|
||||
@ -96,7 +100,7 @@ ElfLinker::Symbol::~Symbol() noexcept { ::free(name); }
|
||||
ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t, const Symbol *v,
|
||||
upx_uint64_t a)
|
||||
: section(s), offset(o), type(t), value(v), add(a) {
|
||||
assert(section != nullptr);
|
||||
assert_noexcept(section != nullptr);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@ -150,7 +154,7 @@ void ElfLinker::init(const void *pdata_v, int plen, unsigned pxtra) {
|
||||
input[inputlen] = 0; // NUL terminate
|
||||
|
||||
output_capacity = (inputlen ? (inputlen + pxtra) : 0x4000);
|
||||
assert(output_capacity <= (1 << 16)); // LE16 l_info.l_size
|
||||
assert(output_capacity < (1 << 16)); // LE16 l_info.l_size
|
||||
output = New(byte, output_capacity);
|
||||
outputlen = 0;
|
||||
NO_printf("\nElfLinker::init %d @%p\n", output_capacity, output);
|
||||
@ -180,8 +184,9 @@ void ElfLinker::init(const void *pdata_v, int plen, unsigned pxtra) {
|
||||
}
|
||||
|
||||
void ElfLinker::preprocessSections(char *start, char const *end) {
|
||||
assert_noexcept(nsections == 0);
|
||||
char *nextl;
|
||||
for (nsections = 0; start < end; start = 1 + nextl) {
|
||||
for (; start < end; start = 1 + nextl) {
|
||||
nextl = strchr(start, '\n');
|
||||
assert(nextl != nullptr);
|
||||
*nextl = '\0'; // a record is a line
|
||||
@ -201,8 +206,9 @@ void ElfLinker::preprocessSections(char *start, char const *end) {
|
||||
}
|
||||
|
||||
void ElfLinker::preprocessSymbols(char *start, char const *end) {
|
||||
assert_noexcept(nsymbols == 0);
|
||||
char *nextl;
|
||||
for (nsymbols = 0; start < end; start = 1 + nextl) {
|
||||
for (; start < end; start = 1 + nextl) {
|
||||
nextl = strchr(start, '\n');
|
||||
assert(nextl != nullptr);
|
||||
*nextl = '\0'; // a record is a line
|
||||
@ -237,9 +243,10 @@ void ElfLinker::preprocessSymbols(char *start, char const *end) {
|
||||
}
|
||||
|
||||
void ElfLinker::preprocessRelocations(char *start, char const *end) {
|
||||
assert_noexcept(nrelocations == 0);
|
||||
Section *section = nullptr;
|
||||
char *nextl;
|
||||
for (nrelocations = 0; start < end; start = 1 + nextl) {
|
||||
for (; start < end; start = 1 + nextl) {
|
||||
nextl = strchr(start, '\n');
|
||||
assert(nextl != nullptr);
|
||||
*nextl = '\0'; // a record is a line
|
||||
@ -314,13 +321,11 @@ ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata,
|
||||
NO_printf("addSection: %s len=%d align=%d\n", sname, slen, p2align);
|
||||
if (!sdata && (!strcmp("ABS*", sname) || !strcmp("UND*", sname)))
|
||||
return nullptr;
|
||||
if (update_capacity(nsections, &nsections_capacity))
|
||||
sections = realloc_array(sections, nsections_capacity);
|
||||
assert(sections);
|
||||
assert(sname);
|
||||
assert(sname[0]);
|
||||
assert(sname && sname[0]);
|
||||
assert(sname[strlen(sname) - 1] != ':');
|
||||
assert(findSection(sname, false) == nullptr);
|
||||
if (grow_capacity(nsections, &nsections_capacity))
|
||||
sections = realloc_array(sections, nsections_capacity);
|
||||
Section *sec = new Section(sname, sdata, slen, p2align);
|
||||
sec->sort_id = nsections;
|
||||
sections[nsections++] = sec;
|
||||
@ -330,13 +335,11 @@ ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata,
|
||||
ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section,
|
||||
upx_uint64_t offset) {
|
||||
NO_printf("addSymbol: %s %s 0x%llx\n", name, section, offset);
|
||||
if (update_capacity(nsymbols, &nsymbols_capacity))
|
||||
symbols = realloc_array(symbols, nsymbols_capacity);
|
||||
assert(symbols != nullptr);
|
||||
assert(name);
|
||||
assert(name[0]);
|
||||
assert(name && name[0]);
|
||||
assert(name[strlen(name) - 1] != ':');
|
||||
assert(findSymbol(name, false) == nullptr);
|
||||
if (grow_capacity(nsymbols, &nsymbols_capacity))
|
||||
symbols = realloc_array(symbols, nsymbols_capacity);
|
||||
Symbol *sym = new Symbol(name, findSection(section), offset);
|
||||
symbols[nsymbols++] = sym;
|
||||
return sym;
|
||||
@ -344,9 +347,8 @@ ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section,
|
||||
|
||||
ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off, const char *type,
|
||||
const char *symbol, upx_uint64_t add) {
|
||||
if (update_capacity(nrelocations, &nrelocations_capacity))
|
||||
if (grow_capacity(nrelocations, &nrelocations_capacity))
|
||||
relocations = realloc_array(relocations, nrelocations_capacity);
|
||||
assert(relocations != nullptr);
|
||||
Relocation *rel = new Relocation(findSection(section), off, type, findSymbol(symbol), add);
|
||||
relocations[nrelocations++] = rel;
|
||||
return rel;
|
||||
|
@ -512,7 +512,7 @@ void PeFile32::processRelocs() // pass1
|
||||
infoWarning("skipping unsupported relocation type %d (%d)", ic, counts[ic]);
|
||||
|
||||
LE32 *fix[4];
|
||||
upx::ArrayDeleter<LE32 **const> fix_deleter{fix, 0}; // don't leak memory
|
||||
auto fix_deleter = upx::ArrayDeleter(fix, 0); // don't leak memory
|
||||
for (unsigned ic = 0; ic <= IMAGE_REL_BASED_HIGHLOW; ic++) {
|
||||
fix[ic] = New(LE32, counts[ic]);
|
||||
fix_deleter.count += 1;
|
||||
@ -614,7 +614,7 @@ void PeFile64::processRelocs() // pass1
|
||||
infoWarning("skipping unsupported relocation type %d (%d)", ic, counts[ic]);
|
||||
|
||||
LE32 *fix[16];
|
||||
upx::ArrayDeleter<LE32 **const> fix_deleter{fix, 0}; // don't leak memory
|
||||
auto fix_deleter = upx::ArrayDeleter(fix, 0); // don't leak memory
|
||||
for (unsigned ic = 0; ic < 16; ic++) {
|
||||
fix[ic] = New(LE32, counts[ic]);
|
||||
fix_deleter.count += 1;
|
||||
@ -1926,7 +1926,7 @@ void PeFile::processResources(Resource *res) {
|
||||
SPAN_S_VAR(byte, ores, oresources + res->dirsize());
|
||||
|
||||
char *keep_icons = nullptr; // icon ids in the first icon group
|
||||
upx::ArrayDeleter<char **const> keep_icons_deleter{&keep_icons, 1}; // don't leak memory
|
||||
const auto keep_icons_deleter = upx::ArrayDeleter(&keep_icons, 1); // don't leak memory
|
||||
unsigned iconsin1stdir = 0;
|
||||
if (opt->win32_pe.compress_icons == 2)
|
||||
while (res->next()) // there is no rewind() in Resource
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// #include <atomic>
|
||||
// #include <cstddef>
|
||||
// #include <new>
|
||||
// #include <type_traits>
|
||||
@ -186,37 +187,76 @@ forceinline Result ptr_static_cast(const From *ptr) noexcept {
|
||||
return static_cast<Result>(static_cast<const void *>(ptr));
|
||||
}
|
||||
|
||||
#if WITH_THREADS
|
||||
// cast "T *" to "std::atomic<T> *"
|
||||
template <class T>
|
||||
forceinline std::atomic<T> *ptr_std_atomic_cast(T *ptr) noexcept {
|
||||
// TODO later: make sure that this cast is indeed legal
|
||||
std::atomic<T> *result = ptr_static_cast<std::atomic<T> *>(ptr);
|
||||
static_assert(sizeof(*result) == sizeof(*ptr));
|
||||
static_assert(alignof(*result) == alignof(*ptr));
|
||||
return result;
|
||||
}
|
||||
#endif // WITH_THREADS
|
||||
|
||||
// atomic_exchange
|
||||
template <class T>
|
||||
forceinline T atomic_exchange(T *ptr, T new_value) noexcept {
|
||||
static_assert(std::is_standard_layout_v<T>);
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
#if __has_builtin(__atomic_exchange_n) && defined(__ATOMIC_SEQ_CST)
|
||||
return __atomic_exchange_n(ptr, new_value, __ATOMIC_SEQ_CST);
|
||||
#elif __has_builtin(__sync_swap)
|
||||
return __sync_swap(ptr, new_value);
|
||||
#elif WITH_THREADS
|
||||
return std::atomic_exchange(ptr_std_atomic_cast(ptr), new_value);
|
||||
#else
|
||||
T old_value = *ptr;
|
||||
*ptr = new_value;
|
||||
return old_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
// helper classes so we don't leak memory on exceptions
|
||||
template <class T> // T is "SomeType **"
|
||||
template <class T>
|
||||
struct ObjectDeleter final {
|
||||
static_assert(std::is_pointer_v<T>);
|
||||
static_assert(std::is_pointer_v<std::remove_pointer_t<T> >);
|
||||
T items; // public
|
||||
size_t count; // public
|
||||
T **items; // public
|
||||
std::size_t count; // public
|
||||
explicit ObjectDeleter(T **p, std::size_t n) noexcept : items(p), count(n) {}
|
||||
~ObjectDeleter() noexcept { delete_items(); }
|
||||
void delete_items() noexcept {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
auto item = items[i];
|
||||
items[i] = nullptr;
|
||||
for (std::size_t i = 0; i < count; i++) {
|
||||
T *item = atomic_exchange(&items[i], (T *) nullptr);
|
||||
delete item; // single object delete
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class T> // T is "SomeType **"
|
||||
template <class T>
|
||||
struct ArrayDeleter final {
|
||||
static_assert(std::is_pointer_v<T>);
|
||||
static_assert(std::is_pointer_v<std::remove_pointer_t<T> >);
|
||||
T items; // public
|
||||
size_t count; // public
|
||||
T **items; // public
|
||||
std::size_t count; // public
|
||||
explicit ArrayDeleter(T **p, std::size_t n) noexcept : items(p), count(n) {}
|
||||
~ArrayDeleter() noexcept { delete_items(); }
|
||||
void delete_items() noexcept {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
auto item = items[i];
|
||||
items[i] = nullptr;
|
||||
for (std::size_t i = 0; i < count; i++) {
|
||||
T *item = atomic_exchange(&items[i], (T *) nullptr);
|
||||
delete[] item; // array delete
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class T>
|
||||
struct MallocDeleter final {
|
||||
T **items; // public
|
||||
std::size_t count; // public
|
||||
explicit MallocDeleter(T **p, std::size_t n) noexcept : items(p), count(n) {}
|
||||
~MallocDeleter() noexcept { delete_items(); }
|
||||
void delete_items() noexcept {
|
||||
for (std::size_t i = 0; i < count; i++) {
|
||||
T *item = atomic_exchange(&items[i], (T *) nullptr);
|
||||
::free(item); // free memory from malloc()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class noncopyable {
|
||||
protected:
|
||||
@ -242,10 +282,10 @@ constexpr bool string_gt(const char *a, const char *b) { return string_lt(b, a);
|
||||
constexpr bool string_le(const char *a, const char *b) { return !string_lt(b, a); }
|
||||
constexpr bool string_ge(const char *a, const char *b) { return !string_lt(a, b); }
|
||||
|
||||
constexpr bool mem_eq(const char *a, const char *b, size_t n) {
|
||||
constexpr bool mem_eq(const char *a, const char *b, std::size_t n) {
|
||||
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
|
||||
}
|
||||
constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, size_t n) {
|
||||
constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, std::size_t n) {
|
||||
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
|
||||
}
|
||||
} // namespace compile_time
|
||||
|
@ -136,19 +136,19 @@ static_assert(sizeof(void *) == sizeof(long));
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
// sanitizers
|
||||
// sanitizers: ASAN, MSAN, UBSAN
|
||||
#if !defined(__SANITIZE_ADDRESS__) && defined(__has_feature)
|
||||
#if __has_feature(address_sanitizer)
|
||||
#if __has_feature(address_sanitizer) // ASAN
|
||||
#define __SANITIZE_ADDRESS__ 1
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(__SANITIZE_MEMORY__) && defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#if __has_feature(memory_sanitizer) // MSAN
|
||||
#define __SANITIZE_MEMORY__ 1
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(__SANITIZE_UNDEFINED_BEHAVIOR__) && defined(__has_feature)
|
||||
#if __has_feature(undefined_behavior_sanitizer)
|
||||
#if __has_feature(undefined_behavior_sanitizer) // UBSAN
|
||||
#define __SANITIZE_UNDEFINED_BEHAVIOR__ 1
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user