static void (*g_debug_finalize_func)();
static void (*g_debug_get_malloc_leak_info_func)(uint8_t**, size_t*, size_t*, size_t*, size_t*);
static void (*g_debug_free_malloc_leak_info_func)(uint8_t*);
+static ssize_t (*g_debug_malloc_backtrace_func)(void*, uintptr_t*, size_t);
// =============================================================================
// Log functions
}
g_debug_free_malloc_leak_info_func = reinterpret_cast<void (*)(uint8_t*)>(sym);
+ sym = dlsym(malloc_impl_handle, "debug_malloc_backtrace");
+ if (sym == nullptr) {
+ error_log("%s: debug_malloc_backtrace routine not found in %s", getprogname(),
+ DEBUG_SHARED_LIB);
+ dlclose(malloc_impl_handle);
+ return;
+ }
+ g_debug_malloc_backtrace_func = reinterpret_cast<ssize_t (*)(void*, uintptr_t*, size_t)>(sym);
+
if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild)) {
dlclose(malloc_impl_handle);
return;
}
return Malloc(malloc_enable)();
}
+
+#ifndef LIBC_STATIC
+extern "C" ssize_t malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count) {
+ if (g_debug_malloc_backtrace_func == nullptr) {
+ return 0;
+ }
+ return g_debug_malloc_backtrace_func(pointer, frames, frame_count);
+}
+#else
+extern "C" ssize_t malloc_backtrace(void*, uintptr_t*, size_t) {
+ return 0;
+}
+#endif
void debug_get_malloc_leak_info(
uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory,
size_t* backtrace_size);
+ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
void debug_free_malloc_leak_info(uint8_t* info);
size_t debug_malloc_usable_size(void* pointer);
void* debug_malloc(size_t size);
if (g_debug->config().options & BACKTRACE) {
BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
if (g_debug->backtrace->enabled()) {
+ ScopedDisableDebugCalls disable;
back_header->num_frames = backtrace_get(
&back_header->frames[0], g_debug->config().backtrace_frames);
backtrace_found = back_header->num_frames > 0;
g_dispatch->malloc_enable();
}
+ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count) {
+ if (DebugCallsDisabled() || pointer == nullptr) {
+ return 0;
+ }
+
+ if (g_debug->need_header()) {
+ Header* header;
+ if (g_debug->config().options & TRACK_ALLOCS) {
+ header = g_debug->GetHeader(pointer);
+ if (!g_debug->track->Contains(header)) {
+ return 0;
+ }
+ } else {
+ header = reinterpret_cast<Header*>(pointer);
+ }
+ if (header->tag != DEBUG_TAG) {
+ return 0;
+ }
+ if (g_debug->config().options & BACKTRACE) {
+ BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
+ if (back_header->num_frames > 0) {
+ if (frame_count > back_header->num_frames) {
+ frame_count = back_header->num_frames;
+ }
+ memcpy(frames, &back_header->frames[0], frame_count * sizeof(uintptr_t));
+ return frame_count;
+ }
+ }
+ }
+
+ return 0;
+}
+
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
void* debug_pvalloc(size_t bytes) {
if (DebugCallsDisabled()) {