void* operator new (std::size_t len) throw(std::bad_alloc) { void* data = nullptr; if (enable_buffer_protection) { // Allocate requested memory + enough to fit checksum at start and end data = malloc(len + sizeof(buffer_protection_checksum) * 2); // Write checksums auto* temp = reinterpret_cast<char*>(data); memcpy(temp, &buffer_protection_checksum, sizeof(buffer_protection_checksum)); memcpy(temp + sizeof(buffer_protection_checksum) + len, &buffer_protection_checksum, sizeof(buffer_protection_checksum)); } else { data = malloc(len); } if (enable_debugging_verbose) { DPRINTF("malloc(%llu bytes) == %p\n", (unsigned long long) len, data); safe_print_symbol(1, __builtin_return_address(0)); safe_print_symbol(2, __builtin_return_address(1)); } if (UNLIKELY(!data)) { print_backtrace(); DPRINTF("malloc(%llu bytes): FAILED\n", (unsigned long long) len); throw std::bad_alloc(); } if (enable_debugging) { if (!free_allocs.empty()) { auto* x = free_allocs.pop(); new(x) allocation((char*) data, len, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2)); } else if (!allocs.free_capacity()) { DPRINTF("[WARNING] Internal fixed vectors are FULL, expect bogus double free messages\n"); } else { allocs.emplace((char*) data, len, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2)); } } if (enable_buffer_protection) { // We need to return a pointer to the allocated memory + 4 // e.g. after our first checksum return reinterpret_cast<void*>(reinterpret_cast<char*>(data) + sizeof(buffer_protection_checksum)); } else { return data; } }
void print_heap_allocations(heap_print_func func) { DPRINTF("Listing %u allocations...\n", allocs.size()); for (auto& x : allocs) { if (x.addr != nullptr && func(x.addr, x.len)) { // entry DPRINTF("[%p] %llu bytes\n", x.addr, (unsigned long long) x.len); // backtrace safe_print_symbol(1, x.level1); safe_print_symbol(2, x.level2); safe_print_symbol(3, x.level3); } } }
void add(void* ra) { // need free space to take more samples if (samplerq->free_capacity()) samplerq->add((uintptr_t) ra); // return when its not our turn if (lockless) return; // transfer all the built up samplings transferq->copy(samplerq->first(), samplerq->size()); samplerq->clear(); lockless = 1; }
fixedvector<T,kmax>::fixedvector(const fixedvector<T,kmax>& rhs) : misize( rhs.size() ) { for(u32 i = 0; i < size(); ++i) mArray[i] = rhs.mArray[i]; }
int _get_heap_debugging_buffers_total() { return allocs.capacity(); }
int _get_heap_debugging_buffers_usage() { return allocs.size(); }
inline static void deleted_ptr(void* ptr) { if (enable_buffer_protection) { // Calculate where the real allocation starts (at our first checksum) ptr = reinterpret_cast<void*>(reinterpret_cast<char*>(ptr) - sizeof(buffer_protection_checksum)); } if (enable_debugging) { auto* x = find_alloc((char*) ptr); if (x == nullptr) { if (ptr < heap_begin || ptr > heap_end) { DPRINTF("[ERROR] Free on invalid non-heap address: %p\n", ptr); } else { DPRINTF("[ERROR] Possible double free on address: %p\n", ptr); } print_backtrace(); return; } else if (x->addr == ptr) { if (enable_debugging_verbose) { DPRINTF("free(%p) == %llu bytes\n", x->addr, (unsigned long long) x->len); safe_print_symbol(1, __builtin_return_address(1)); safe_print_symbol(2, __builtin_return_address(2)); } // This is the only place where we can verify the buffer protection // checksums, since we need to know the length of the allocation if (enable_buffer_protection) { auto* temp = reinterpret_cast<char*>(ptr); auto underflow = memcmp(temp, &buffer_protection_checksum, sizeof(buffer_protection_checksum)); auto overflow = memcmp(temp + sizeof(buffer_protection_checksum) + x->len, &buffer_protection_checksum, sizeof(buffer_protection_checksum)); if (underflow) { DPRINTF("[ERROR] Buffer underflow found on address: %p\n", ptr); // TODO: print stacktrace } if (overflow) { DPRINTF("[ERROR] Buffer overflow found on address: %p\n", ptr); // TODO: print stacktrace } } // perfect match x->addr = nullptr; x->len = 0; free_allocs.add(x); } else if (x->addr != ptr) { DPRINTF("[ERROR] Free on misaligned address: %p inside %p:%llu", ptr, x->addr, (unsigned long long) x->len); print_backtrace(); return; } } free(ptr); }