mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Allow loading of the dwarf information from the gba rom
This commit is contained in:
parent
25e15baa2b
commit
89f6a2782b
|
@ -15,6 +15,8 @@ addr2line = { version = "0.21", default-features = false, features = [
|
||||||
"std-object",
|
"std-object",
|
||||||
] }
|
] }
|
||||||
colored = "2"
|
colored = "2"
|
||||||
|
rmp-serde = "1"
|
||||||
|
lz4_flex = "0.11"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
74
agb-addr2line/src/load_dwarf.rs
Normal file
74
agb-addr2line/src/load_dwarf.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
use std::{borrow::Cow, collections::HashMap, io::Cursor, rc::Rc};
|
||||||
|
|
||||||
|
use addr2line::{
|
||||||
|
gimli,
|
||||||
|
object::{self, Object},
|
||||||
|
};
|
||||||
|
use anyhow::bail;
|
||||||
|
|
||||||
|
pub fn load_dwarf(
|
||||||
|
file_content: &[u8],
|
||||||
|
) -> anyhow::Result<gimli::Dwarf<gimli::EndianRcSlice<gimli::RunTimeEndian>>> {
|
||||||
|
if let Ok(object) = object::File::parse(file_content) {
|
||||||
|
return load_from_object(&object);
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_8_bytes = &file_content[file_content.len() - 8..];
|
||||||
|
let len = u32::from_le_bytes(last_8_bytes[0..4].try_into()?) as usize;
|
||||||
|
let version = u32::from_le_bytes(last_8_bytes[4..].try_into()?) as usize;
|
||||||
|
|
||||||
|
if version != 1 {
|
||||||
|
bail!("Only version 1 of the debug info is supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
let compressed_debug_data = &file_content[file_content.len() - len - 8..file_content.len() - 8];
|
||||||
|
|
||||||
|
let decompressing_reader =
|
||||||
|
lz4_flex::frame::FrameDecoder::new(Cursor::new(compressed_debug_data));
|
||||||
|
let debug_info: HashMap<String, Vec<u8>> = rmp_serde::decode::from_read(decompressing_reader)?;
|
||||||
|
|
||||||
|
let dwarf = gimli::Dwarf::load(|id| {
|
||||||
|
let data = debug_info
|
||||||
|
.get(id.name())
|
||||||
|
.map(|data| Cow::Borrowed(data.as_slice()))
|
||||||
|
.unwrap_or(Cow::Borrowed(&[]));
|
||||||
|
|
||||||
|
Result::<_, gimli::Error>::Ok(gimli::EndianRcSlice::new(
|
||||||
|
Rc::from(&*data),
|
||||||
|
gimli::RunTimeEndian::Little,
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(dwarf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_from_object<'file>(
|
||||||
|
object: &object::File<'file, &'file [u8]>,
|
||||||
|
) -> anyhow::Result<gimli::Dwarf<gimli::EndianRcSlice<gimli::RunTimeEndian>>> {
|
||||||
|
let endian = if object.is_little_endian() {
|
||||||
|
gimli::RunTimeEndian::Little
|
||||||
|
} else {
|
||||||
|
gimli::RunTimeEndian::Big
|
||||||
|
};
|
||||||
|
|
||||||
|
fn load_section<'data: 'file, 'file, O, Endian>(
|
||||||
|
id: gimli::SectionId,
|
||||||
|
file: &'file O,
|
||||||
|
endian: Endian,
|
||||||
|
) -> Result<gimli::EndianRcSlice<Endian>, gimli::Error>
|
||||||
|
where
|
||||||
|
O: object::Object<'data, 'file>,
|
||||||
|
Endian: gimli::Endianity,
|
||||||
|
{
|
||||||
|
use object::ObjectSection;
|
||||||
|
|
||||||
|
let data = file
|
||||||
|
.section_by_name(id.name())
|
||||||
|
.and_then(|section| section.uncompressed_data().ok())
|
||||||
|
.unwrap_or(Cow::Borrowed(&[]));
|
||||||
|
Ok(gimli::EndianRcSlice::new(Rc::from(&*data), endian))
|
||||||
|
}
|
||||||
|
|
||||||
|
let dwarf = gimli::Dwarf::load(|id| load_section(id, object, endian))?;
|
||||||
|
Ok(dwarf)
|
||||||
|
}
|
|
@ -6,11 +6,13 @@ use std::{
|
||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
use addr2line::{gimli, object};
|
use addr2line::gimli;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use load_dwarf::load_dwarf;
|
||||||
|
|
||||||
mod gwilym_encoding;
|
mod gwilym_encoding;
|
||||||
|
mod load_dwarf;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
|
@ -46,9 +48,9 @@ fn main() -> anyhow::Result<()> {
|
||||||
.unwrap_or(SystemTime::UNIX_EPOCH);
|
.unwrap_or(SystemTime::UNIX_EPOCH);
|
||||||
|
|
||||||
let file = fs::read(&cli.elf_path)?;
|
let file = fs::read(&cli.elf_path)?;
|
||||||
let object = object::File::parse(file.as_slice())?;
|
let dwarf = load_dwarf(&file)?;
|
||||||
|
|
||||||
let ctx = addr2line::Context::new(&object)?;
|
let ctx = addr2line::Context::from_dwarf(dwarf)?;
|
||||||
|
|
||||||
for (i, address) in gwilym_encoding::gwilym_decode(&cli.dump)?.enumerate() {
|
for (i, address) in gwilym_encoding::gwilym_decode(&cli.dump)?.enumerate() {
|
||||||
print_address(&ctx, i, address.into(), modification_time)?;
|
print_address(&ctx, i, address.into(), modification_time)?;
|
||||||
|
|
Loading…
Reference in a new issue