diff --git a/Userland/Applications/Debugger/main.cpp b/Userland/Applications/Debugger/main.cpp index 42f30e3ac8..5af52439a9 100644 --- a/Userland/Applications/Debugger/main.cpp +++ b/Userland/Applications/Debugger/main.cpp @@ -78,6 +78,28 @@ static bool handle_disassemble_command(const String& command, void* first_instru return true; } +static bool handle_backtrace_command(const PtraceRegisters& regs) +{ + auto ebp_val = regs.ebp; + auto eip_val = regs.eip; + outln("Backtrace:\n"); + while (g_debug_session->peek((u32*)eip_val).has_value() && g_debug_session->peek((u32*)ebp_val).has_value()) { + auto eip_symbol = g_debug_session->symbolicate(eip_val); + auto source_position = g_debug_session->get_source_position(eip_val); + String symbol_location = (eip_symbol.has_value() && eip_symbol->symbol != "") ? eip_symbol->symbol : "???"; + if (source_position.has_value()) { + outln("{:p} in {} ({}:{})", eip_val, symbol_location, source_position->file_path, source_position->line_number); + } else { + outln("{:p} in {}", eip_val, symbol_location); + } + auto next_eip = g_debug_session->peek((u32*)(ebp_val + 4)); + auto next_ebp = g_debug_session->peek((u32*)ebp_val); + eip_val = (u32)next_eip.value(); + ebp_val = (u32)next_ebp.value(); + } + return true; +} + static bool insert_breakpoint_at_address(FlatPtr address) { return g_debug_session->insert_breakpoint((void*)address); @@ -165,6 +187,7 @@ static void print_help() "regs - Print registers\n" "dis [number of instructions] - Print disassembly\n" "bp
- Insert a breakpoint\n" + "bt - show backtrace for current thread\n" "x
- examine dword in memory\n"); } @@ -274,6 +297,8 @@ int main(int argc, char** argv) success = handle_breakpoint_command(command); } else if (command.starts_with("x")) { success = handle_examine_command(command); + } else if (command.starts_with("bt")) { + success = handle_backtrace_command(regs); } if (success && !command.is_empty()) {