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