mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Include the source code too
This commit is contained in:
parent
ac49855937
commit
d729591c0e
|
@ -1,4 +1,9 @@
|
||||||
use std::{borrow::Cow, fs, path::PathBuf};
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
fs::{self, File},
|
||||||
|
io::Read,
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
use addr2line::{gimli, object};
|
use addr2line::{gimli, object};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
@ -12,11 +17,16 @@ struct Args {
|
||||||
|
|
||||||
/// The output of agb's dump
|
/// The output of agb's dump
|
||||||
dump: String,
|
dump: String,
|
||||||
|
|
||||||
|
/// Whether the actual code should be shown
|
||||||
|
#[arg(short, long)]
|
||||||
|
code: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Location {
|
struct Location {
|
||||||
filename: String,
|
filename: String,
|
||||||
line: u32,
|
line: u32,
|
||||||
|
col: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Location {
|
impl Default for Location {
|
||||||
|
@ -24,6 +34,7 @@ impl Default for Location {
|
||||||
Self {
|
Self {
|
||||||
filename: "??".to_string(),
|
filename: "??".to_string(),
|
||||||
line: 0,
|
line: 0,
|
||||||
|
col: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +53,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
address += 0x0800_0000;
|
address += 0x0800_0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_address(&ctx, i, address)?;
|
print_address(&ctx, i, address, cli.code)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -52,13 +63,14 @@ fn print_address(
|
||||||
ctx: &addr2line::Context<impl gimli::Reader>,
|
ctx: &addr2line::Context<impl gimli::Reader>,
|
||||||
index: usize,
|
index: usize,
|
||||||
address: u64,
|
address: u64,
|
||||||
|
include_code: bool,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut frames = ctx.find_frames(address).skip_all_loads()?;
|
let mut frames = ctx.find_frames(address).skip_all_loads()?;
|
||||||
|
|
||||||
let mut is_first = true;
|
let mut is_first = true;
|
||||||
|
|
||||||
while let Some(frame) = frames.next()? {
|
while let Some(frame) = frames.next()? {
|
||||||
let function_name = if let Some(func) = frame.function {
|
let function_name = if let Some(ref func) = frame.function {
|
||||||
func.demangle()?.into_owned()
|
func.demangle()?.into_owned()
|
||||||
} else {
|
} else {
|
||||||
"unknown function".to_string()
|
"unknown function".to_string()
|
||||||
|
@ -66,9 +78,11 @@ fn print_address(
|
||||||
|
|
||||||
let location = frame
|
let location = frame
|
||||||
.location
|
.location
|
||||||
|
.as_ref()
|
||||||
.map(|location| Location {
|
.map(|location| Location {
|
||||||
filename: location.file.unwrap_or("??").to_owned(),
|
filename: location.file.unwrap_or("??").to_owned(),
|
||||||
line: location.line.unwrap_or(0),
|
line: location.line.unwrap_or(0),
|
||||||
|
col: location.column.unwrap_or(0),
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
@ -84,12 +98,51 @@ fn print_address(
|
||||||
location.line.to_string().green()
|
location.line.to_string().green()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if include_code && location.line != 0 {
|
||||||
|
print_line_of_code(&frame, location)?;
|
||||||
|
}
|
||||||
|
|
||||||
is_first = false;
|
is_first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_line_of_code(
|
||||||
|
frame: &addr2line::Frame<'_, impl gimli::Reader>,
|
||||||
|
location: Location,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let Some(filename) = frame.location.as_ref().and_then(|location| location.file) else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(mut file) = File::open(filename) else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut content = String::new();
|
||||||
|
file.read_to_string(&mut content)?;
|
||||||
|
|
||||||
|
let Some(line_of_code) = content.split('\n').nth(location.line as usize - 1) else {
|
||||||
|
eprintln!("File {filename} does not have line {}", location.line);
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let trimmed = line_of_code.trim_start();
|
||||||
|
let trimmed_len = line_of_code.len() - trimmed.len();
|
||||||
|
println!("\t\t{}", trimmed);
|
||||||
|
|
||||||
|
if location.col != 0 {
|
||||||
|
println!(
|
||||||
|
"\t\t{}{}",
|
||||||
|
" ".repeat(location.col as usize - trimmed_len - 1),
|
||||||
|
"^".bright_blue()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn prettify_path(path: &str) -> Cow<'_, str> {
|
fn prettify_path(path: &str) -> Cow<'_, str> {
|
||||||
if let Some(src_index) = path.rfind("/src/") {
|
if let Some(src_index) = path.rfind("/src/") {
|
||||||
let crate_name_start = path[0..src_index].rfind('/');
|
let crate_name_start = path[0..src_index].rfind('/');
|
||||||
|
|
Loading…
Reference in a new issue