Skip to content

Commit bea0a00

Browse files
committed
Initial support for line number info
1 parent ba74d63 commit bea0a00

File tree

6 files changed

+74
-14
lines changed

6 files changed

+74
-14
lines changed

src/diff.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,19 @@ fn no_diff_code(
1717
data: &[u8],
1818
symbol: &mut ObjSymbol,
1919
relocs: &[ObjReloc],
20+
line_info: &Option<BTreeMap<u32, u32>>,
2021
) -> Result<()> {
2122
let code =
2223
&data[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
2324
let (_, ins) = match arch {
24-
ObjArchitecture::PowerPc => ppc::process_code(code, symbol.address, relocs)?,
25-
ObjArchitecture::Mips => {
26-
mips::process_code(code, symbol.address, symbol.address + symbol.size, relocs)?
27-
}
25+
ObjArchitecture::PowerPc => ppc::process_code(code, symbol.address, relocs, line_info)?,
26+
ObjArchitecture::Mips => mips::process_code(
27+
code,
28+
symbol.address,
29+
symbol.address + symbol.size,
30+
relocs,
31+
line_info,
32+
)?,
2833
};
2934

3035
let mut diff = Vec::<ObjInsDiff>::new();
@@ -36,6 +41,7 @@ fn no_diff_code(
3641
Ok(())
3742
}
3843

44+
#[allow(clippy::too_many_arguments)]
3945
pub fn diff_code(
4046
arch: ObjArchitecture,
4147
left_data: &[u8],
@@ -44,28 +50,32 @@ pub fn diff_code(
4450
right_symbol: &mut ObjSymbol,
4551
left_relocs: &[ObjReloc],
4652
right_relocs: &[ObjReloc],
53+
left_line_info: &Option<BTreeMap<u32, u32>>,
54+
right_line_info: &Option<BTreeMap<u32, u32>>,
4755
) -> Result<()> {
4856
let left_code = &left_data[left_symbol.section_address as usize
4957
..(left_symbol.section_address + left_symbol.size) as usize];
5058
let right_code = &right_data[right_symbol.section_address as usize
5159
..(right_symbol.section_address + right_symbol.size) as usize];
5260
let ((left_ops, left_insts), (right_ops, right_insts)) = match arch {
5361
ObjArchitecture::PowerPc => (
54-
ppc::process_code(left_code, left_symbol.address, left_relocs)?,
55-
ppc::process_code(right_code, right_symbol.address, right_relocs)?,
62+
ppc::process_code(left_code, left_symbol.address, left_relocs, left_line_info)?,
63+
ppc::process_code(right_code, right_symbol.address, right_relocs, right_line_info)?,
5664
),
5765
ObjArchitecture::Mips => (
5866
mips::process_code(
5967
left_code,
6068
left_symbol.address,
6169
left_symbol.address + left_symbol.size,
6270
left_relocs,
71+
left_line_info,
6372
)?,
6473
mips::process_code(
6574
right_code,
6675
right_symbol.address,
6776
left_symbol.address + left_symbol.size,
6877
right_relocs,
78+
right_line_info,
6979
)?,
7080
),
7181
};
@@ -353,17 +363,13 @@ fn compare_ins(
353363
Ok(result)
354364
}
355365

356-
fn find_section<'a>(obj: &'a mut ObjInfo, name: &str) -> Option<&'a mut ObjSection> {
357-
obj.sections.iter_mut().find(|s| s.name == name)
358-
}
359-
360366
fn find_symbol<'a>(symbols: &'a mut [ObjSymbol], name: &str) -> Option<&'a mut ObjSymbol> {
361367
symbols.iter_mut().find(|s| s.name == name)
362368
}
363369

364370
pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffConfig) -> Result<()> {
365371
for left_section in &mut left.sections {
366-
let Some(right_section) = find_section(right, &left_section.name) else {
372+
let Some(right_section) = right.sections.iter_mut().find(|s| s.name == left_section.name) else {
367373
continue;
368374
};
369375
if left_section.kind == ObjSectionKind::Code {
@@ -381,13 +387,16 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon
381387
right_symbol,
382388
&left_section.relocations,
383389
&right_section.relocations,
390+
&left.line_info,
391+
&right.line_info,
384392
)?;
385393
} else {
386394
no_diff_code(
387395
left.architecture,
388396
&left_section.data,
389397
left_symbol,
390398
&left_section.relocations,
399+
&left.line_info,
391400
)?;
392401
}
393402
}
@@ -398,6 +407,7 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon
398407
&right_section.data,
399408
right_symbol,
400409
&right_section.relocations,
410+
&left.line_info,
401411
)?;
402412
}
403413
}

src/obj/elf.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use std::{fs, path::Path};
1+
use std::{collections::BTreeMap, fs, io::Cursor, path::Path};
22

