Initial support for line number info

This commit is contained in:
Luke Street 2023-01-21 00:03:56 -05:00
parent ba74d63a99
commit bea0a0007d
6 changed files with 74 additions and 14 deletions

View File

@ -17,14 +17,19 @@ fn no_diff_code(
data: &[u8], data: &[u8],
symbol: &mut ObjSymbol, symbol: &mut ObjSymbol,
relocs: &[ObjReloc], relocs: &[ObjReloc],
line_info: &Option<BTreeMap<u32, u32>>,
) -> Result<()> { ) -> Result<()> {
let code = let code =
&data[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize]; &data[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
let (_, ins) = match arch { let (_, ins) = match arch {
ObjArchitecture::PowerPc => ppc::process_code(code, symbol.address, relocs)?, ObjArchitecture::PowerPc => ppc::process_code(code, symbol.address, relocs, line_info)?,
ObjArchitecture::Mips => { ObjArchitecture::Mips => mips::process_code(
mips::process_code(code, symbol.address, symbol.address + symbol.size, relocs)? code,
} symbol.address,
symbol.address + symbol.size,
relocs,
line_info,
)?,
}; };
let mut diff = Vec::<ObjInsDiff>::new(); let mut diff = Vec::<ObjInsDiff>::new();
@ -36,6 +41,7 @@ fn no_diff_code(
Ok(()) Ok(())
} }
#[allow(clippy::too_many_arguments)]
pub fn diff_code( pub fn diff_code(
arch: ObjArchitecture, arch: ObjArchitecture,
left_data: &[u8], left_data: &[u8],
@ -44,6 +50,8 @@ pub fn diff_code(
right_symbol: &mut ObjSymbol, right_symbol: &mut ObjSymbol,
left_relocs: &[ObjReloc], left_relocs: &[ObjReloc],
right_relocs: &[ObjReloc], right_relocs: &[ObjReloc],
left_line_info: &Option<BTreeMap<u32, u32>>,
right_line_info: &Option<BTreeMap<u32, u32>>,
) -> Result<()> { ) -> Result<()> {
let left_code = &left_data[left_symbol.section_address as usize let left_code = &left_data[left_symbol.section_address as usize
..(left_symbol.section_address + left_symbol.size) 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]; ..(right_symbol.section_address + right_symbol.size) as usize];
let ((left_ops, left_insts), (right_ops, right_insts)) = match arch { let ((left_ops, left_insts), (right_ops, right_insts)) = match arch {
ObjArchitecture::PowerPc => ( ObjArchitecture::PowerPc => (
ppc::process_code(left_code, left_symbol.address, left_relocs)?, ppc::process_code(left_code, left_symbol.address, left_relocs, left_line_info)?,
ppc::process_code(right_code, right_symbol.address, right_relocs)?, ppc::process_code(right_code, right_symbol.address, right_relocs, right_line_info)?,
), ),
ObjArchitecture::Mips => ( ObjArchitecture::Mips => (
mips::process_code( mips::process_code(
@ -60,12 +68,14 @@ pub fn diff_code(
left_symbol.address, left_symbol.address,
left_symbol.address + left_symbol.size, left_symbol.address + left_symbol.size,
left_relocs, left_relocs,
left_line_info,
)?, )?,
mips::process_code( mips::process_code(
right_code, right_code,
right_symbol.address, right_symbol.address,
left_symbol.address + left_symbol.size, left_symbol.address + left_symbol.size,
right_relocs, right_relocs,
right_line_info,
)?, )?,
), ),
}; };
@ -353,17 +363,13 @@ fn compare_ins(
Ok(result) 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> { fn find_symbol<'a>(symbols: &'a mut [ObjSymbol], name: &str) -> Option<&'a mut ObjSymbol> {
symbols.iter_mut().find(|s| s.name == name) symbols.iter_mut().find(|s| s.name == name)
} }
pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffConfig) -> Result<()> { pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffConfig) -> Result<()> {
for left_section in &mut left.sections { 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; continue;
}; };
if left_section.kind == ObjSectionKind::Code { 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, right_symbol,
&left_section.relocations, &left_section.relocations,
&right_section.relocations, &right_section.relocations,
&left.line_info,
&right.line_info,
)?; )?;
} else { } else {
no_diff_code( no_diff_code(
@ -388,6 +396,7 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon
&left_section.data, &left_section.data,
left_symbol, left_symbol,
&left_section.relocations, &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_section.data,
right_symbol, right_symbol,
&right_section.relocations, &right_section.relocations,
&left.line_info,
)?; )?;
} }
} }

View File

