kernel/guarded_heap: Add stack traces to allocations command.

This allows dumping the allocation stack traces in the more powerful
allocations command with the optional "trace" argument. The stack trace
could previously only be dumped manually by inspecting individual
guarded heap pages.
This commit is contained in:
Michael Lotz 2020-06-13 22:35:25 +02:00
parent e65c8deae2
commit 3ff5a87931

View File

@ -577,6 +577,31 @@ guarded_heap_realloc(void* address, size_t newSize)
// #pragma mark - Debugger commands
static void
dump_guarded_heap_stack_trace(guarded_heap_page& page)
{
#if GUARDED_HEAP_STACK_TRACE_DEPTH > 0
kprintf("stack trace:\n");
for (size_t i = 0; i < page.stack_trace_depth; i++) {
addr_t address = page.stack_trace[i];
const char* symbol;
const char* imageName;
bool exactMatch;
addr_t baseAddress;
if (elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
&imageName, &exactMatch) == B_OK) {
kprintf(" %p %s + 0x%lx (%s)%s\n", (void*)address, symbol,
address - baseAddress, imageName,
exactMatch ? "" : " (nearest)");
} else
kprintf(" %p\n", (void*)address);
}
#endif
}
static int
dump_guarded_heap_page(int argc, char** argv)
{
@ -627,26 +652,7 @@ dump_guarded_heap_page(int argc, char** argv)
kprintf("allocating team: %" B_PRId32 "\n", page.team);
kprintf("allocating thread: %" B_PRId32 "\n", page.thread);
#if GUARDED_HEAP_STACK_TRACE_DEPTH > 0
kprintf("stack trace:\n");
for (size_t i = 0; i < page.stack_trace_depth; i++) {
addr_t address = page.stack_trace[i];
const char* symbol;
const char* imageName;
bool exactMatch;
addr_t baseAddress;
if (elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
&imageName, &exactMatch) == B_OK) {
kprintf(" %p %s + 0x%lx (%s)%s\n", (void*)address, symbol,
address - baseAddress, imageName,
exactMatch ? "" : " (nearest)");
} else
kprintf(" %p\n", (void*)address);
}
#endif
dump_guarded_heap_stack_trace(page);
return 0;
}
@ -783,6 +789,7 @@ dump_guarded_heap_allocations(int argc, char** argv)
thread_id thread = -1;
addr_t address = 0;
bool statsOnly = false;
bool stackTrace = false;
for (int32 i = 1; i < argc; i++) {
if (strcmp(argv[i], "team") == 0)
@ -793,6 +800,10 @@ dump_guarded_heap_allocations(int argc, char** argv)
address = parse_expression(argv[++i]);
else if (strcmp(argv[i], "stats") == 0)
statsOnly = true;
#if GUARDED_HEAP_STACK_TRACE_DEPTH > 0
else if (strcmp(argv[i], "trace") == 0)
stackTrace = true;
#endif
else {
print_debugger_command_usage(argv[0]);
return 0;
@ -818,6 +829,9 @@ dump_guarded_heap_allocations(int argc, char** argv)
"address: 0x%08" B_PRIxADDR "; size: %" B_PRIuSIZE
" bytes\n", page.team, page.thread,
(addr_t)page.allocation_base, page.allocation_size);
if (stackTrace)
dump_guarded_heap_stack_trace(page);
}
totalSize += page.allocation_size;
@ -892,10 +906,18 @@ heap_init_post_sem()
0);
add_debugger_command_etc("allocations", &dump_guarded_heap_allocations,
"Dump current heap allocations",
#if GUARDED_HEAP_STACK_TRACE_DEPTH == 0
"[\"stats\"] [team] [thread] [address]\n"
#else
"[\"stats\"|\"trace\"] [team] [thread] [address]\n"
#endif
"If no parameters are given, all current alloactions are dumped.\n"
"If the optional argument \"stats\" is specified, only the allocation\n"
"counts and no individual allocations are printed.\n"
#if GUARDED_HEAP_STACK_TRACE_DEPTH > 0
"If the optional argument \"trace\" is specified, a stack trace for\n"
"each allocation is printed.\n"
#endif
"If a specific allocation address is given, only this allocation is\n"
"dumped.\n"
"If a team and/or thread is specified, only allocations of this\n"