diff --git a/headers/posix/malloc_debug.h b/headers/posix/malloc_debug.h index 4c07f5af8e..5e0de0016a 100644 --- a/headers/posix/malloc_debug.h +++ b/headers/posix/malloc_debug.h @@ -30,6 +30,7 @@ void *heap_debug_malloc_with_guard_page(size_t size); status_t heap_debug_get_allocation_info(void *address, size_t *size, thread_id *thread); +status_t heap_debug_dump_allocations_on_exit(bool enabled); status_t heap_debug_set_stack_trace_depth(size_t stackTraceDepth); #ifdef __cplusplus diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h index 7f6dcd5f3a..85036df0bf 100644 --- a/headers/private/libroot/libroot_private.h +++ b/headers/private/libroot/libroot_private.h @@ -35,6 +35,7 @@ void _call_atexit_hooks_for_range(addr_t start, addr_t size); void __init_env(const struct user_space_program_args *args); status_t __init_heap(void); void __init_heap_post_env(void); +void __heap_terminate_after(void); void __init_time(addr_t commPageTable); void __arch_init_time(struct real_time_data *data, bool setDefaults); diff --git a/src/system/libroot/libroot_init.c b/src/system/libroot/libroot_init.c index caef95b2fc..03cb17f70d 100644 --- a/src/system/libroot/libroot_init.c +++ b/src/system/libroot/libroot_init.c @@ -20,6 +20,7 @@ void initialize_before(image_id imageID); +void terminate_after(image_id imageID); struct rld_export *__gRuntimeLoader = NULL; // This little bugger is set to something meaningful by the runtime loader @@ -94,3 +95,9 @@ _init_c_library_(void) // do anything here. } + +void +terminate_after(image_id id) +{ + __heap_terminate_after(); +} diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp index 4b9572e868..d2c25b8f5e 100644 --- a/src/system/libroot/posix/malloc/arch-specific.cpp +++ b/src/system/libroot/posix/malloc/arch-specific.cpp @@ -131,6 +131,13 @@ __init_heap_post_env(void) } +extern "C" void +__heap_terminate_after() +{ + // nothing to do +} + + static void insert_chunk(free_chunk *newChunk) { diff --git a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp index 1a1b0a85c2..09793a478a 100644 --- a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp +++ b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp @@ -22,6 +22,7 @@ static const size_t kMaxStackTraceDepth = 50; static bool sDebuggerCalls = true; +static bool sDumpAllocationsOnExit = false; static size_t sStackTraceDepth = 0; #if __cplusplus >= 201103L @@ -50,6 +51,22 @@ panic(const char* format, ...) } +static void +print_stdout(const char* format, ...) +{ + // To avoid any allocations due to dynamic memory need by printf() we use a + // stack buffer and vsnprintf(). Otherwise this does the same as printf(). + char buffer[1024]; + + va_list args; + va_start(args, format); + vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + + write(STDOUT_FILENO, buffer, strlen(buffer)); +} + + // #pragma mark - Linked List @@ -218,12 +235,12 @@ guarded_heap_print_stack_trace(addr_t stackTrace[], size_t depth) status_t status = _kern_lookup_symbol(address, &baseAddress, symbolName, sizeof(symbolName), imageName, sizeof(imageName), &exactMatch); if (status != B_OK) { - printf("\t%#" B_PRIxADDR " (lookup failed: %s)\n", address, + print_stdout("\t%#" B_PRIxADDR " (lookup failed: %s)\n", address, strerror(status)); continue; } - printf("\t<%s> %s + %#" B_PRIxADDR "%s\n", imageName, symbolName, + print_stdout("\t<%s> %s + %#" B_PRIxADDR "%s\n", imageName, symbolName, address - baseAddress, (exactMatch ? "" : " (nearest)")); } } @@ -929,7 +946,7 @@ dump_allocations(guarded_heap& heap, bool statsOnly, thread_id thread) if (statsOnly) continue; - printf("allocation: base: %p; size: %" B_PRIuSIZE + print_stdout("allocation: base: %p; size: %" B_PRIuSIZE "; thread: %" B_PRId32 "; alignment: %" B_PRIuSIZE "\n", page.allocation_base, page.allocation_size, page.thread, page.alignment); @@ -939,11 +956,18 @@ dump_allocations(guarded_heap& heap, bool statsOnly, thread_id thread) } } - printf("total allocations: %" B_PRIuSIZE ", %" B_PRIuSIZE " bytes\n", + print_stdout("total allocations: %" B_PRIuSIZE ", %" B_PRIuSIZE " bytes\n", allocationCount, allocationSize); } +static void +dump_allocations_full() +{ + dump_allocations(sGuardedHeap, false, -1); +} + + // #pragma mark - Heap Debug API @@ -1047,6 +1071,14 @@ heap_debug_get_allocation_info(void *address, size_t *size, } +extern "C" status_t +heap_debug_dump_allocations_on_exit(bool enabled) +{ + sDumpAllocationsOnExit = enabled; + return B_OK; +} + + extern "C" status_t heap_debug_set_stack_trace_depth(size_t stackTraceDepth) { @@ -1104,6 +1136,8 @@ __init_heap_post_env(void) if (mode != NULL) { if (strchr(mode, 'r')) heap_debug_set_memory_reuse(false); + if (strchr(mode, 'e')) + heap_debug_dump_allocations_on_exit(true); size_t defaultAlignment = 0; const char *argument = strchr(mode, 'a'); @@ -1123,6 +1157,14 @@ __init_heap_post_env(void) } +extern "C" void +__heap_terminate_after() +{ + if (sDumpAllocationsOnExit) + dump_allocations_full(); +} + + // #pragma mark - Public API diff --git a/src/system/libroot/posix/malloc_debug/heap.cpp b/src/system/libroot/posix/malloc_debug/heap.cpp index 1da238e0d6..280953b2cc 100644 --- a/src/system/libroot/posix/malloc_debug/heap.cpp +++ b/src/system/libroot/posix/malloc_debug/heap.cpp @@ -1807,6 +1807,13 @@ heap_debug_get_allocation_info(void *address, size_t *size, } +extern "C" status_t +heap_debug_dump_allocations_on_exit(bool enabled) +{ + return B_NOT_SUPPORTED; +} + + extern "C" status_t heap_debug_set_stack_trace_depth(size_t stackTraceDepth) { @@ -1873,6 +1880,13 @@ __init_heap_post_env(void) } +extern "C" void +__heap_terminate_after() +{ + // nothing to do +} + + // #pragma mark - Public API