From 3f374f3e9c9b7936806b7e401d0eacf7b070bc8d Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Mon, 1 Apr 2024 14:05:22 +0100 Subject: [PATCH] Print the entire backtrace --- agb-addr2line/src/main.rs | 34 +++++++++++++++++----------------- agb/src/backtrace.rs | 33 ++++++++++++++++++++++++++++----- agb/src/lib.rs | 10 ++++------ 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/agb-addr2line/src/main.rs b/agb-addr2line/src/main.rs index 85cbebcb..b13a9b6d 100644 --- a/agb-addr2line/src/main.rs +++ b/agb-addr2line/src/main.rs @@ -1,6 +1,6 @@ -use std::{fs, path::PathBuf, str::FromStr}; +use std::{fs, path::PathBuf}; -use addr2line::object; +use addr2line::{gimli, object}; use clap::Parser; #[derive(Parser, Debug)] @@ -35,9 +35,20 @@ fn main() -> anyhow::Result<()> { let ctx = addr2line::Context::new(&object)?; - let mut frames = ctx - .find_frames(parse_address(&cli.dump)?) - .skip_all_loads()?; + for address in cli.dump.split('-') { + let mut address = u64::from_str_radix(address, 16)?; + if address <= 0xFFFF { + address += 0x0800_0000; + } + + print_address(&ctx, address)?; + } + + Ok(()) +} + +fn print_address(ctx: &addr2line::Context, address: u64) -> anyhow::Result<()> { + let mut frames = ctx.find_frames(address).skip_all_loads()?; while let Some(frame) = frames.next()? { let function_name = if let Some(func) = frame.function { @@ -54,19 +65,8 @@ fn main() -> anyhow::Result<()> { }) .unwrap_or_default(); - println!( - "{}:{} ({})", - location.filename, location.line, function_name - ); + println!("{function_name} ({}:{})", location.filename, location.line); } Ok(()) } - -fn parse_address(input: &str) -> Result::Err> { - if let Some(input) = input.strip_prefix("0x") { - u64::from_str_radix(input, 16) - } else { - input.parse() - } -} diff --git a/agb/src/backtrace.rs b/agb/src/backtrace.rs index 6081c45c..530fe845 100644 --- a/agb/src/backtrace.rs +++ b/agb/src/backtrace.rs @@ -9,8 +9,8 @@ struct Context { registers: [u32; 11], } -pub struct Frame { - pub address: u32, +pub struct Frames { + frames: Vec, } #[allow(unused)] @@ -37,7 +37,7 @@ impl Index for Context { } #[inline(never)] -pub(crate) fn unwind_exception() -> Vec { +pub(crate) fn unwind_exception() -> Frames { let mut context = Context::default(); unsafe { @@ -77,10 +77,33 @@ pub(crate) fn unwind_exception() -> Vec { break; } - frames.push(Frame { address: lr }); + frames.push(lr); frame_pointer = sp; } - frames + Frames { frames } +} + +impl core::fmt::Display for Frames { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut is_first = true; + + for frame in &self.frames { + if !is_first { + write!(f, "-")?; + } + + if frame & 0xFFFF_0000 == 0x0800_0000 { + let frame = frame & 0xFFFF; + write!(f, "{frame:x}")?; + } else { + write!(f, "{frame:x}")?; + } + + is_first = false; + } + + Ok(()) + } } diff --git a/agb/src/lib.rs b/agb/src/lib.rs index 03a29264..a9743390 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -323,12 +323,10 @@ pub mod test_runner { if let Some(mut mgba) = mgba::Mgba::new() { let _ = mgba.print(format_args!("[failed]"), mgba::DebugLevel::Error); - for frame in frames { - let _ = mgba.print( - format_args!("{:#08x}", frame.address), - mgba::DebugLevel::Error, - ); - } + let _ = mgba.print( + format_args!("debug data: {frames}"), + mgba::DebugLevel::Error, + ); let _ = mgba.print(format_args!("Error: {info}"), mgba::DebugLevel::Fatal); }