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