33
use anyhow::{Context, Result};
4+
use byteorder::{BigEndian, ReadBytesExt};
45
use cwdemangle::demangle;
56
use flagset::Flags;
67
use object::{
@@ -284,6 +285,32 @@ fn relocations_by_section(
284285
Ok(relocations)
285286
}
286287

288+
fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u32, u32>>> {
289+
if let Some(section) = obj_file.section_by_name(".line") {
290+
if section.size() == 0 {
291+
return Ok(None);
292+
}
293+
let data = section.uncompressed_data()?;
294+
let mut reader = Cursor::new(data.as_ref());
295+
296+
let mut map = BTreeMap::new();
297+
let size = reader.read_u32::<BigEndian>()?;
298+
let base_address = reader.read_u32::<BigEndian>()?;
299+
while reader.position() < size as u64 {
300+
let line_number = reader.read_u32::<BigEndian>()?;
301+
let statement_pos = reader.read_u16::<BigEndian>()?;
302+
if statement_pos != 0xFFFF {
303+
log::warn!("Unhandled statement pos {}", statement_pos);
304+
}
305+
let address_delta = reader.read_u32::<BigEndian>()?;
306+
map.insert(base_address + address_delta, line_number);
307+
}
308+
println!("Line info: {:#X?}", map);
309+
return Ok(Some(map));
310+
}
311+
Ok(None)
312+
}
313+
287314
pub fn read(obj_path: &Path) -> Result<ObjInfo> {
288315
let data = {
289316
let file = fs::File::open(obj_path)?;
@@ -305,6 +332,7 @@ pub fn read(obj_path: &Path) -> Result<ObjInfo> {
305332
path: obj_path.to_owned(),
306333
sections: filter_sections(&obj_file)?,
307334
common: common_symbols(&obj_file)?,
335+
line_info: line_info(&obj_file)?,
308336
};
309337
for section in &mut result.sections {
310338
section.symbols = symbols_by_section(&obj_file, section)?;

src/obj/mips.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::BTreeMap;
2+
13
use anyhow::Result;
24
use rabbitizer::{config_set_register_fpr_abi_names, Abi, Instruction, SimpleOperandType};
35

@@ -8,6 +10,7 @@ pub fn process_code(
810
start_address: u64,
911
end_address: u64,
1012
relocs: &[ObjReloc],
13+
line_info: &Option<BTreeMap<u32, u32>>,
1114
) -> Result<(Vec<u8>, Vec<ObjIns>)> {
1215
config_set_register_fpr_abi_names(Abi::RABBITIZER_ABI_O32);
1316

@@ -59,6 +62,8 @@ pub fn process_code(
5962
_ => ObjInsArg::MipsArg(op.disassembled.clone()),
6063
})
6164
.collect();
65+
let line =
66+
line_info.as_ref().and_then(|map| map.range(..=cur_addr).last().map(|(_, &b)| b));
6267
insts.push(ObjIns {
6368
address: cur_addr,
6469
code,
@@ -67,6 +72,7 @@ pub fn process_code(
6772
args,
6873
reloc: reloc.cloned(),
6974
branch_dest,
75+
line,
7076
});
7177
cur_addr += 4;
7278
}

src/obj/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ pub mod elf;
22
pub mod mips;
33
pub mod ppc;
44

5-
use std::path::PathBuf;
5+
use std::{collections::BTreeMap, path::PathBuf};
66

77
use flagset::{flags, FlagSet};
88

@@ -83,6 +83,8 @@ pub struct ObjIns {
8383
pub args: Vec<ObjInsArg>,
8484
pub reloc: Option<ObjReloc>,
8585
pub branch_dest: Option<u32>,
86+
/// Line info
87+
pub line: Option<u32>,
8688
}
8789
#[derive(Debug, Clone, Default)]
8890
pub struct ObjInsDiff {
@@ -138,6 +140,7 @@ pub struct ObjInfo {
138140
pub path: PathBuf,
139141
pub sections: Vec<ObjSection>,
140142
pub common: Vec<ObjSymbol>,
143+
pub line_info: Option<BTreeMap<u32, u32>>,
141144
}
142145
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
143146
pub enum ObjRelocKind {

src/obj/ppc.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::BTreeMap;
2+
13
use anyhow::Result;
24
use ppc750cl::{disasm_iter, Argument};
35

@@ -19,6 +21,7 @@ pub fn process_code(
1921
data: &[u8],
2022
address: u64,
2123
relocs: &[ObjReloc],
24+
line_info: &Option<BTreeMap<u32, u32>>,
2225
) -> Result<(Vec<u8>, Vec<ObjIns>)> {
2326
let ins_count = data.len() / 4;
2427
let mut ops = Vec::<u8>::with_capacity(ins_count);
@@ -74,6 +77,9 @@ pub fn process_code(
7477
}
7578
}
7679
ops.push(simplified.ins.op as u8);
80+
let line = line_info
81+
.as_ref()
82+
.and_then(|map| map.range(..=simplified.ins.addr).last().map(|(_, &b)| b));
7783
insts.push(ObjIns {
7884
address: simplified.ins.addr,
7985
code: simplified.ins.code,
@@ -82,6 +88,7 @@ pub fn process_code(
8288
reloc: reloc.cloned(),
8389
op: 0,
8490
branch_dest: None,
91+
line,
8592
});
8693
}
8794
Ok((ops, insts))

src/views/function_diff.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,14 @@ fn asm_row_ui(ui: &mut egui::Ui, ins_diff: &ObjInsDiff, symbol: &ObjSymbol, conf
264264
ObjInsDiffKind::Delete => COLOR_RED,
265265
ObjInsDiffKind::Insert => Color32::GREEN,
266266
};
267+
let mut pad = 6;
268+
if let Some(line) = ins.line {
269+
let line_str = format!("{line} ");
270+
write_text(&line_str, Color32::DARK_GRAY, &mut job, config.code_font.clone());
271+
pad = 12 - line_str.len();
272+
}
267273
write_text(
268-
&format!("{:<6}", format!("{:x}:", ins.address - symbol.address as u32)),
274+
&format!("{:<1$}", format!("{:x}: ", ins.address - symbol.address as u32), pad),
269275
base_color,
270276
&mut job,
271277
config.code_font.clone(),

0 commit comments

Comments
 (0)