debugger: reverse the order the backtrace is printed (#3474)

This commit is contained in:
ManDude 2024-04-16 05:22:31 +01:00 committed by GitHub
parent 8e5830321c
commit bcab625864
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -224,11 +224,6 @@ InstructionPointerInfo Debugger::get_rip_info(u64 rip) {
return result; return result;
} }
void print_and_append_to_string(std::string& str, const std::string& log) {
str += log;
lg::print("{}", log);
}
std::vector<BacktraceFrame> Debugger::get_backtrace(u64 rip, std::vector<BacktraceFrame> Debugger::get_backtrace(u64 rip,
u64 rsp, u64 rsp,
std::optional<std::string> dump_path) { std::optional<std::string> dump_path) {
@ -238,14 +233,13 @@ std::vector<BacktraceFrame> Debugger::get_backtrace(u64 rip,
lg::print("Backtrace:\n"); lg::print("Backtrace:\n");
std::vector<BacktraceFrame> bt; std::vector<BacktraceFrame> bt;
if (rip == m_debug_context.base) { bool null_pc = rip == m_debug_context.base;
if (null_pc) {
// we jumped to NULL. // we jumped to NULL.
print_and_append_to_string(backtrace_contents,
"Jumped to GOAL 0x0. Attempting to find previous function.\n");
u64 next_rip = 0; u64 next_rip = 0;
if (!read_memory_if_safe<u64>(&next_rip, rsp - m_debug_context.base)) { if (!read_memory_if_safe<u64>(&next_rip, rsp - m_debug_context.base)) {
print_and_append_to_string(backtrace_contents, lg::print("Failed to read return address off of the stack!\n");
" failed to read return address off of the stack\n");
return {}; return {};
} }
@ -255,10 +249,9 @@ std::vector<BacktraceFrame> Debugger::get_backtrace(u64 rip,
int fails = 0; int fails = 0;
while (true) { while (true) {
print_and_append_to_string( std::string this_backtrace;
backtrace_contents, this_backtrace = fmt::format(" rsp: 0x{:x} (#x{:x}) rip: 0x{:x} (#x{:x})\n", rsp,
fmt::format(" rsp: 0x{:x} (#x{:x}) rip: 0x{:x} (#x{:x})\n", rsp, rsp - m_debug_context.base, rip, rip - m_debug_context.base);
rsp - m_debug_context.base, rip, rip - m_debug_context.base));
BacktraceFrame frame; BacktraceFrame frame;
frame.rip_info = get_rip_info(rip); frame.rip_info = get_rip_info(rip);
frame.rsp_at_rip = rsp; frame.rsp_at_rip = rsp;
@ -266,19 +259,18 @@ std::vector<BacktraceFrame> Debugger::get_backtrace(u64 rip,
if (frame.rip_info.knows_function && frame.rip_info.func_debug && if (frame.rip_info.knows_function && frame.rip_info.func_debug &&
frame.rip_info.func_debug->stack_usage) { frame.rip_info.func_debug->stack_usage) {
fails = 0; fails = 0;
print_and_append_to_string(backtrace_contents, this_backtrace += "<====================== CALL STACK ======================>\n";
"<====================== CALL STACK ======================>\n"); this_backtrace += fmt::format("{} from {}\n", frame.rip_info.function_name,
print_and_append_to_string(backtrace_contents, frame.rip_info.func_debug->obj_name);
fmt::format("{} from {}\n", frame.rip_info.function_name,
frame.rip_info.func_debug->obj_name));
// we're good! // we're good!
auto disasm = disassemble_at_rip(frame.rip_info); auto disasm = disassemble_at_rip(frame.rip_info);
print_and_append_to_string(backtrace_contents, fmt::format("{}\n", disasm.text)); this_backtrace += fmt::format("{}\n", disasm.text);
u64 rsp_at_call = rsp + *frame.rip_info.func_debug->stack_usage; u64 rsp_at_call = rsp + *frame.rip_info.func_debug->stack_usage;
u64 next_rip = 0; u64 next_rip = 0;
if (!read_memory_if_safe<u64>(&next_rip, rsp_at_call - m_debug_context.base)) { if (!read_memory_if_safe<u64>(&next_rip, rsp_at_call - m_debug_context.base)) {
print_and_append_to_string(backtrace_contents, "Invalid return address encountered!\n"); this_backtrace += "Invalid return address encountered!\n";
backtrace_contents = this_backtrace + backtrace_contents;
break; break;
} }
@ -288,7 +280,7 @@ std::vector<BacktraceFrame> Debugger::get_backtrace(u64 rip,
} else { } else {
if (!frame.rip_info.knows_function) { if (!frame.rip_info.knows_function) {
if (fails == 0) { if (fails == 0) {
print_and_append_to_string(backtrace_contents, "Unknown Function at rip\n"); this_backtrace += "Unknown Function at rip\n";
} }
/* /*
@ -325,16 +317,17 @@ std::vector<BacktraceFrame> Debugger::get_backtrace(u64 rip,
} }
} else*/ } else*/
if (fails > 70) { if (fails > 70) {
print_and_append_to_string( this_backtrace +=
backtrace_contents,
"Backtrace was too long. Exception might have happened outside GOAL code, or the " "Backtrace was too long. Exception might have happened outside GOAL code, or the "
"stack frame is too long.\n"); "stack frame is too long.\n";
backtrace_contents = this_backtrace + backtrace_contents;
break; break;
} }
// attempt to backtrace anyway! if this fails then rip // attempt to backtrace anyway! if this fails then rip
u64 next_rip = 0; u64 next_rip = 0;
if (!read_memory_if_safe<u64>(&next_rip, rsp - m_debug_context.base - 8)) { if (!read_memory_if_safe<u64>(&next_rip, rsp - m_debug_context.base - 8)) {
print_and_append_to_string(backtrace_contents, "Invalid return address encountered!\n"); this_backtrace += "Invalid return address encountered!\n";
backtrace_contents = this_backtrace + backtrace_contents;
break; break;
} }
@ -343,21 +336,24 @@ std::vector<BacktraceFrame> Debugger::get_backtrace(u64 rip,
++fails; ++fails;
// break; // break;
} else if (!frame.rip_info.func_debug) { } else if (!frame.rip_info.func_debug) {
print_and_append_to_string( this_backtrace +=
backtrace_contents, fmt::format("Function {} has no debug info.\n", frame.rip_info.function_name);
fmt::format("Function {} has no debug info.\n", frame.rip_info.function_name)); backtrace_contents = this_backtrace + backtrace_contents;
break; break;
} else { } else {
print_and_append_to_string( this_backtrace +=
backtrace_contents, fmt::format("Function {} with no stack frame data.\n", frame.rip_info.function_name);
fmt::format("Function {} with no stack frame data.\n", frame.rip_info.function_name)); backtrace_contents = this_backtrace + backtrace_contents;
break; break;
} }
} }
bt.push_back(frame); bt.push_back(frame);
backtrace_contents = this_backtrace + backtrace_contents;
} }
lg::print("{}\n", backtrace_contents);
if (dump_path) { if (dump_path) {
file_util::write_text_file(dump_path.value(), backtrace_contents); file_util::write_text_file(dump_path.value(), backtrace_contents);
} }
@ -449,21 +445,21 @@ void Debugger::update_break_info(std::optional<std::string> dump_path) {
m_memory_map = m_listener->build_memory_map(); m_memory_map = m_listener->build_memory_map();
// lg::print("{}", m_memory_map.print()); // lg::print("{}", m_memory_map.print());
read_symbol_table(); read_symbol_table();
m_regs_valid = false; m_regs_valid = xdbg::get_regs_now(m_debug_context.tid, &m_regs_at_break);
if (!xdbg::get_regs_now(m_debug_context.tid, &m_regs_at_break)) {
lg::print("[Debugger] get_regs_now failed after break, something is wrong\n");
} else {
m_regs_valid = true;
lg::print("{}", m_regs_at_break.print_gprs());
}
if (regs_valid()) { if (regs_valid()) {
m_break_info = get_rip_info(m_regs_at_break.rip); m_break_info = get_rip_info(m_regs_at_break.rip);
update_continue_info(); update_continue_info();
auto dis = disassemble_at_rip(m_break_info);
lg::print("{}\n", dis.text);
get_backtrace(m_regs_at_break.rip, m_regs_at_break.gprs[emitter::RSP], dump_path); get_backtrace(m_regs_at_break.rip, m_regs_at_break.gprs[emitter::RSP], dump_path);
auto dis = disassemble_at_rip(m_break_info);
lg::print("{}\n", dis.text);
}
if (!m_regs_valid) {
lg::print("[Debugger] get_regs_now failed after break, something is wrong\n");
} else {
lg::print("{}", m_regs_at_break.print_gprs());
} }
} }