use library functions to get address info

This commit is contained in:
Corwin 2024-04-20 21:49:05 +01:00
parent 528fe889fa
commit 04f1d5c2ff
No known key found for this signature in database

View file

@ -7,8 +7,7 @@ use std::{
time::SystemTime, time::SystemTime,
}; };
use addr2line::gimli; use agb_debug::{address_info, AddressInfo, Location};
use agb_debug::Location;
use clap::Parser; use clap::Parser;
use colored::Colorize; use colored::Colorize;
@ -35,77 +34,46 @@ fn main() -> Result<(), Box<dyn Error>> {
let ctx = addr2line::Context::from_dwarf(dwarf)?; let ctx = addr2line::Context::from_dwarf(dwarf)?;
for (i, address) in agb_debug::gwilym_decode(&cli.dump)?.enumerate() { for (i, address) in agb_debug::gwilym_decode(&cli.dump)?.enumerate() {
print_address(&ctx, i, address.into(), modification_time)?; let infos = address_info(&ctx, address.into())?;
for info in infos {
print_address_info(&info, i, modification_time)?;
}
} }
Ok(()) Ok(())
} }
fn print_address( fn print_address_info(
ctx: &addr2line::Context<impl gimli::Reader>, info: &AddressInfo,
index: usize, index: usize,
address: u64,
elf_modification_time: SystemTime, elf_modification_time: SystemTime,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
let mut frames = ctx.find_frames(address).skip_all_loads()?; let function_name_to_print = &info.function;
let mut is_first = true; if !info.is_inline {
print!("{index}:\t{function_name_to_print}");
} else {
print!("\t(inlined into) {function_name_to_print}");
}
while let Some(frame) = frames.next()? { println!(
let function_name = if let Some(ref func) = frame.function { " {}:{}",
func.demangle()?.into_owned() prettify_path(&info.location.filename).green(),
} else { info.location.line.to_string().green()
"unknown function".to_string() );
};
let location = frame if info.location.line != 0 && info.is_interesting {
.location print_line_of_code(&info.location, elf_modification_time)?;
.as_ref()
.map(|location| Location {
filename: location.file.unwrap_or("??").to_owned(),
line: location.line.unwrap_or(0),
col: location.column.unwrap_or(0),
})
.unwrap_or_default();
let is_interesting = is_interesting_function(&function_name, &location.filename);
let function_name_to_print = if is_interesting {
function_name.bold()
} else {
function_name.normal()
};
if is_first {
print!("{index}:\t{function_name_to_print}");
} else {
print!("\t(inlined into) {function_name_to_print}");
}
println!(
" {}:{}",
prettify_path(&location.filename).green(),
location.line.to_string().green()
);
if location.line != 0 && is_interesting {
print_line_of_code(&frame, location, elf_modification_time)?;
}
is_first = false;
} }
Ok(()) Ok(())
} }
fn print_line_of_code( fn print_line_of_code(
frame: &addr2line::Frame<'_, impl gimli::Reader>, location: &Location,
location: Location,
elf_modification_time: SystemTime, elf_modification_time: SystemTime,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
let Some(filename) = frame.location.as_ref().and_then(|location| location.file) else { let filename = &location.filename;
return Ok(());
};
let Ok(mut file) = File::open(filename) else { let Ok(mut file) = File::open(filename) else {
return Ok(()); return Ok(());
}; };
@ -153,15 +121,3 @@ fn prettify_path(path: &str) -> Cow<'_, str> {
Cow::Borrowed(path) Cow::Borrowed(path)
} }
} }
fn is_interesting_function(function_name: &str, path: &str) -> bool {
if function_name == "rust_begin_unwind" {
return false; // this is the unwind exception call
}
if path.ends_with("panicking.rs") {
return false; // probably part of rust's internal panic mechanisms
}
true
}