|
1 | | -use std::{collections::BTreeMap, fs, io::Cursor, path::Path}; |
| 1 | +use std::{borrow::Cow, collections::BTreeMap, fs, io::Cursor, path::Path}; |
2 | 2 |
|
3 | 3 | use anyhow::{anyhow, bail, Context, Result}; |
4 | 4 | use byteorder::{BigEndian, ReadBytesExt}; |
5 | 5 | use cwdemangle::demangle; |
6 | 6 | use filetime::FileTime; |
7 | 7 | use flagset::Flags; |
8 | 8 | 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, |
11 | 11 | }; |
12 | 12 |
|
13 | 13 | use crate::obj::{ |
@@ -278,30 +278,59 @@ fn relocations_by_section( |
278 | 278 | Ok(relocations) |
279 | 279 | } |
280 | 280 |
|
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(); |
282 | 284 | if let Some(section) = obj_file.section_by_name(".line") { |
283 | 285 | if section.size() == 0 { |
284 | 286 | return Ok(None); |
285 | 287 | } |
286 | 288 | let data = section.uncompressed_data()?; |
287 | 289 | let mut reader = Cursor::new(data.as_ref()); |
288 | 290 |
|
289 | | - let mut map = BTreeMap::new(); |
290 | 291 | let size = reader.read_u32::<BigEndian>()?; |
291 | | - let base_address = reader.read_u32::<BigEndian>()?; |
| 292 | + let base_address = reader.read_u32::<BigEndian>()? as u64; |
292 | 293 | while reader.position() < size as u64 { |
293 | | - let line_number = reader.read_u32::<BigEndian>()?; |
| 294 | + let line_number = reader.read_u32::<BigEndian>()? as u64; |
294 | 295 | let statement_pos = reader.read_u16::<BigEndian>()?; |
295 | 296 | if statement_pos != 0xFFFF { |
296 | 297 | log::warn!("Unhandled statement pos {}", statement_pos); |
297 | 298 | } |
298 | | - let address_delta = reader.read_u32::<BigEndian>()?; |
| 299 | + let address_delta = reader.read_u32::<BigEndian>()? as u64; |
299 | 300 | map.insert(base_address + address_delta, line_number); |
300 | 301 | } |
301 | | - // log::debug!("Line info: {map:#X?}"); |
302 | | - return Ok(Some(map)); |
303 | 302 | } |
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)) |
305 | 334 | } |
306 | 335 |
|
307 | 336 | pub fn read(obj_path: &Path) -> Result<ObjInfo> { |
|
0 commit comments