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
This commit is contained in:
2024-06-03 18:51:44 -06:00
parent 0ea6242669
commit 3f82c1a50f
6 changed files with 71 additions and 67 deletions

View File

@@ -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<u64, u64>,
config: &DiffObjConfig,
) -> Result<ProcessCodeResult> {
let (section, symbol) = obj.section_symbol(symbol_ref);
let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?;
let code = &section.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::<u16>::with_capacity(ins_count);
let mut insts = Vec::<ObjIns>::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,

View File

@@ -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<u64, u64>,
config: &DiffObjConfig,
) -> Result<ProcessCodeResult>;

View File

@@ -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<u64, u64>,
config: &DiffObjConfig,
) -> Result<ProcessCodeResult> {
let (section, symbol) = obj.section_symbol(symbol_ref);
let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?;
let code = &section.data
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
let ins_count = code.len() / 4;
let mut ops = Vec::<u16>::with_capacity(ins_count);
let mut insts = Vec::<ObjIns>::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,

View File

@@ -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<u64, u64>,
config: &DiffObjConfig,
) -> Result<ProcessCodeResult> {
let (section, symbol) = obj.section_symbol(symbol_ref);
let section = section.ok_or_else(|| anyhow!("Code symbol section not found"))?;
let code = &section.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<dyn Formatter> = 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,