From 3f82c1a50fd4d446ee409d5dec04c0d949917fcd Mon Sep 17 00:00:00 2001 From: Luke Street Date: Mon, 3 Jun 2024 18:51:44 -0600 Subject: [PATCH] objdiff-core API adjustments - Allows using process_code without constructing an ObjInfo - Allows creating an arch without having to provide an object Used in decomp-toolkit --- objdiff-core/src/arch/mips.rs | 23 ++++++++++------------- objdiff-core/src/arch/mod.rs | 16 +++++++++------- objdiff-core/src/arch/ppc.rs | 23 ++++++++++------------- objdiff-core/src/arch/x86.rs | 22 +++++++++------------- objdiff-core/src/diff/code.rs | 31 +++++++++++++++++++------------ objdiff-core/src/diff/mod.rs | 23 ++++++++++++++--------- 6 files changed, 71 insertions(+), 67 deletions(-) diff --git a/objdiff-core/src/arch/mips.rs b/objdiff-core/src/arch/mips.rs index 406f0ad..dcdc391 100644 --- a/objdiff-core/src/arch/mips.rs +++ b/objdiff-core/src/arch/mips.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, sync::Mutex}; +use std::{borrow::Cow, collections::BTreeMap, sync::Mutex}; use anyhow::{anyhow, bail, Result}; use object::{elf, Endian, Endianness, File, FileFlags, Object, Relocation, RelocationFlags}; @@ -7,7 +7,7 @@ use rabbitizer::{config, Abi, InstrCategory, Instruction, OperandType}; use crate::{ arch::{ObjArch, ProcessCodeResult}, diff::{DiffObjConfig, MipsAbi, MipsInstrCategory}, - obj::{ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection, SymbolRef}, + obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection}, }; static RABBITIZER_MUTEX: Mutex<()> = Mutex::new(()); @@ -57,15 +57,12 @@ impl ObjArchMips { impl ObjArch for ObjArchMips { fn process_code( &self, - obj: &ObjInfo, - symbol_ref: SymbolRef, + address: u64, + code: &[u8], + relocations: &[ObjReloc], + line_info: &BTreeMap, config: &DiffObjConfig, ) -> Result { - let (section, symbol) = obj.section_symbol(symbol_ref); - let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?; - let code = §ion.data - [symbol.section_address as usize..(symbol.section_address + symbol.size) as usize]; - let _guard = RABBITIZER_MUTEX.lock().map_err(|e| anyhow!("Failed to lock mutex: {e}"))?; configure_rabbitizer(match config.mips_abi { MipsAbi::Auto => self.abi, @@ -82,14 +79,14 @@ impl ObjArch for ObjArchMips { MipsInstrCategory::R5900 => InstrCategory::R5900, }; - let start_address = symbol.address; - let end_address = symbol.address + symbol.size; + let start_address = address; + let end_address = address + code.len() as u64; let ins_count = code.len() / 4; let mut ops = Vec::::with_capacity(ins_count); let mut insts = Vec::::with_capacity(ins_count); let mut cur_addr = start_address as u32; for chunk in code.chunks_exact(4) { - let reloc = section.relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr); + let reloc = relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr); let code = self.endianness.read_u32_bytes(chunk.try_into()?); let instruction = Instruction::new(code, cur_addr, instr_category); @@ -155,7 +152,7 @@ impl ObjArch for ObjArchMips { } } } - let line = section.line_info.range(..=cur_addr as u64).last().map(|(_, &b)| b); + let line = line_info.range(..=cur_addr as u64).last().map(|(_, &b)| b); insts.push(ObjIns { address: cur_addr as u64, size: 4, diff --git a/objdiff-core/src/arch/mod.rs b/objdiff-core/src/arch/mod.rs index 6e5057c..ce4b545 100644 --- a/objdiff-core/src/arch/mod.rs +++ b/objdiff-core/src/arch/mod.rs @@ -1,25 +1,27 @@ -use std::borrow::Cow; +use std::{borrow::Cow, collections::BTreeMap}; use anyhow::{bail, Result}; use object::{Architecture, Object, Relocation, RelocationFlags}; use crate::{ diff::DiffObjConfig, - obj::{ObjInfo, ObjIns, ObjSection, SymbolRef}, + obj::{ObjIns, ObjReloc, ObjSection}, }; #[cfg(feature = "mips")] -mod mips; +pub mod mips; #[cfg(feature = "ppc")] -mod ppc; +pub mod ppc; #[cfg(feature = "x86")] -mod x86; +pub mod x86; pub trait ObjArch: Send + Sync { fn process_code( &self, - obj: &ObjInfo, - symbol_ref: SymbolRef, + address: u64, + code: &[u8], + relocations: &[ObjReloc], + line_info: &BTreeMap, config: &DiffObjConfig, ) -> Result; diff --git a/objdiff-core/src/arch/ppc.rs b/objdiff-core/src/arch/ppc.rs index 107b9d9..377243b 100644 --- a/objdiff-core/src/arch/ppc.rs +++ b/objdiff-core/src/arch/ppc.rs @@ -1,13 +1,13 @@ -use std::borrow::Cow; +use std::{borrow::Cow, collections::BTreeMap}; -use anyhow::{anyhow, bail, Result}; +use anyhow::{bail, Result}; use object::{elf, File, Relocation, RelocationFlags}; use ppc750cl::{Argument, InsIter, GPR}; use crate::{ arch::{ObjArch, ProcessCodeResult}, diff::DiffObjConfig, - obj::{ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection, SymbolRef}, + obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection}, }; // Relative relocation, can be Simm, Offset or BranchDest @@ -31,20 +31,17 @@ impl ObjArchPpc { impl ObjArch for ObjArchPpc { fn process_code( &self, - obj: &ObjInfo, - symbol_ref: SymbolRef, + address: u64, + code: &[u8], + relocations: &[ObjReloc], + line_info: &BTreeMap, config: &DiffObjConfig, ) -> Result { - let (section, symbol) = obj.section_symbol(symbol_ref); - let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?; - let code = §ion.data - [symbol.section_address as usize..(symbol.section_address + symbol.size) as usize]; - let ins_count = code.len() / 4; let mut ops = Vec::::with_capacity(ins_count); let mut insts = Vec::::with_capacity(ins_count); - for (cur_addr, mut ins) in InsIter::new(code, symbol.address as u32) { - let reloc = section.relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr); + for (cur_addr, mut ins) in InsIter::new(code, address as u32) { + let reloc = relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr); if let Some(reloc) = reloc { // Zero out relocations ins.code = match reloc.flags { @@ -133,7 +130,7 @@ impl ObjArch for ObjArchPpc { } ops.push(ins.op as u16); - let line = section.line_info.range(..=cur_addr as u64).last().map(|(_, &b)| b); + let line = line_info.range(..=cur_addr as u64).last().map(|(_, &b)| b); insts.push(ObjIns { address: cur_addr as u64, size: 4, diff --git a/objdiff-core/src/arch/x86.rs b/objdiff-core/src/arch/x86.rs index 637eb0b..44ff73a 100644 --- a/objdiff-core/src/arch/x86.rs +++ b/objdiff-core/src/arch/x86.rs @@ -1,4 +1,4 @@ -use std::borrow::Cow; +use std::{borrow::Cow, collections::BTreeMap}; use anyhow::{anyhow, bail, ensure, Result}; use iced_x86::{ @@ -11,7 +11,7 @@ use object::{pe, Endian, Endianness, File, Object, Relocation, RelocationFlags}; use crate::{ arch::{ObjArch, ProcessCodeResult}, diff::{DiffObjConfig, X86Formatter}, - obj::{ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjSection, SymbolRef}, + obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection}, }; pub struct ObjArchX86 { @@ -28,17 +28,14 @@ impl ObjArchX86 { impl ObjArch for ObjArchX86 { fn process_code( &self, - obj: &ObjInfo, - symbol_ref: SymbolRef, + address: u64, + code: &[u8], + relocations: &[ObjReloc], + line_info: &BTreeMap, config: &DiffObjConfig, ) -> Result { - let (section, symbol) = obj.section_symbol(symbol_ref); - let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?; - let code = §ion.data - [symbol.section_address as usize..(symbol.section_address + symbol.size) as usize]; - 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, address, DecoderOptions::NONE); let mut formatter: Box = match config.x86_formatter { X86Formatter::Intel => Box::new(IntelFormatter::new()), X86Formatter::Gas => Box::new(GasFormatter::new()), @@ -70,11 +67,10 @@ impl ObjArch for ObjArchX86 { let address = instruction.ip(); let op = instruction.mnemonic() as u16; - let reloc = section - .relocations + let reloc = relocations .iter() .find(|r| r.address >= address && r.address < address + instruction.len() as u64); - let line = section.line_info.range(..=address).last().map(|(_, &b)| b); + let line = line_info.range(..=address).last().map(|(_, &b)| b); output.ins = ObjIns { address, size: instruction.len() as u8, diff --git a/objdiff-core/src/diff/code.rs b/objdiff-core/src/diff/code.rs index bbd300d..19343f6 100644 --- a/objdiff-core/src/diff/code.rs +++ b/objdiff-core/src/diff/code.rs @@ -4,7 +4,7 @@ use std::{ time::{Duration, Instant}, }; -use anyhow::Result; +use anyhow::{anyhow, Result}; use similar::{capture_diff_slices_deadline, Algorithm}; use crate::{ @@ -16,34 +16,41 @@ use crate::{ obj::{ObjInfo, ObjInsArg, ObjReloc, ObjSymbol, ObjSymbolFlags, SymbolRef}, }; -pub fn no_diff_code( +pub fn process_code_symbol( obj: &ObjInfo, symbol_ref: SymbolRef, config: &DiffObjConfig, -) -> Result { - let out = obj.arch.process_code(obj, symbol_ref, config)?; +) -> Result { + let (section, symbol) = obj.section_symbol(symbol_ref); + let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?; + let code = §ion.data + [symbol.section_address as usize..(symbol.section_address + symbol.size) as usize]; + obj.arch.process_code(symbol.address, code, §ion.relocations, §ion.line_info, config) +} +pub fn no_diff_code(out: &ProcessCodeResult, symbol_ref: SymbolRef) -> Result { let mut diff = Vec::::new(); - for i in out.insts { - diff.push(ObjInsDiff { ins: Some(i), kind: ObjInsDiffKind::None, ..Default::default() }); + for i in &out.insts { + diff.push(ObjInsDiff { + ins: Some(i.clone()), + kind: ObjInsDiffKind::None, + ..Default::default() + }); } resolve_branches(&mut diff); Ok(ObjSymbolDiff { symbol_ref, diff_symbol: None, instructions: diff, match_percent: None }) } pub fn diff_code( - left_obj: &ObjInfo, - right_obj: &ObjInfo, + left_out: &ProcessCodeResult, + right_out: &ProcessCodeResult, left_symbol_ref: SymbolRef, right_symbol_ref: SymbolRef, config: &DiffObjConfig, ) -> Result<(ObjSymbolDiff, ObjSymbolDiff)> { - let left_out = left_obj.arch.process_code(left_obj, left_symbol_ref, config)?; - let right_out = right_obj.arch.process_code(right_obj, right_symbol_ref, config)?; - let mut left_diff = Vec::::new(); let mut right_diff = Vec::::new(); - diff_instructions(&mut left_diff, &mut right_diff, &left_out, &right_out)?; + diff_instructions(&mut left_diff, &mut right_diff, left_out, right_out)?; resolve_branches(&mut left_diff); resolve_branches(&mut right_diff); diff --git a/objdiff-core/src/diff/mod.rs b/objdiff-core/src/diff/mod.rs index fab8350..a983fcc 100644 --- a/objdiff-core/src/diff/mod.rs +++ b/objdiff-core/src/diff/mod.rs @@ -4,7 +4,7 @@ use anyhow::Result; use crate::{ diff::{ - code::{diff_code, no_diff_code}, + code::{diff_code, no_diff_code, process_code_symbol}, data::{ diff_bss_section, diff_bss_symbol, diff_data_section, diff_data_symbol, diff_text_section, no_diff_symbol, @@ -13,8 +13,8 @@ use crate::{ obj::{ObjInfo, ObjIns, ObjSection, ObjSectionKind, ObjSymbol, SymbolRef}, }; -mod code; -mod data; +pub mod code; +pub mod data; pub mod display; #[derive( @@ -321,9 +321,11 @@ pub fn diff_objs( let (right_obj, right_out) = right.as_mut().unwrap(); match section_kind { ObjSectionKind::Code => { + let left_code = process_code_symbol(left_obj, left_symbol_ref, config)?; + let right_code = process_code_symbol(right_obj, right_symbol_ref, config)?; let (left_diff, right_diff) = diff_code( - left_obj, - right_obj, + &left_code, + &right_code, left_symbol_ref, right_symbol_ref, config, @@ -333,9 +335,10 @@ pub fn diff_objs( if let Some(prev_symbol_ref) = prev_symbol_ref { let (prev_obj, prev_out) = prev.as_mut().unwrap(); + let prev_code = process_code_symbol(prev_obj, prev_symbol_ref, config)?; let (_, prev_diff) = diff_code( - right_obj, - prev_obj, + &right_code, + &prev_code, right_symbol_ref, prev_symbol_ref, config, @@ -369,8 +372,9 @@ pub fn diff_objs( let (left_obj, left_out) = left.as_mut().unwrap(); match section_kind { ObjSectionKind::Code => { + let code = process_code_symbol(left_obj, left_symbol_ref, config)?; *left_out.symbol_diff_mut(left_symbol_ref) = - no_diff_code(left_obj, left_symbol_ref, config)?; + no_diff_code(&code, left_symbol_ref)?; } ObjSectionKind::Data | ObjSectionKind::Bss => { *left_out.symbol_diff_mut(left_symbol_ref) = @@ -382,8 +386,9 @@ pub fn diff_objs( let (right_obj, right_out) = right.as_mut().unwrap(); match section_kind { ObjSectionKind::Code => { + let code = process_code_symbol(right_obj, right_symbol_ref, config)?; *right_out.symbol_diff_mut(right_symbol_ref) = - no_diff_code(right_obj, right_symbol_ref, config)?; + no_diff_code(&code, right_symbol_ref)?; } ObjSectionKind::Data | ObjSectionKind::Bss => { *right_out.symbol_diff_mut(right_symbol_ref) =