mirror of https://github.com/encounter/objdiff.git
parent
405a2a82db
commit
eef9598e76
|
@ -1483,6 +1483,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
|
@ -1820,6 +1826,10 @@ name = "gimli"
|
|||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||
dependencies = [
|
||||
"fallible-iterator",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio-sys"
|
||||
|
@ -2867,6 +2877,7 @@ dependencies = [
|
|||
"flagset",
|
||||
"float-ord",
|
||||
"font-kit",
|
||||
"gimli",
|
||||
"globset",
|
||||
"log",
|
||||
"memmap2",
|
||||
|
@ -3900,6 +3911,12 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
|
|
|
@ -38,6 +38,7 @@ filetime = "0.2.23"
|
|||
flagset = "0.4.4"
|
||||
float-ord = "0.3.2"
|
||||
font-kit = "0.12.0"
|
||||
gimli = { version = "0.28.1", default-features = false, features = ["read-all"] }
|
||||
globset = { version = "0.4.14", features = ["serde1"] }
|
||||
log = "0.4.20"
|
||||
memmap2 = "0.9.3"
|
||||
|
|
|
@ -23,7 +23,7 @@ pub fn no_diff_code(
|
|||
data: &[u8],
|
||||
symbol: &mut ObjSymbol,
|
||||
relocs: &[ObjReloc],
|
||||
line_info: &Option<BTreeMap<u32, u32>>,
|
||||
line_info: &Option<BTreeMap<u64, u64>>,
|
||||
) -> Result<()> {
|
||||
let code =
|
||||
&data[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
||||
|
@ -57,8 +57,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>>,
|
||||
left_line_info: &Option<BTreeMap<u64, u64>>,
|
||||
right_line_info: &Option<BTreeMap<u64, u64>>,
|
||||
) -> Result<()> {
|
||||
let left_code = &left_data[left_symbol.section_address as usize
|
||||
..(left_symbol.section_address + left_symbol.size) as usize];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::BTreeMap, fs, io::Cursor, path::Path};
|
||||
use std::{borrow::Cow, collections::BTreeMap, fs, io::Cursor, path::Path};
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
|
@ -6,8 +6,8 @@ use cwdemangle::demangle;
|
|||
use filetime::FileTime;
|
||||
use flagset::Flags;
|
||||
use object::{
|
||||
elf, Architecture, File, Object, ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget,
|
||||
SectionIndex, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
|
||||
elf, Architecture, Endianness, File, Object, ObjectSection, ObjectSymbol, RelocationKind,
|
||||
RelocationTarget, SectionIndex, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
|
||||
};
|
||||
|
||||
use crate::obj::{
|
||||
|
@ -278,7 +278,9 @@ fn relocations_by_section(
|
|||
Ok(relocations)
|
||||
}
|
||||
|
||||
fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u32, u32>>> {
|
||||
fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u64, u64>>> {
|
||||
// DWARF 1.1
|
||||
let mut map = BTreeMap::new();
|
||||
if let Some(section) = obj_file.section_by_name(".line") {
|
||||
if section.size() == 0 {
|
||||
return Ok(None);
|
||||
|
@ -286,22 +288,49 @@ fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u32, u32>>> {
|
|||
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>()?;
|
||||
let base_address = reader.read_u32::<BigEndian>()? as u64;
|
||||
while reader.position() < size as u64 {
|
||||
let line_number = reader.read_u32::<BigEndian>()?;
|
||||
let line_number = reader.read_u32::<BigEndian>()? as u64;
|
||||
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>()?;
|
||||
let address_delta = reader.read_u32::<BigEndian>()? as u64;
|
||||
map.insert(base_address + address_delta, line_number);
|
||||
}
|
||||
// log::debug!("Line info: {map:#X?}");
|
||||
return Ok(Some(map));
|
||||
}
|
||||
Ok(None)
|
||||
|
||||
// DWARF 2+
|
||||
let dwarf_cow = gimli::Dwarf::load(|id| {
|
||||
Ok::<_, gimli::Error>(
|
||||
obj_file
|
||||
.section_by_name(id.name())
|
||||
.and_then(|section| section.uncompressed_data().ok())
|
||||
.unwrap_or(Cow::Borrowed(&[][..])),
|
||||
)
|
||||
})?;
|
||||
let endian = match obj_file.endianness() {
|
||||
Endianness::Little => gimli::RunTimeEndian::Little,
|
||||
Endianness::Big => gimli::RunTimeEndian::Big,
|
||||
};
|
||||
let dwarf = dwarf_cow.borrow(|section| gimli::EndianSlice::new(section, endian));
|
||||
let mut iter = dwarf.units();
|
||||
while let Some(header) = iter.next()? {
|
||||
let unit = dwarf.unit(header)?;
|
||||
if let Some(program) = unit.line_program.clone() {
|
||||
let mut rows = program.rows();
|
||||
while let Some((_header, row)) = rows.next_row()? {
|
||||
if let Some(line) = row.line() {
|
||||
map.insert(row.address(), line.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if map.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
Ok(Some(map))
|
||||
}
|
||||
|
||||
pub fn read(obj_path: &Path) -> Result<ObjInfo> {
|
||||
|
|
|
@ -19,7 +19,7 @@ pub fn process_code(
|
|||
start_address: u64,
|
||||
end_address: u64,
|
||||
relocs: &[ObjReloc],
|
||||
line_info: &Option<BTreeMap<u32, u32>>,
|
||||
line_info: &Option<BTreeMap<u64, u64>>,
|
||||
) -> Result<ProcessCodeResult> {
|
||||
configure_rabbitizer();
|
||||
|
||||
|
@ -83,8 +83,9 @@ pub fn process_code(
|
|||
}
|
||||
}
|
||||
}
|
||||
let line =
|
||||
line_info.as_ref().and_then(|map| map.range(..=cur_addr).last().map(|(_, &b)| b));
|
||||
let line = line_info
|
||||
.as_ref()
|
||||
.and_then(|map| map.range(..=cur_addr as u64).last().map(|(_, &b)| b));
|
||||
insts.push(ObjIns {
|
||||
address: cur_addr,
|
||||
code,
|
||||
|
|
|
@ -113,7 +113,7 @@ pub struct ObjIns {
|
|||
pub reloc: Option<ObjReloc>,
|
||||
pub branch_dest: Option<u32>,
|
||||
/// Line info
|
||||
pub line: Option<u32>,
|
||||
pub line: Option<u64>,
|
||||
/// Original (unsimplified) instruction
|
||||
pub orig: Option<String>,
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ pub struct ObjInfo {
|
|||
pub timestamp: FileTime,
|
||||
pub sections: Vec<ObjSection>,
|
||||
pub common: Vec<ObjSymbol>,
|
||||
pub line_info: Option<BTreeMap<u32, u32>>,
|
||||
pub line_info: Option<BTreeMap<u64, u64>>,
|
||||
}
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||
pub enum ObjRelocKind {
|
||||
|
|
|
@ -24,7 +24,7 @@ pub fn process_code(
|
|||
data: &[u8],
|
||||
address: u64,
|
||||
relocs: &[ObjReloc],
|
||||
line_info: &Option<BTreeMap<u32, u32>>,
|
||||
line_info: &Option<BTreeMap<u64, u64>>,
|
||||
) -> Result<ProcessCodeResult> {
|
||||
let ins_count = data.len() / 4;
|
||||
let mut ops = Vec::<u8>::with_capacity(ins_count);
|
||||
|
@ -82,7 +82,7 @@ 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));
|
||||
.and_then(|map| map.range(..=simplified.ins.addr as u64).last().map(|(_, &b)| b));
|
||||
insts.push(ObjIns {
|
||||
address: simplified.ins.addr,
|
||||
code: simplified.ins.code,
|
||||
|
|
Loading…
Reference in New Issue