Skip to content

Commit dcf209a

Browse files
committed
Cleanup & move extab code into ppc arch
1 parent c7e6394 commit dcf209a

File tree

7 files changed

+207
-186
lines changed

7 files changed

+207
-186
lines changed

objdiff-core/src/arch/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,18 @@ pub trait ObjArch: Send + Sync {
4141
fn display_reloc(&self, flags: RelocationFlags) -> Cow<'static, str>;
4242

4343
fn symbol_address(&self, symbol: &Symbol) -> u64 { symbol.address() }
44+
45+
// Downcast methods
46+
#[cfg(feature = "ppc")]
47+
fn ppc(&self) -> Option<&ppc::ObjArchPpc> { None }
4448
}
4549

4650
pub struct ProcessCodeResult {
4751
pub ops: Vec<u16>,
4852
pub insts: Vec<ObjIns>,
4953
}
5054

51-
pub fn new_arch(object: &object::File) -> Result<Box<dyn ObjArch>> {
55+
pub fn new_arch(object: &File) -> Result<Box<dyn ObjArch>> {
5256
Ok(match object.architecture() {
5357
#[cfg(feature = "ppc")]
5458
Architecture::PowerPc => Box::new(ppc::ObjArchPpc::new(object)?),

objdiff-core/src/arch/ppc.rs

Lines changed: 145 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
use std::{borrow::Cow, collections::BTreeMap};
22

3-
use anyhow::{bail, Result};
4-
use object::{elf, File, Relocation, RelocationFlags};
3+
use anyhow::{bail, ensure, Result};
4+
use cwextab::{decode_extab, ExceptionTableData};
5+
use object::{
6+
elf, File, Object, ObjectSection, ObjectSymbol, Relocation, RelocationFlags, RelocationTarget,
7+
Symbol, SymbolKind,
8+
};
59
use ppc750cl::{Argument, InsIter, GPR};
610

711
use crate::{
812
arch::{ObjArch, ProcessCodeResult},
913
diff::DiffObjConfig,
10-
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
14+
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection, ObjSymbol},
1115
};
1216

1317
// Relative relocation, can be Simm, Offset or BranchDest
@@ -22,10 +26,13 @@ fn is_rel_abs_arg(arg: &Argument) -> bool {
2226

2327
fn is_offset_arg(arg: &Argument) -> bool { matches!(arg, Argument::Offset(_)) }
2428

25-
pub struct ObjArchPpc {}
29+
pub struct ObjArchPpc {
30+
/// Exception info
31+
pub extab: Option<BTreeMap<usize, ExceptionInfo>>,
32+
}
2633

2734
impl ObjArchPpc {
28-
pub fn new(_file: &File) -> Result<Self> { Ok(Self {}) }
35+
pub fn new(file: &File) -> Result<Self> { Ok(Self { extab: decode_exception_info(file)? }) }
2936
}
3037

3138
impl ObjArch for ObjArchPpc {
@@ -178,6 +185,14 @@ impl ObjArch for ObjArchPpc {
178185
_ => Cow::Owned(format!("<{flags:?}>")),
179186
}
180187
}
188+
189+
fn ppc(&self) -> Option<&ObjArchPpc> { Some(self) }
190+
}
191+
192+
impl ObjArchPpc {
193+
pub fn extab_for_symbol(&self, symbol: &ObjSymbol) -> Option<&ExceptionInfo> {
194+
symbol.original_index.and_then(|i| self.extab.as_ref()?.get(&i))
195+
}
181196
}
182197

183198
fn push_reloc(args: &mut Vec<ObjInsArg>, reloc: &ObjReloc) -> Result<()> {
@@ -208,3 +223,128 @@ fn push_reloc(args: &mut Vec<ObjInsArg>, reloc: &ObjReloc) -> Result<()> {
208223
};
209224
Ok(())
210225
}
226+
227+
#[derive(Debug, Clone)]
228+
pub struct ExtabSymbolRef {
229+
pub original_index: usize,
230+
pub name: String,
231+
pub demangled_name: Option<String>,
232+
}
233+
234+
#[derive(Debug, Clone)]
235+
pub struct ExceptionInfo {
236+
pub eti_symbol: ExtabSymbolRef,
237+
pub etb_symbol: ExtabSymbolRef,
238+
pub data: ExceptionTableData,
239+
pub dtors: Vec<ExtabSymbolRef>,
240+
}
241+
242+
fn decode_exception_info(file: &File<'_>) -> Result<Option<BTreeMap<usize, ExceptionInfo>>> {
243+
let Some(extab_section) = file.section_by_name("extab") else {
244+
return Ok(None);
245+
};
246+
let Some(extabindex_section) = file.section_by_name("extabindex") else {
247+
return Ok(None);
248+
};
249+
250+
let mut result = BTreeMap::new();
251+
let extab_relocations = extab_section.relocations().collect::<BTreeMap<u64, Relocation>>();
252+
let extabindex_relocations =
253+
extabindex_section.relocations().collect::<BTreeMap<u64, Relocation>>();
254+
255+
for extabindex in file.symbols().filter(|symbol| {
256+
symbol.section_index() == Some(extabindex_section.index())
257+
&& symbol.kind() == SymbolKind::Data
258+
}) {
259+
if extabindex.size() != 12 {
260+
log::warn!("Invalid extabindex entry size {}", extabindex.size());
261+
continue;
262+
}
263+
264+
// Each extabindex entry has two relocations:
265+
// - 0x0: The function that the exception table is for
266+
// - 0x8: The relevant entry in extab section
267+
let Some(extab_func_reloc) = extabindex_relocations.get(&extabindex.address()) else {
268+
log::warn!("Failed to find function relocation for extabindex entry");
269+
continue;
270+
};
271+
let Some(extab_reloc) = extabindex_relocations.get(&(extabindex.address() + 8)) else {
272+
log::warn!("Failed to find extab relocation for extabindex entry");
273+
continue;
274+
};
275+
276+
// Resolve the function and extab symbols
277+
let Some(extab_func) = relocation_symbol(file, extab_func_reloc)? else {
278+
log::warn!("Failed to find function symbol for extabindex entry");
279+
continue;
280+
};
281+
let extab_func_name = extab_func.name()?;
282+
let Some(extab) = relocation_symbol(file, extab_reloc)? else {
283+
log::warn!("Failed to find extab symbol for extabindex entry");
284+
continue;
285+
};
286+
287+
let extab_start_addr = extab.address() - extab_section.address();
288+
let extab_end_addr = extab_start_addr + extab.size();
289+
290+
// All relocations in the extab section are dtors
291+
let mut dtors: Vec<ExtabSymbolRef> = vec![];
292+
for (_, reloc) in extab_relocations.range(extab_start_addr..extab_end_addr) {
293+
let Some(symbol) = relocation_symbol(file, reloc)? else {
294+
log::warn!("Failed to find symbol for extab relocation");
295+
continue;
296+
};
297+
dtors.push(make_symbol_ref(&symbol)?);
298+
}
299+
300+
// Decode the extab data
301+
let Some(extab_data) = extab_section.data_range(extab_start_addr, extab.size())? else {
302+
log::warn!("Failed to get extab data for function {}", extab_func_name);
303+
continue;
304+
};
305+
let data = match decode_extab(extab_data) {
306+
Some(decoded_data) => decoded_data,
307+
None => {
308+
log::warn!("Exception table decoding failed for function {}", extab_func_name);
309+
return Ok(None);
310+
}
311+
};
312+
313+
//Add the new entry to the list
314+
result.insert(extab_func.index().0, ExceptionInfo {
315+
eti_symbol: make_symbol_ref(&extabindex)?,
316+
etb_symbol: make_symbol_ref(&extab)?,
317+
data,
318+
dtors,
319+
});
320+
}
321+
322+
Ok(Some(result))
323+
}
324+
325+
fn relocation_symbol<'data, 'file>(
326+
file: &'file File<'data>,
327+
relocation: &Relocation,
328+
) -> Result<Option<Symbol<'data, 'file>>> {
329+
let addend = relocation.addend();
330+
match relocation.target() {
331+
RelocationTarget::Symbol(idx) => {
332+
ensure!(addend == 0, "Symbol relocations must have zero addend");
333+
Ok(Some(file.symbol_by_index(idx)?))
334+
}
335+
RelocationTarget::Section(idx) => {
336+
ensure!(addend >= 0, "Section relocations must have non-negative addend");
337+
let addend = addend as u64;
338+
Ok(file
339+
.symbols()
340+
.find(|symbol| symbol.section_index() == Some(idx) && symbol.address() == addend))
341+
}
342+
target => bail!("Unsupported relocation target: {target:?}"),
343+
}
344+
}
345+
346+
fn make_symbol_ref(symbol: &Symbol) -> Result<ExtabSymbolRef> {
347+
let name = symbol.name()?.to_string();
348+
let demangled_name = cwdemangle::demangle(&name, &cwdemangle::DemangleOptions::default());
349+
Ok(ExtabSymbolRef { original_index: symbol.index().0, name, demangled_name })
350+
}

objdiff-core/src/obj/mod.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ pub mod split_meta;
33

44
use std::{borrow::Cow, collections::BTreeMap, fmt, path::PathBuf};
55

6-
use cwextab::*;
76
use filetime::FileTime;
87
use flagset::{flags, FlagSet};
98
use object::RelocationFlags;
@@ -24,6 +23,9 @@ flags! {
2423
Weak,
2524
Common,
2625
Hidden,
26+
/// Has extra data associated with the symbol
27+
/// (e.g. exception table entry)
28+
HasExtra,
2729
}
2830
}
2931
#[derive(Debug, Copy, Clone, Default)]
@@ -114,9 +116,6 @@ pub struct ObjIns {
114116
pub struct ObjSymbol {
115117
pub name: String,
116118
pub demangled_name: Option<String>,
117-
pub has_extab: bool,
118-
pub extab_name: Option<String>,
119-
pub extabindex_name: Option<String>,
120119
pub address: u64,
121120
pub section_address: u64,
122121
pub size: u64,
@@ -125,13 +124,8 @@ pub struct ObjSymbol {
125124
pub addend: i64,
126125
/// Original virtual address (from .note.split section)
127126
pub virtual_address: Option<u64>,
128-
}
129-
130-
#[derive(Debug, Clone)]
131-
pub struct ObjExtab {
132-
pub func: ObjSymbol,
133-
pub data: ExceptionTableData,
134-
pub dtors: Vec<ObjSymbol>,
127+
/// Original index in object symbol table
128+
pub original_index: Option<usize>,
135129
}
136130

137131
pub struct ObjInfo {
@@ -141,8 +135,6 @@ pub struct ObjInfo {
141135
pub sections: Vec<ObjSection>,
142136
/// Common BSS symbols
143137
pub common: Vec<ObjSymbol>,
144-
/// Exception tables
145-
pub extab: Option<Vec<ObjExtab>>,
146138
/// Split object metadata (.note.split section)
147139
pub split_meta: Option<SplitMeta>,
148140
}

0 commit comments

Comments
 (0)