Skip to content

Commit eef9598

Browse files
committed
Add DWARF 2+ line info support
Resolves #37
1 parent 405a2a8 commit eef9598

File tree

7 files changed

+69
-21
lines changed

7 files changed

+69
-21
lines changed

Cargo.lock

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ filetime = "0.2.23"
3838
flagset = "0.4.4"
3939
float-ord = "0.3.2"
4040
font-kit = "0.12.0"
41+
gimli = { version = "0.28.1", default-features = false, features = ["read-all"] }
4142
globset = { version = "0.4.14", features = ["serde1"] }
4243
log = "0.4.20"
4344
memmap2 = "0.9.3"

src/diff/code.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn no_diff_code(
2323
data: &[u8],
2424
symbol: &mut ObjSymbol,
2525
relocs: &[ObjReloc],
26-
line_info: &Option<BTreeMap<u32, u32>>,
26+
line_info: &Option<BTreeMap<u64, u64>>,
2727
) -> Result<()> {
2828
let code =
2929
&data[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
@@ -57,8 +57,8 @@ pub fn diff_code(
5757
right_symbol: &mut ObjSymbol,
5858
left_relocs: &[ObjReloc],
5959
right_relocs: &[ObjReloc],
60-
left_line_info: &Option<BTreeMap<u32, u32>>,
61-
right_line_info: &Option<BTreeMap<u32, u32>>,
60+
left_line_info: &Option<BTreeMap<u64, u64>>,
61+
right_line_info: &Option<BTreeMap<u64, u64>>,
6262
) -> Result<()> {
6363
let left_code = &left_data[left_symbol.section_address as usize
6464
..(left_symbol.section_address + left_symbol.size) as usize];

src/obj/elf.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
use std::{collections::BTreeMap, fs, io::Cursor, path::Path};
1+
use std::{borrow::Cow, collections::BTreeMap, fs, io::Cursor, path::Path};
22

33
use anyhow::{anyhow, bail, Context, Result};
44
use byteorder::{BigEndian, ReadBytesExt};
55
use cwdemangle::demangle;
66
use filetime::FileTime;
77
use flagset::Flags;
88
use object::{
9-
elf, Architecture, File, Object, ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget,
10-
SectionIndex, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
9+
elf, Architecture, Endianness, File, Object, ObjectSection, ObjectSymbol, RelocationKind,
10+
RelocationTarget, SectionIndex, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
1111
};
1212

1313
use crate::obj::{
@@ -278,30 +278,59 @@ fn relocations_by_section(
278278
Ok(relocations)
279279
}
280280

281-
fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u32, u32>>> {
281+
fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u64, u64>>> {
282+
// DWARF 1.1
283+
let mut map = BTreeMap::new();
282284
if let Some(section) = obj_file.section_by_name(".line") {
283285
if section.size() == 0 {
284286
return Ok(None);
285287
}
286288
let data = section.uncompressed_data()?;
287289
let mut reader = Cursor::new(data.as_ref());
288290

289-
let mut map = BTreeMap::new();
290291
let size = reader.read_u32::<BigEndian>()?;
291-
let base_address = reader.read_u32::<BigEndian>()?;
292+
let base_address = reader.read_u32::<BigEndian>()? as u64;
292293
while reader.position() < size as u64 {
293-
let line_number = reader.read_u32::<BigEndian>()?;
294+
let line_number = reader.read_u32::<BigEndian>()? as u64;
294295
let statement_pos = reader.read_u16::<BigEndian>()?;
295296
if statement_pos != 0xFFFF {
296297
log::warn!("Unhandled statement pos {}", statement_pos);
297298
}
298-
let address_delta = reader.read_u32::<BigEndian>()?;
299+
let address_delta = reader.read_u32::<BigEndian>()? as u64;
299300
map.insert(base_address + address_delta, line_number);
300301
}
301-
// log::debug!("Line info: {map:#X?}");
302-
return Ok(Some(map));
303302
}
304-
Ok(None)
303+
304+
// DWARF 2+
305+
let dwarf_cow = gimli::Dwarf::load(|id| {
306+
Ok::<_, gimli::Error>(
307+
obj_file
308+
.section_by_name(id.name())
309+
.and_then(|section| section.uncompressed_data().ok())
310+
.unwrap_or(Cow::Borrowed(&[][..])),
311+
)
312+
})?;
313+
let endian = match obj_file.endianness() {
314+
Endianness::Little => gimli::RunTimeEndian::Little,
315+
Endianness::Big => gimli::RunTimeEndian::Big,
316+
};
317+
let dwarf = dwarf_cow.borrow(|section| gimli::EndianSlice::new(section, endian));
318+
let mut iter = dwarf.units();
319+
while let Some(header) = iter.next()? {
320+
let unit = dwarf.unit(header)?;
321+
if let Some(program) = unit.line_program.clone() {
322+
let mut rows = program.rows();
323+
while let Some((_header, row)) = rows.next_row()? {
324+
if let Some(line) = row.line() {
325+
map.insert(row.address(), line.get());
326+
}
327+
}
328+
}
329+
}
330+
if map.is_empty() {
331+
return Ok(None);
332+
}
333+
Ok(Some(map))
305334
}
306335

307336
pub fn read(obj_path: &Path) -> Result<ObjInfo> {

src/obj/mips.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub fn process_code(
1919
start_address: u64,
2020
end_address: u64,
2121
relocs: &[ObjReloc],
22-
line_info: &Option<BTreeMap<u32, u32>>,
22+
line_info: &Option<BTreeMap<u64, u64>>,
2323
) -> Result<ProcessCodeResult> {
2424
configure_rabbitizer();
2525

@@ -83,8 +83,9 @@ pub fn process_code(
8383
}
8484
}
8585
}
86-
let line =
87-
line_info.as_ref().and_then(|map| map.range(..=cur_addr).last().map(|(_, &b)| b));
86+
let line = line_info
87+
.as_ref()
88+
.and_then(|map| map.range(..=cur_addr as u64).last().map(|(_, &b)| b));
8889
insts.push(ObjIns {
8990
address: cur_addr,
9091
code,

src/obj/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub struct ObjIns {
113113
pub reloc: Option<ObjReloc>,
114114
pub branch_dest: Option<u32>,
115115
/// Line info
116-
pub line: Option<u32>,
116+
pub line: Option<u64>,
117117
/// Original (unsimplified) instruction
118118
pub orig: Option<String>,
119119
}
@@ -172,7 +172,7 @@ pub struct ObjInfo {
172172
pub timestamp: FileTime,
173173
pub sections: Vec<ObjSection>,
174174
pub common: Vec<ObjSymbol>,
175-
pub line_info: Option<BTreeMap<u32, u32>>,
175+
pub line_info: Option<BTreeMap<u64, u64>>,
176176
}
177177
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
178178
pub enum ObjRelocKind {

src/obj/ppc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub fn process_code(
2424
data: &[u8],
2525
address: u64,
2626
relocs: &[ObjReloc],
27-
line_info: &Option<BTreeMap<u32, u32>>,
27+
line_info: &Option<BTreeMap<u64, u64>>,
2828
) -> Result<ProcessCodeResult> {
2929
let ins_count = data.len() / 4;
3030
let mut ops = Vec::<u8>::with_capacity(ins_count);
@@ -82,7 +82,7 @@ pub fn process_code(
8282
ops.push(simplified.ins.op as u8);
8383
let line = line_info
8484
.as_ref()
85-
.and_then(|map| map.range(..=simplified.ins.addr).last().map(|(_, &b)| b));
85+
.and_then(|map| map.range(..=simplified.ins.addr as u64).last().map(|(_, &b)| b));
8686
insts.push(ObjIns {
8787
address: simplified.ins.addr,
8888
code: simplified.ins.code,

0 commit comments

Comments
 (0)