Print the entire backtrace

This commit is contained in:
Gwilym Inzani 2024-04-01 14:05:22 +01:00
parent 8453b46eab
commit 3f374f3e9c
3 changed files with 49 additions and 28 deletions

View file

@ -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<impl gimli::Reader>, 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<u64, <u64 as FromStr>::Err> {
if let Some(input) = input.strip_prefix("0x") {
u64::from_str_radix(input, 16)
} else {
input.parse()
}
}

View file

@ -9,8 +9,8 @@ struct Context {
registers: [u32; 11],
}
pub struct Frame {
pub address: u32,
pub struct Frames {
frames: Vec<u32>,
}
#[allow(unused)]
@ -37,7 +37,7 @@ impl Index<Register> for Context {
}
#[inline(never)]
pub(crate) fn unwind_exception() -> Vec<Frame> {
pub(crate) fn unwind_exception() -> Frames {
let mut context = Context::default();
unsafe {
@ -77,10 +77,33 @@ pub(crate) fn unwind_exception() -> Vec<Frame> {
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(())
}
}

View file

@ -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),
format_args!("debug data: {frames}"),
mgba::DebugLevel::Error,
);
}
let _ = mgba.print(format_args!("Error: {info}"), mgba::DebugLevel::Fatal);
}