mirror of
https://github.com/encounter/objdiff.git
synced 2025-07-03 11:45:57 +00:00
Support multiple DWARF sequences
This commit is contained in:
parent
8b36fa4fc6
commit
ff910d94c9
@ -1,7 +1,7 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use object::{elf, Endian, Endianness, File, Object, Relocation, RelocationFlags};
|
use object::{elf, Endian, Endianness, File, Object, Relocation, RelocationFlags, SectionIndex};
|
||||||
use rabbitizer::{config, Abi, InstrCategory, Instruction, OperandType};
|
use rabbitizer::{config, Abi, InstrCategory, Instruction, OperandType};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -38,6 +38,9 @@ impl ObjArch for ObjArchMips {
|
|||||||
let code = §ion.data
|
let code = §ion.data
|
||||||
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
||||||
|
|
||||||
|
let line_info =
|
||||||
|
obj.line_info.as_ref().and_then(|map| map.get(&SectionIndex(section.orig_index)));
|
||||||
|
|
||||||
let start_address = symbol.address;
|
let start_address = symbol.address;
|
||||||
let end_address = symbol.address + symbol.size;
|
let end_address = symbol.address + symbol.size;
|
||||||
let ins_count = code.len() / 4;
|
let ins_count = code.len() / 4;
|
||||||
@ -110,10 +113,8 @@ impl ObjArch for ObjArchMips {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let line = obj
|
let line =
|
||||||
.line_info
|
line_info.and_then(|map| map.range(..=cur_addr as u64).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 as u64,
|
address: cur_addr as u64,
|
||||||
size: 4,
|
size: 4,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use object::{elf, File, Relocation, RelocationFlags};
|
use object::{elf, File, Relocation, RelocationFlags, SectionIndex};
|
||||||
use ppc750cl::{Argument, InsIter, GPR};
|
use ppc750cl::{Argument, InsIter, GPR};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -39,6 +39,9 @@ impl ObjArch for ObjArchPpc {
|
|||||||
let code = §ion.data
|
let code = §ion.data
|
||||||
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
||||||
|
|
||||||
|
let line_info =
|
||||||
|
obj.line_info.as_ref().and_then(|map| map.get(&SectionIndex(section.orig_index)));
|
||||||
|
|
||||||
let ins_count = code.len() / 4;
|
let ins_count = code.len() / 4;
|
||||||
let mut ops = Vec::<u16>::with_capacity(ins_count);
|
let mut ops = Vec::<u16>::with_capacity(ins_count);
|
||||||
let mut insts = Vec::<ObjIns>::with_capacity(ins_count);
|
let mut insts = Vec::<ObjIns>::with_capacity(ins_count);
|
||||||
@ -131,10 +134,8 @@ impl ObjArch for ObjArchPpc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ops.push(ins.op as u16);
|
ops.push(ins.op as u16);
|
||||||
let line = obj
|
let line =
|
||||||
.line_info
|
line_info.and_then(|map| map.range(..=cur_addr as u64).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 as u64,
|
address: cur_addr as u64,
|
||||||
size: 4,
|
size: 4,
|
||||||
|
@ -6,7 +6,7 @@ use iced_x86::{
|
|||||||
GasFormatter, Instruction, IntelFormatter, MasmFormatter, NasmFormatter, NumberKind, OpKind,
|
GasFormatter, Instruction, IntelFormatter, MasmFormatter, NasmFormatter, NumberKind, OpKind,
|
||||||
PrefixKind, Register,
|
PrefixKind, Register,
|
||||||
};
|
};
|
||||||
use object::{pe, Endian, Endianness, File, Object, Relocation, RelocationFlags};
|
use object::{pe, Endian, Endianness, File, Object, Relocation, RelocationFlags, SectionIndex};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{ObjArch, ProcessCodeResult},
|
arch::{ObjArch, ProcessCodeResult},
|
||||||
@ -36,6 +36,9 @@ impl ObjArch for ObjArchX86 {
|
|||||||
let code = §ion.data
|
let code = §ion.data
|
||||||
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
||||||
|
|
||||||
|
let line_info =
|
||||||
|
obj.line_info.as_ref().and_then(|map| map.get(&SectionIndex(section.orig_index)));
|
||||||
|
|
||||||
let mut result = ProcessCodeResult { ops: Vec::new(), insts: Vec::new() };
|
let mut result = ProcessCodeResult { ops: Vec::new(), insts: Vec::new() };
|
||||||
let mut decoder = Decoder::with_ip(self.bits, code, symbol.address, DecoderOptions::NONE);
|
let mut decoder = Decoder::with_ip(self.bits, code, symbol.address, DecoderOptions::NONE);
|
||||||
let mut formatter: Box<dyn Formatter> = match config.x86_formatter {
|
let mut formatter: Box<dyn Formatter> = match config.x86_formatter {
|
||||||
@ -80,7 +83,7 @@ impl ObjArch for ObjArchX86 {
|
|||||||
args: vec![],
|
args: vec![],
|
||||||
reloc: reloc.cloned(),
|
reloc: reloc.cloned(),
|
||||||
branch_dest: None,
|
branch_dest: None,
|
||||||
line: obj.line_info.as_ref().and_then(|m| m.get(&address).cloned()),
|
line: line_info.and_then(|m| m.get(&address).cloned()),
|
||||||
orig: None,
|
orig: None,
|
||||||
};
|
};
|
||||||
// Run the formatter, which will populate output.ins
|
// Run the formatter, which will populate output.ins
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
pub mod read;
|
pub mod read;
|
||||||
pub mod split_meta;
|
pub mod split_meta;
|
||||||
|
|
||||||
use std::{borrow::Cow, collections::BTreeMap, fmt, path::PathBuf};
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
collections::{BTreeMap, HashMap},
|
||||||
|
fmt,
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
use filetime::FileTime;
|
use filetime::FileTime;
|
||||||
use flagset::{flags, FlagSet};
|
use flagset::{flags, FlagSet};
|
||||||
use object::RelocationFlags;
|
use object::{RelocationFlags, SectionIndex};
|
||||||
use split_meta::SplitMeta;
|
use split_meta::SplitMeta;
|
||||||
|
|
||||||
use crate::{arch::ObjArch, util::ReallySigned};
|
use crate::{arch::ObjArch, util::ReallySigned};
|
||||||
@ -127,7 +132,7 @@ pub struct ObjInfo {
|
|||||||
/// Common BSS symbols
|
/// Common BSS symbols
|
||||||
pub common: Vec<ObjSymbol>,
|
pub common: Vec<ObjSymbol>,
|
||||||
/// Line number info (.line or .debug_line section)
|
/// Line number info (.line or .debug_line section)
|
||||||
pub line_info: Option<BTreeMap<u64, u64>>,
|
pub line_info: Option<HashMap<SectionIndex, BTreeMap<u64, u64>>>,
|
||||||
/// Split object metadata (.note.split section)
|
/// Split object metadata (.note.split section)
|
||||||
pub split_meta: Option<SplitMeta>,
|
pub split_meta: Option<SplitMeta>,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
use std::{collections::BTreeMap, fs, io::Cursor, path::Path};
|
use std::{
|
||||||
|
collections::{BTreeMap, HashMap},
|
||||||
|
fs,
|
||||||
|
io::Cursor,
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, ensure, Context, Result};
|
use anyhow::{anyhow, bail, ensure, Context, Result};
|
||||||
use byteorder::{BigEndian, ReadBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
@ -268,13 +273,20 @@ fn relocations_by_section(
|
|||||||
Ok(relocations)
|
Ok(relocations)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u64, u64>>> {
|
fn line_info(obj_file: &File<'_>) -> Result<Option<HashMap<SectionIndex, BTreeMap<u64, u64>>>> {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
// DWARF 1.1
|
// 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);
|
||||||
}
|
}
|
||||||
|
let text_section = obj_file
|
||||||
|
.sections()
|
||||||
|
.find(|s| s.kind() == SectionKind::Text)
|
||||||
|
.context("No text section found for line info")?;
|
||||||
|
let mut lines = BTreeMap::new();
|
||||||
|
|
||||||
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());
|
||||||
|
|
||||||
@ -287,13 +299,20 @@ fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u64, u64>>> {
|
|||||||
log::warn!("Unhandled statement pos {}", statement_pos);
|
log::warn!("Unhandled statement pos {}", statement_pos);
|
||||||
}
|
}
|
||||||
let address_delta = reader.read_u32::<BigEndian>()? as u64;
|
let address_delta = reader.read_u32::<BigEndian>()? as u64;
|
||||||
map.insert(base_address + address_delta, line_number);
|
lines.insert(base_address + address_delta, line_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map.insert(text_section.index(), lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DWARF 2+
|
// DWARF 2+
|
||||||
#[cfg(feature = "dwarf")]
|
#[cfg(feature = "dwarf")]
|
||||||
{
|
{
|
||||||
|
let mut text_sections = obj_file.sections().filter(|s| s.kind() == SectionKind::Text);
|
||||||
|
let first_section = text_sections.next().context("No text section found for line info")?;
|
||||||
|
map.insert(first_section.index(), BTreeMap::new());
|
||||||
|
let mut lines = map.get_mut(&first_section.index()).unwrap();
|
||||||
|
|
||||||
let dwarf_cow = gimli::DwarfSections::load(|id| {
|
let dwarf_cow = gimli::DwarfSections::load(|id| {
|
||||||
Ok::<_, gimli::Error>(
|
Ok::<_, gimli::Error>(
|
||||||
obj_file
|
obj_file
|
||||||
@ -308,13 +327,23 @@ fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u64, u64>>> {
|
|||||||
};
|
};
|
||||||
let dwarf = dwarf_cow.borrow(|section| gimli::EndianSlice::new(section, endian));
|
let dwarf = dwarf_cow.borrow(|section| gimli::EndianSlice::new(section, endian));
|
||||||
let mut iter = dwarf.units();
|
let mut iter = dwarf.units();
|
||||||
while let Some(header) = iter.next()? {
|
'outer: while let Some(header) = iter.next()? {
|
||||||
let unit = dwarf.unit(header)?;
|
let unit = dwarf.unit(header)?;
|
||||||
if let Some(program) = unit.line_program.clone() {
|
if let Some(program) = unit.line_program.clone() {
|
||||||
let mut rows = program.rows();
|
let mut rows = program.rows();
|
||||||
while let Some((_header, row)) = rows.next_row()? {
|
while let Some((_header, row)) = rows.next_row()? {
|
||||||
if let Some(line) = row.line() {
|
if let Some(line) = row.line() {
|
||||||
map.insert(row.address(), line.get());
|
lines.insert(row.address(), line.get());
|
||||||
|
}
|
||||||
|
if row.end_sequence() {
|
||||||
|
// The next row is the start of a new sequence, which means we must
|
||||||
|
// advance to the next .text section.
|
||||||
|
if let Some(next_section) = text_sections.next() {
|
||||||
|
map.insert(next_section.index(), BTreeMap::new());
|
||||||
|
lines = map.get_mut(&next_section.index()).unwrap();
|
||||||
|
} else {
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user