@ -1,6 +1,7 @@
use std::{fs, path::Path}; use std::{collections::BTreeMap, fs, io::Cursor, path::Path};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use byteorder::{BigEndian, ReadBytesExt};
use cwdemangle::demangle; use cwdemangle::demangle;
use flagset::Flags; use flagset::Flags;
use object::{ use object::{
@ -284,6 +285,32 @@ fn relocations_by_section(
Ok(relocations) Ok(relocations)
} }
fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u32, u32>>> {
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::<BigEndian>()?;
let base_address = reader.read_u32::<BigEndian>()?;
while reader.position() < size as u64 {
let line_number = reader.read_u32::<BigEndian>()?;
let statement_pos = reader.read_u16::<BigEndian>()?;
if statement_pos != 0xFFFF {
log::warn!("Unhandled statement pos {}", statement_pos);
}
let address_delta = reader.read_u32::<BigEndian>()?;
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<ObjInfo> { pub fn read(obj_path: &Path) -> Result<ObjInfo> {
let data = { let data = {
let file = fs::File::open(obj_path)?; let file = fs::File::open(obj_path)?;
@ -305,6 +332,7 @@ pub fn read(obj_path: &Path) -> Result<ObjInfo> {
path: obj_path.to_owned(), path: obj_path.to_owned(),
sections: filter_sections(&obj_file)?, sections: filter_sections(&obj_file)?,
common: common_symbols(&obj_file)?, common: common_symbols(&obj_file)?,
line_info: line_info(&obj_file)?,
}; };
for section in &mut result.sections { for section in &mut result.sections {
section.symbols = symbols_by_section(&obj_file, section)?; section.symbols = symbols_by_section(&obj_file, section)?;

View File

@ -1,3 +1,5 @@
use std::collections::BTreeMap;
use anyhow::Result; use anyhow::Result;
use rabbitizer::{config_set_register_fpr_abi_names, Abi, Instruction, SimpleOperandType}; use rabbitizer::{config_set_register_fpr_abi_names, Abi, Instruction, SimpleOperandType};
@ -8,6 +10,7 @@ pub fn process_code(
start_address: u64, start_address: u64,
end_address: u64, end_address: u64,
relocs: &[ObjReloc], relocs: &[ObjReloc],
line_info: &Option<BTreeMap<u32, u32>>,
) -> Result<(Vec<u8>, Vec<ObjIns>)> { ) -> Result<(Vec<u8>, Vec<ObjIns>)> {
config_set_register_fpr_abi_names(Abi::RABBITIZER_ABI_O32); config_set_register_fpr_abi_names(Abi::RABBITIZER_ABI_O32);
@ -59,6 +62,8 @@ pub fn process_code(
_ => ObjInsArg::MipsArg(op.disassembled.clone()), _ => ObjInsArg::MipsArg(op.disassembled.clone()),
}) })
.collect(); .collect();
let line =
line_info.as_ref().and_then(|map| map.range(..=cur_addr).last().map(|(_, &b)| b));
insts.push(ObjIns { insts.push(ObjIns {
address: cur_addr, address: cur_addr,
code, code,
@ -67,6 +72,7 @@ pub fn process_code(
args, args,
reloc: reloc.cloned(), reloc: reloc.cloned(),
branch_dest, branch_dest,
line,
}); });
cur_addr += 4; cur_addr += 4;
} }

View File

@ -2,7 +2,7 @@ pub mod elf;
pub mod mips; pub mod mips;
pub mod ppc; pub mod ppc;
use std::path::PathBuf; use std::{collections::BTreeMap, path::PathBuf};
use flagset::{flags, FlagSet}; use flagset::{flags, FlagSet};
@ -83,6 +83,8 @@ pub struct ObjIns {
pub args: Vec<ObjInsArg>, pub args: Vec<ObjInsArg>,
pub reloc: Option<ObjReloc>, pub reloc: Option<ObjReloc>,
pub branch_dest: Option<u32>, pub branch_dest: Option<u32>,
/// Line info
pub line: Option<u32>,
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct ObjInsDiff { pub struct ObjInsDiff {
@ -138,6 +140,7 @@ pub struct ObjInfo {
pub path: PathBuf, pub path: PathBuf,
pub sections: Vec<ObjSection>, pub sections: Vec<ObjSection>,
pub common: Vec<ObjSymbol>, pub common: Vec<ObjSymbol>,
pub line_info: Option<BTreeMap<u32, u32>>,
} }
#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum ObjRelocKind { pub enum ObjRelocKind {

View File

@ -1,3 +1,5 @@
use std::collections::BTreeMap;
use anyhow::Result; use anyhow::Result;
use ppc750cl::{disasm_iter, Argument}; use ppc750cl::{disasm_iter, Argument};
@ -19,6 +21,7 @@ pub fn process_code(
data: &[u8], data: &[u8],
address: u64, address: u64,
relocs: &[ObjReloc], relocs: &[ObjReloc],
line_info: &Option<BTreeMap<u32, u32>>,
) -> Result<(Vec<u8>, Vec<ObjIns>)> { ) -> Result<(Vec<u8>, Vec<ObjIns>)> {
let ins_count = data.len() / 4; let ins_count = data.len() / 4;
let mut ops = Vec::<u8>::with_capacity(ins_count); let mut ops = Vec::<u8>::with_capacity(ins_count);
@ -74,6 +77,9 @@ pub fn process_code(
} }
} }
ops.push(simplified.ins.op as u8); 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 { insts.push(ObjIns {
address: simplified.ins.addr, address: simplified.ins.addr,
code: simplified.ins.code, code: simplified.ins.code,
@ -82,6 +88,7 @@ pub fn process_code(
reloc: reloc.cloned(), reloc: reloc.cloned(),
op: 0, op: 0,
branch_dest: None, branch_dest: None,
line,
}); });
} }
Ok((ops, insts)) Ok((ops, insts))

View File

@ -264,8 +264,14 @@ fn asm_row_ui(ui: &mut egui::Ui, ins_diff: &ObjInsDiff, symbol: &ObjSymbol, conf
ObjInsDiffKind::Delete => COLOR_RED, ObjInsDiffKind::Delete => COLOR_RED,
ObjInsDiffKind::Insert => Color32::GREEN, 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( 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, base_color,
&mut job, &mut job,
config.code_font.clone(), config.code_font.clone(),