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],
symbol: &mut ObjSymbol,
relocs: &[ObjReloc],
line_info: &Option<BTreeMap<u32, u32>>,
) -> 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::<ObjInsDiff>::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<BTreeMap<u32, u32>>,
right_line_info: &Option<BTreeMap<u32, u32>>,
) -> 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,
)?;
}
}

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 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<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> {
let data = {
let file = fs::File::open(obj_path)?;
@ -305,6 +332,7 @@ pub fn read(obj_path: &Path) -> Result<ObjInfo> {
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)?;

View File

@ -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<BTreeMap<u32, u32>>,
) -> Result<(Vec<u8>, Vec<ObjIns>)> {
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;
}

View File

@ -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<ObjInsArg>,
pub reloc: Option<ObjReloc>,
pub branch_dest: Option<u32>,
/// Line info
pub line: Option<u32>,
}
#[derive(Debug, Clone, Default)]
pub struct ObjInsDiff {
@ -138,6 +140,7 @@ pub struct ObjInfo {
pub path: PathBuf,
pub sections: Vec<ObjSection>,
pub common: Vec<ObjSymbol>,
pub line_info: Option<BTreeMap<u32, u32>>,
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum ObjRelocKind {

View File

@ -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<BTreeMap<u32, u32>>,
) -> Result<(Vec<u8>, Vec<ObjIns>)> {
let ins_count = data.len() / 4;
let mut ops = Vec::<u8>::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))

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::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(),