Parcourir la source

Debugger: Add basic backtrace support

This adds the "bt" command to the debugger which displays a backtrace
of the current thread.
spigwitmer il y a 4 ans
Parent
commit
04f26183cb
1 fichiers modifiés avec 25 ajouts et 0 suppressions
  1. 25 0
      Userland/Applications/Debugger/main.cpp

+ 25 - 0
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 <address/symbol/file:line> - Insert a breakpoint\n"
+        "bt - show backtrace for current thread\n"
         "x <address> - 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()) {