Skip to content

Commit

Permalink
Cleanup & move extab code into ppc arch
Browse files Browse the repository at this point in the history
  • Loading branch information
encounter committed Sep 10, 2024
1 parent c7e6394 commit dcf209a
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 186 deletions.
6 changes: 5 additions & 1 deletion objdiff-core/src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,18 @@ pub trait ObjArch: Send + Sync {
fn display_reloc(&self, flags: RelocationFlags) -> Cow<'static, str>;

fn symbol_address(&self, symbol: &Symbol) -> u64 { symbol.address() }

// Downcast methods
#[cfg(feature = "ppc")]
fn ppc(&self) -> Option<&ppc::ObjArchPpc> { None }
}

pub struct ProcessCodeResult {
pub ops: Vec<u16>,
pub insts: Vec<ObjIns>,
}

pub fn new_arch(object: &object::File) -> Result<Box<dyn ObjArch>> {
pub fn new_arch(object: &File) -> Result<Box<dyn ObjArch>> {
Ok(match object.architecture() {
#[cfg(feature = "ppc")]
Architecture::PowerPc => Box::new(ppc::ObjArchPpc::new(object)?),
Expand Down
150 changes: 145 additions & 5 deletions objdiff-core/src/arch/ppc.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use std::{borrow::Cow, collections::BTreeMap};

use anyhow::{bail, Result};
use object::{elf, File, Relocation, RelocationFlags};
use anyhow::{bail, ensure, Result};
use cwextab::{decode_extab, ExceptionTableData};
use object::{
elf, File, Object, ObjectSection, ObjectSymbol, Relocation, RelocationFlags, RelocationTarget,
Symbol, SymbolKind,
};
use ppc750cl::{Argument, InsIter, GPR};

use crate::{
arch::{ObjArch, ProcessCodeResult},
diff::DiffObjConfig,
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection, ObjSymbol},
};

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

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

pub struct ObjArchPpc {}
pub struct ObjArchPpc {
/// Exception info
pub extab: Option<BTreeMap<usize, ExceptionInfo>>,
}

impl ObjArchPpc {
pub fn new(_file: &File) -> Result<Self> { Ok(Self {}) }
pub fn new(file: &File) -> Result<Self> { Ok(Self { extab: decode_exception_info(file)? }) }
}

impl ObjArch for ObjArchPpc {
Expand Down Expand Up @@ -178,6 +185,14 @@ impl ObjArch for ObjArchPpc {
_ => Cow::Owned(format!("<{flags:?}>")),
}
}

fn ppc(&self) -> Option<&ObjArchPpc> { Some(self) }
}

impl ObjArchPpc {
pub fn extab_for_symbol(&self, symbol: &ObjSymbol) -> Option<&ExceptionInfo> {
symbol.original_index.and_then(|i| self.extab.as_ref()?.get(&i))
}
}

fn push_reloc(args: &mut Vec<ObjInsArg>, reloc: &ObjReloc) -> Result<()> {
Expand Down Expand Up @@ -208,3 +223,128 @@ fn push_reloc(args: &mut Vec<ObjInsArg>, reloc: &ObjReloc) -> Result<()> {
};
Ok(())
}

#[derive(Debug, Clone)]
pub struct ExtabSymbolRef {
pub original_index: usize,
pub name: String,
pub demangled_name: Option<String>,
}

#[derive(Debug, Clone)]
pub struct ExceptionInfo {
pub eti_symbol: ExtabSymbolRef,
pub etb_symbol: ExtabSymbolRef,
pub data: ExceptionTableData,
pub dtors: Vec<ExtabSymbolRef>,
}

fn decode_exception_info(file: &File<'_>) -> Result<Option<BTreeMap<usize, ExceptionInfo>>> {
let Some(extab_section) = file.section_by_name("extab") else {
return Ok(None);
};
let Some(extabindex_section) = file.section_by_name("extabindex") else {
return Ok(None);
};

let mut result = BTreeMap::new();
let extab_relocations = extab_section.relocations().collect::<BTreeMap<u64, Relocation>>();
let extabindex_relocations =
extabindex_section.relocations().collect::<BTreeMap<u64, Relocation>>();

for extabindex in file.symbols().filter(|symbol| {
symbol.section_index() == Some(extabindex_section.index())
&& symbol.kind() == SymbolKind::Data
}) {
if extabindex.size() != 12 {
log::warn!("Invalid extabindex entry size {}", extabindex.size());
continue;
}

// Each extabindex entry has two relocations:
// - 0x0: The function that the exception table is for
// - 0x8: The relevant entry in extab section
let Some(extab_func_reloc) = extabindex_relocations.get(&extabindex.address()) else {
log::warn!("Failed to find function relocation for extabindex entry");
continue;
};
let Some(extab_reloc) = extabindex_relocations.get(&(extabindex.address() + 8)) else {
log::warn!("Failed to find extab relocation for extabindex entry");
continue;
};

// Resolve the function and extab symbols
let Some(extab_func) = relocation_symbol(file, extab_func_reloc)? else {
log::warn!("Failed to find function symbol for extabindex entry");
continue;
};
let extab_func_name = extab_func.name()?;
let Some(extab) = relocation_symbol(file, extab_reloc)? else {
log::warn!("Failed to find extab symbol for extabindex entry");
continue;
};

let extab_start_addr = extab.address() - extab_section.address();
let extab_end_addr = extab_start_addr + extab.size();

// All relocations in the extab section are dtors
let mut dtors: Vec<ExtabSymbolRef> = vec![];
for (_, reloc) in extab_relocations.range(extab_start_addr..extab_end_addr) {
let Some(symbol) = relocation_symbol(file, reloc)? else {
log::warn!("Failed to find symbol for extab relocation");
continue;
};
dtors.push(make_symbol_ref(&symbol)?);
}

// Decode the extab data
let Some(extab_data) = extab_section.data_range(extab_start_addr, extab.size())? else {
log::warn!("Failed to get extab data for function {}", extab_func_name);
continue;
};
let data = match decode_extab(extab_data) {
Some(decoded_data) => decoded_data,
None => {
log::warn!("Exception table decoding failed for function {}", extab_func_name);
return Ok(None);
}
};

//Add the new entry to the list
result.insert(extab_func.index().0, ExceptionInfo {
eti_symbol: make_symbol_ref(&extabindex)?,
etb_symbol: make_symbol_ref(&extab)?,
data,
dtors,
});
}

Ok(Some(result))
}

fn relocation_symbol<'data, 'file>(
file: &'file File<'data>,
relocation: &Relocation,
) -> Result<Option<Symbol<'data, 'file>>> {
let addend = relocation.addend();
match relocation.target() {
RelocationTarget::Symbol(idx) => {
ensure!(addend == 0, "Symbol relocations must have zero addend");
Ok(Some(file.symbol_by_index(idx)?))
}
RelocationTarget::Section(idx) => {
ensure!(addend >= 0, "Section relocations must have non-negative addend");
let addend = addend as u64;
Ok(file
.symbols()
.find(|symbol| symbol.section_index() == Some(idx) && symbol.address() == addend))
}
target => bail!("Unsupported relocation target: {target:?}"),
}
}

fn make_symbol_ref(symbol: &Symbol) -> Result<ExtabSymbolRef> {
let name = symbol.name()?.to_string();
let demangled_name = cwdemangle::demangle(&name, &cwdemangle::DemangleOptions::default());
Ok(ExtabSymbolRef { original_index: symbol.index().0, name, demangled_name })
}
18 changes: 5 additions & 13 deletions objdiff-core/src/obj/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pub mod split_meta;

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

use cwextab::*;
use filetime::FileTime;
use flagset::{flags, FlagSet};
use object::RelocationFlags;
Expand All @@ -24,6 +23,9 @@ flags! {
Weak,
Common,
Hidden,
/// Has extra data associated with the symbol
/// (e.g. exception table entry)
HasExtra,
}
}
#[derive(Debug, Copy, Clone, Default)]
Expand Down Expand Up @@ -114,9 +116,6 @@ pub struct ObjIns {
pub struct ObjSymbol {
pub name: String,
pub demangled_name: Option<String>,
pub has_extab: bool,
pub extab_name: Option<String>,
pub extabindex_name: Option<String>,
pub address: u64,
pub section_address: u64,
pub size: u64,
Expand All @@ -125,13 +124,8 @@ pub struct ObjSymbol {
pub addend: i64,
/// Original virtual address (from .note.split section)
pub virtual_address: Option<u64>,
}

#[derive(Debug, Clone)]
pub struct ObjExtab {
pub func: ObjSymbol,
pub data: ExceptionTableData,
pub dtors: Vec<ObjSymbol>,
/// Original index in object symbol table
pub original_index: Option<usize>,
}

pub struct ObjInfo {
Expand All @@ -141,8 +135,6 @@ pub struct ObjInfo {
pub sections: Vec<ObjSection>,
/// Common BSS symbols
pub common: Vec<ObjSymbol>,
/// Exception tables
pub extab: Option<Vec<ObjExtab>>,
/// Split object metadata (.note.split section)
pub split_meta: Option<SplitMeta>,
}
Expand Down
Loading

0 comments on commit dcf209a

Please sign in to comment.