diff --git a/src/diff.rs b/src/diff.rs index 1063f03..5401191 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -17,14 +17,19 @@ fn no_diff_code( data: &[u8], symbol: &mut ObjSymbol, relocs: &[ObjReloc], + line_info: &Option>, ) -> Result<()> { let code = &data[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize]; let (_, ins) = match arch { - ObjArchitecture::PowerPc => ppc::process_code(code, symbol.address, relocs)?, - ObjArchitecture::Mips => { - mips::process_code(code, symbol.address, symbol.address + symbol.size, relocs)? - } + ObjArchitecture::PowerPc => ppc::process_code(code, symbol.address, relocs, line_info)?, + ObjArchitecture::Mips => mips::process_code( + code, + symbol.address, + symbol.address + symbol.size, + relocs, + line_info, + )?, }; let mut diff = Vec::::new(); @@ -36,6 +41,7 @@ fn no_diff_code( Ok(()) } +#[allow(clippy::too_many_arguments)] pub fn diff_code( arch: ObjArchitecture, left_data: &[u8], @@ -44,6 +50,8 @@ pub fn diff_code( right_symbol: &mut ObjSymbol, left_relocs: &[ObjReloc], right_relocs: &[ObjReloc], + left_line_info: &Option>, + right_line_info: &Option>, ) -> Result<()> { let left_code = &left_data[left_symbol.section_address as usize ..(left_symbol.section_address + left_symbol.size) as usize]; @@ -51,8 +59,8 @@ pub fn diff_code( ..(right_symbol.section_address + right_symbol.size) as usize]; let ((left_ops, left_insts), (right_ops, right_insts)) = match arch { ObjArchitecture::PowerPc => ( - ppc::process_code(left_code, left_symbol.address, left_relocs)?, - ppc::process_code(right_code, right_symbol.address, right_relocs)?, + ppc::process_code(left_code, left_symbol.address, left_relocs, left_line_info)?, + ppc::process_code(right_code, right_symbol.address, right_relocs, right_line_info)?, ), ObjArchitecture::Mips => ( mips::process_code( @@ -60,12 +68,14 @@ pub fn diff_code( left_symbol.address, left_symbol.address + left_symbol.size, left_relocs, + left_line_info, )?, mips::process_code( right_code, right_symbol.address, left_symbol.address + left_symbol.size, right_relocs, + right_line_info, )?, ), }; @@ -353,17 +363,13 @@ fn compare_ins( Ok(result) } -fn find_section<'a>(obj: &'a mut ObjInfo, name: &str) -> Option<&'a mut ObjSection> { - obj.sections.iter_mut().find(|s| s.name == name) -} - fn find_symbol<'a>(symbols: &'a mut [ObjSymbol], name: &str) -> Option<&'a mut ObjSymbol> { symbols.iter_mut().find(|s| s.name == name) } pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffConfig) -> Result<()> { for left_section in &mut left.sections { - let Some(right_section) = find_section(right, &left_section.name) else { + let Some(right_section) = right.sections.iter_mut().find(|s| s.name == left_section.name) else { continue; }; if left_section.kind == ObjSectionKind::Code { @@ -381,6 +387,8 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon right_symbol, &left_section.relocations, &right_section.relocations, + &left.line_info, + &right.line_info, )?; } else { no_diff_code( @@ -388,6 +396,7 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon &left_section.data, left_symbol, &left_section.relocations, + &left.line_info, )?; } } @@ -398,6 +407,7 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon &right_section.data, right_symbol, &right_section.relocations, + &left.line_info, )?; } } diff --git a/src/obj/elf.rs b/src/obj/elf.rs index 98d2f0e..370f2b6 100644 --- a/src/obj/elf.rs +++ b/src/obj/elf.rs @@ -1,6 +1,7 @@ -use std::{fs, path::Path}; +use std::{collections::BTreeMap, fs, io::Cursor, path::Path}; use anyhow::{Context, Result}; +use byteorder::{BigEndian, ReadBytesExt}; use cwdemangle::demangle; use flagset::Flags; use object::{ @@ -284,6 +285,32 @@ fn relocations_by_section( Ok(relocations) } +fn line_info(obj_file: &File<'_>) -> Result>> { + if let Some(section) = obj_file.section_by_name(".line") { + if section.size() == 0 { + return Ok(None); + } + let data = section.uncompressed_data()?; + let mut reader = Cursor::new(data.as_ref()); + + let mut map = BTreeMap::new(); + let size = reader.read_u32::()?; + let base_address = reader.read_u32::()?; + while reader.position() < size as u64 { + let line_number = reader.read_u32::()?; + let statement_pos = reader.read_u16::()?; + if statement_pos != 0xFFFF { + log::warn!("Unhandled statement pos {}", statement_pos); + } + let address_delta = reader.read_u32::()?; + map.insert(base_address + address_delta, line_number); + } + println!("Line info: {:#X?}", map); + return Ok(Some(map)); + } + Ok(None) +} + pub fn read(obj_path: &Path) -> Result { let data = { let file = fs::File::open(obj_path)?; @@ -305,6 +332,7 @@ pub fn read(obj_path: &Path) -> Result { path: obj_path.to_owned(), sections: filter_sections(&obj_file)?, common: common_symbols(&obj_file)?, + line_info: line_info(&obj_file)?, }; for section in &mut result.sections { section.symbols = symbols_by_section(&obj_file, section)?; diff --git a/src/obj/mips.rs b/src/obj/mips.rs index 4374ece..a0e9a1d 100644 --- a/src/obj/mips.rs +++ b/src/obj/mips.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use anyhow::Result; use rabbitizer::{config_set_register_fpr_abi_names, Abi, Instruction, SimpleOperandType}; @@ -8,6 +10,7 @@ pub fn process_code( start_address: u64, end_address: u64, relocs: &[ObjReloc], + line_info: &Option>, ) -> Result<(Vec, Vec)> { config_set_register_fpr_abi_names(Abi::RABBITIZER_ABI_O32); @@ -59,6 +62,8 @@ pub fn process_code( _ => ObjInsArg::MipsArg(op.disassembled.clone()), }) .collect(); + let line = + line_info.as_ref().and_then(|map| map.range(..=cur_addr).last().map(|(_, &b)| b)); insts.push(ObjIns { address: cur_addr, code, @@ -67,6 +72,7 @@ pub fn process_code( args, reloc: reloc.cloned(), branch_dest, + line, }); cur_addr += 4; } diff --git a/src/obj/mod.rs b/src/obj/mod.rs index 09e8389..0bc58c6 100644 --- a/src/obj/mod.rs +++ b/src/obj/mod.rs @@ -2,7 +2,7 @@ pub mod elf; pub mod mips; pub mod ppc; -use std::path::PathBuf; +use std::{collections::BTreeMap, path::PathBuf}; use flagset::{flags, FlagSet}; @@ -83,6 +83,8 @@ pub struct ObjIns { pub args: Vec, pub reloc: Option, pub branch_dest: Option, + /// Line info + pub line: Option, } #[derive(Debug, Clone, Default)] pub struct ObjInsDiff { @@ -138,6 +140,7 @@ pub struct ObjInfo { pub path: PathBuf, pub sections: Vec, pub common: Vec, + pub line_info: Option>, } #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum ObjRelocKind { diff --git a/src/obj/ppc.rs b/src/obj/ppc.rs index 094ec38..85fe2e0 100644 --- a/src/obj/ppc.rs +++ b/src/obj/ppc.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use anyhow::Result; use ppc750cl::{disasm_iter, Argument}; @@ -19,6 +21,7 @@ pub fn process_code( data: &[u8], address: u64, relocs: &[ObjReloc], + line_info: &Option>, ) -> Result<(Vec, Vec)> { let ins_count = data.len() / 4; let mut ops = Vec::::with_capacity(ins_count); @@ -74,6 +77,9 @@ pub fn process_code( } } ops.push(simplified.ins.op as u8); + let line = line_info + .as_ref() + .and_then(|map| map.range(..=simplified.ins.addr).last().map(|(_, &b)| b)); insts.push(ObjIns { address: simplified.ins.addr, code: simplified.ins.code, @@ -82,6 +88,7 @@ pub fn process_code( reloc: reloc.cloned(), op: 0, branch_dest: None, + line, }); } Ok((ops, insts)) diff --git a/src/views/function_diff.rs b/src/views/function_diff.rs index 1408847..df63029 100644 --- a/src/views/function_diff.rs +++ b/src/views/function_diff.rs @@ -264,8 +264,14 @@ fn asm_row_ui(ui: &mut egui::Ui, ins_diff: &ObjInsDiff, symbol: &ObjSymbol, conf ObjInsDiffKind::Delete => COLOR_RED, ObjInsDiffKind::Insert => Color32::GREEN, }; + let mut pad = 6; + if let Some(line) = ins.line { + let line_str = format!("{line} "); + write_text(&line_str, Color32::DARK_GRAY, &mut job, config.code_font.clone()); + pad = 12 - line_str.len(); + } write_text( - &format!("{:<6}", format!("{:x}:", ins.address - symbol.address as u32)), + &format!("{:<1$}", format!("{:x}: ", ins.address - symbol.address as u32), pad), base_color, &mut job, config.code_font.clone(),