src: fix m68k-atari build, prepare for std::atomic, port John's MemBuffer debug
This commit is contained in:
@@ -33,8 +33,12 @@
|
||||
#if !defined(UPX_DOCTEST_CONFIG_MULTITHREADING)
|
||||
#define DOCTEST_CONFIG_NO_MULTITHREADING
|
||||
#endif
|
||||
#if defined(__MSDOS__) && defined(__DJGPP__)
|
||||
#if defined(__i386__) && defined(__MSDOS__) && defined(__DJGPP__) && defined(__GNUC__)
|
||||
#define DOCTEST_CONFIG_NO_POSIX_SIGNALS
|
||||
#elif defined(__m68k__) && defined(__atarist__) && defined(__GNUC__)
|
||||
#define DOCTEST_CONFIG_COLORS_NONE
|
||||
#define DOCTEST_CONFIG_NO_POSIX_SIGNALS
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
#define DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
|
||||
#if !defined(DOCTEST_CONFIG_DISABLE)
|
||||
|
||||
+24
-4
@@ -32,6 +32,14 @@
|
||||
void *membuffer_get_void_ptr(MemBuffer &mb) { return mb.getVoidPtr(); }
|
||||
unsigned membuffer_get_size(MemBuffer &mb) { return mb.getSize(); }
|
||||
|
||||
MemBuffer::Stats MemBuffer::stats;
|
||||
|
||||
#if DEBUG
|
||||
#define debug_set(var, expr) (var) = (expr)
|
||||
#else
|
||||
#define debug_set(var, expr) /*empty*/
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
// bool use_simple_mcheck()
|
||||
**************************************************************************/
|
||||
@@ -60,13 +68,17 @@ __acc_static_forceinline constexpr bool use_simple_mcheck() { return true; }
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
MemBuffer::MemBuffer(upx_uint64_t size_in_bytes) { alloc(size_in_bytes); }
|
||||
MemBuffer::MemBuffer(upx_uint64_t size_in_bytes) {
|
||||
alloc(size_in_bytes);
|
||||
debug_set(debug.last_return_address_alloc, upx_return_address());
|
||||
}
|
||||
|
||||
MemBuffer::~MemBuffer() { this->dealloc(); }
|
||||
|
||||
// similar to BoundedPtr, except checks only at creation
|
||||
// skip == offset, take == size_in_bytes
|
||||
void *MemBuffer::subref_impl(const char *errfmt, size_t skip, size_t take) {
|
||||
debug_set(debug.last_return_address_subref, upx_return_address());
|
||||
// check overrun and wrap-around
|
||||
if (skip + take > b_size_in_bytes || skip + take < skip) {
|
||||
char buf[100];
|
||||
@@ -130,14 +142,17 @@ unsigned MemBuffer::getSizeForDecompression(unsigned uncompressed_size, unsigned
|
||||
void MemBuffer::allocForCompression(unsigned uncompressed_size, unsigned extra) {
|
||||
unsigned size = getSizeForCompression(uncompressed_size, extra);
|
||||
alloc(size);
|
||||
debug_set(debug.last_return_address_alloc, upx_return_address());
|
||||
}
|
||||
|
||||
void MemBuffer::allocForDecompression(unsigned uncompressed_size, unsigned extra) {
|
||||
unsigned size = getSizeForDecompression(uncompressed_size, extra);
|
||||
alloc(size);
|
||||
debug_set(debug.last_return_address_alloc, upx_return_address());
|
||||
}
|
||||
|
||||
void MemBuffer::fill(unsigned off, unsigned len, int value) {
|
||||
debug_set(debug.last_return_address_fill, upx_return_address());
|
||||
checkState();
|
||||
assert((int) off >= 0);
|
||||
assert((int) len >= 0);
|
||||
@@ -156,8 +171,6 @@ void MemBuffer::fill(unsigned off, unsigned len, int value) {
|
||||
#define MAGIC1(p) ((PTR_BITS(p) ^ 0xfefdbeeb) | 1)
|
||||
#define MAGIC2(p) ((PTR_BITS(p) ^ 0xfefdbeeb ^ 0x80024011) | 1)
|
||||
|
||||
unsigned MemBuffer::global_alloc_counter = 0;
|
||||
|
||||
void MemBuffer::checkState() const {
|
||||
if (!b)
|
||||
throwInternalError("block not allocated");
|
||||
@@ -177,8 +190,10 @@ void MemBuffer::alloc(upx_uint64_t size) {
|
||||
assert(b_size_in_bytes == 0);
|
||||
//
|
||||
assert(size > 0);
|
||||
debug_set(debug.last_return_address_alloc, upx_return_address());
|
||||
size_t bytes = mem_size(1, size, use_simple_mcheck() ? 32 : 0);
|
||||
unsigned char *p = (unsigned char *) malloc(bytes);
|
||||
NO_printf("MemBuffer::alloc %llu: %p\n", size, p);
|
||||
if (!p)
|
||||
throwOutOfMemoryException();
|
||||
b = p;
|
||||
@@ -189,17 +204,22 @@ void MemBuffer::alloc(upx_uint64_t size) {
|
||||
set_ne32(b - 8, b_size_in_bytes);
|
||||
set_ne32(b - 4, MAGIC1(b));
|
||||
set_ne32(b + b_size_in_bytes, MAGIC2(b));
|
||||
set_ne32(b + b_size_in_bytes + 4, global_alloc_counter++);
|
||||
set_ne32(b + b_size_in_bytes + 4, stats.global_alloc_counter);
|
||||
}
|
||||
#if !defined(__SANITIZE_ADDRESS__) && 0
|
||||
fill(0, b_size_in_bytes, (rand() & 0xff) | 1); // debug
|
||||
(void) VALGRIND_MAKE_MEM_UNDEFINED(b, b_size_in_bytes);
|
||||
#endif
|
||||
stats.global_alloc_counter += 1;
|
||||
stats.global_total_bytes += b_size_in_bytes;
|
||||
stats.global_total_active_bytes += b_size_in_bytes;
|
||||
}
|
||||
|
||||
void MemBuffer::dealloc() {
|
||||
if (b != nullptr) {
|
||||
debug_set(debug.last_return_address_dealloc, upx_return_address());
|
||||
checkState();
|
||||
stats.global_total_active_bytes -= b_size_in_bytes;
|
||||
if (use_simple_mcheck()) {
|
||||
// clear magic constants
|
||||
set_ne32(b - 8, 0);
|
||||
|
||||
+21
-5
@@ -71,7 +71,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class MemBuffer : public MemBufferBase<unsigned char> {
|
||||
class MemBuffer final : public MemBufferBase<unsigned char> {
|
||||
public:
|
||||
MemBuffer() = default;
|
||||
explicit MemBuffer(upx_uint64_t size_in_bytes);
|
||||
@@ -94,21 +94,37 @@ public:
|
||||
|
||||
// util
|
||||
void fill(unsigned off, unsigned len, int value);
|
||||
void clear(unsigned off, unsigned len) { fill(off, len, 0); }
|
||||
void clear() { fill(0, b_size_in_bytes, 0); }
|
||||
__acc_forceinline void clear(unsigned off, unsigned len) { fill(off, len, 0); }
|
||||
__acc_forceinline void clear() { fill(0, b_size_in_bytes, 0); }
|
||||
|
||||
// If the entire range [skip, skip+take) is inside the buffer,
|
||||
// then return &b[skip]; else throwCantPack(sprintf(errfmt, skip, take)).
|
||||
// This is similar to BoundedPtr, except only checks once.
|
||||
// skip == offset, take == size_in_bytes
|
||||
pointer subref(const char *errfmt, size_t skip, size_t take) {
|
||||
__acc_forceinline pointer subref(const char *errfmt, size_t skip, size_t take) {
|
||||
return (pointer) subref_impl(errfmt, skip, take);
|
||||
}
|
||||
|
||||
private:
|
||||
void *subref_impl(const char *errfmt, size_t skip, size_t take);
|
||||
|
||||
static unsigned global_alloc_counter;
|
||||
// static debug stats
|
||||
struct Stats {
|
||||
upx_std_atomic(upx_uint32_t) global_alloc_counter;
|
||||
upx_std_atomic(upx_uint64_t) global_total_bytes;
|
||||
upx_std_atomic(upx_uint64_t) global_total_active_bytes;
|
||||
};
|
||||
static Stats stats;
|
||||
#if DEBUG
|
||||
// debugging aid
|
||||
struct Debug {
|
||||
void *last_return_address_alloc = nullptr;
|
||||
void *last_return_address_dealloc = nullptr;
|
||||
void *last_return_address_fill = nullptr;
|
||||
void *last_return_address_subref = nullptr;
|
||||
};
|
||||
Debug debug;
|
||||
#endif
|
||||
|
||||
// disable copy, assignment and move assignment
|
||||
MemBuffer(const MemBuffer &) = delete;
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@
|
||||
|
||||
SPAN_NAMESPACE_BEGIN
|
||||
|
||||
unsigned long long span_check_stats_check_range = 0;
|
||||
upx_std_atomic(upx_uint64_t) span_check_stats_check_range_counter(0);
|
||||
|
||||
// HINT: set env-var "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience
|
||||
__acc_noinline void span_fail_nullptr() {
|
||||
@@ -61,7 +61,7 @@ void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes)
|
||||
ptrdiff_t off = (const char *) p - (const char *) base;
|
||||
if __acc_very_unlikely (off < 0 || off > size_in_bytes)
|
||||
span_fail_range_range();
|
||||
span_check_stats_check_range += 1;
|
||||
span_check_stats_check_range_counter += 1;
|
||||
// fprintf(stderr, "span_check_range done\n");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user