mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-09 13:37:55 +00:00
Auto-detect MIPS ABI/category & add config
Under Diff Options -> Arch Settings, one can override the ABI/instruction category
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "objdiff-core"
|
||||
version = "2.0.0-alpha.1"
|
||||
version = "2.0.0-alpha.2"
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
authors = ["Luke Street <luke@street.dev>"]
|
||||
@@ -31,6 +31,7 @@ num-traits = "0.2.18"
|
||||
object = { version = "0.35.0", features = ["read_core", "std", "elf", "pe"], default-features = false }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
similar = { version = "2.5.0", default-features = false }
|
||||
strum = { version = "0.26.2", features = ["derive"] }
|
||||
|
||||
# config
|
||||
globset = { version = "0.4.14", features = ["serde1"], optional = true }
|
||||
|
||||
@@ -1,29 +1,56 @@
|
||||
use std::borrow::Cow;
|
||||
use std::{borrow::Cow, sync::Mutex};
|
||||
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use object::{elf, Endian, Endianness, File, Object, Relocation, RelocationFlags};
|
||||
use object::{elf, Endian, Endianness, File, FileFlags, Object, Relocation, RelocationFlags};
|
||||
use rabbitizer::{config, Abi, InstrCategory, Instruction, OperandType};
|
||||
|
||||
use crate::{
|
||||
arch::{ObjArch, ProcessCodeResult},
|
||||
diff::DiffObjConfig,
|
||||
diff::{DiffObjConfig, MipsAbi, MipsInstrCategory},
|
||||
obj::{ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection, SymbolRef},
|
||||
};
|
||||
|
||||
fn configure_rabbitizer() {
|
||||
static RABBITIZER_MUTEX: Mutex<()> = Mutex::new(());
|
||||
|
||||
fn configure_rabbitizer(abi: Abi) {
|
||||
unsafe {
|
||||
config::RabbitizerConfig_Cfg.reg_names.fpr_abi_names = Abi::O32;
|
||||
config::RabbitizerConfig_Cfg.reg_names.fpr_abi_names = abi;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ObjArchMips {
|
||||
pub endianness: Endianness,
|
||||
pub abi: Abi,
|
||||
pub instr_category: InstrCategory,
|
||||
}
|
||||
|
||||
const EF_MIPS_ABI: u32 = 0x0000F000;
|
||||
const EF_MIPS_MACH: u32 = 0x00FF0000;
|
||||
|
||||
const E_MIPS_MACH_ALLEGREX: u32 = 0x00840000;
|
||||
const E_MIPS_MACH_5900: u32 = 0x00920000;
|
||||
|
||||
impl ObjArchMips {
|
||||
pub fn new(object: &File) -> Result<Self> {
|
||||
configure_rabbitizer();
|
||||
Ok(Self { endianness: object.endianness() })
|
||||
let mut abi = Abi::NUMERIC;
|
||||
let mut instr_category = InstrCategory::CPU;
|
||||
match object.flags() {
|
||||
FileFlags::None => {}
|
||||
FileFlags::Elf { e_flags, .. } => {
|
||||
abi = match e_flags & EF_MIPS_ABI {
|
||||
elf::EF_MIPS_ABI_O32 => Abi::O32,
|
||||
elf::EF_MIPS_ABI_EABI32 | elf::EF_MIPS_ABI_EABI64 => Abi::N32,
|
||||
_ => Abi::NUMERIC,
|
||||
};
|
||||
instr_category = match e_flags & EF_MIPS_MACH {
|
||||
E_MIPS_MACH_ALLEGREX => InstrCategory::R4000ALLEGREX,
|
||||
E_MIPS_MACH_5900 => InstrCategory::R5900,
|
||||
_ => InstrCategory::CPU,
|
||||
};
|
||||
}
|
||||
_ => bail!("Unsupported MIPS file flags"),
|
||||
}
|
||||
Ok(Self { endianness: object.endianness(), abi, instr_category })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +66,22 @@ impl ObjArch for ObjArchMips {
|
||||
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,
|
||||
MipsAbi::O32 => Abi::O32,
|
||||
MipsAbi::N32 => Abi::N32,
|
||||
MipsAbi::N64 => Abi::N64,
|
||||
});
|
||||
let instr_category = match config.mips_instr_category {
|
||||
MipsInstrCategory::Auto => self.instr_category,
|
||||
MipsInstrCategory::Cpu => InstrCategory::CPU,
|
||||
MipsInstrCategory::Rsp => InstrCategory::RSP,
|
||||
MipsInstrCategory::R3000Gte => InstrCategory::R3000GTE,
|
||||
MipsInstrCategory::R4000Allegrex => InstrCategory::R4000ALLEGREX,
|
||||
MipsInstrCategory::R5900 => InstrCategory::R5900,
|
||||
};
|
||||
|
||||
let start_address = symbol.address;
|
||||
let end_address = symbol.address + symbol.size;
|
||||
let ins_count = code.len() / 4;
|
||||
@@ -48,7 +91,7 @@ impl ObjArch for ObjArchMips {
|
||||
for chunk in code.chunks_exact(4) {
|
||||
let reloc = section.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, InstrCategory::CPU);
|
||||
let instruction = Instruction::new(code, cur_addr, instr_category);
|
||||
|
||||
let formatted = instruction.disassemble(None, 0);
|
||||
let op = instruction.unique_id as u16;
|
||||
|
||||
@@ -17,15 +17,82 @@ mod code;
|
||||
mod data;
|
||||
pub mod display;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Copy,
|
||||
Clone,
|
||||
Default,
|
||||
Eq,
|
||||
PartialEq,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::VariantArray,
|
||||
strum::EnumMessage,
|
||||
)]
|
||||
pub enum X86Formatter {
|
||||
#[default]
|
||||
#[strum(message = "Intel (default)")]
|
||||
Intel,
|
||||
#[strum(message = "AT&T")]
|
||||
Gas,
|
||||
#[strum(message = "NASM")]
|
||||
Nasm,
|
||||
#[strum(message = "MASM")]
|
||||
Masm,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Copy,
|
||||
Clone,
|
||||
Default,
|
||||
Eq,
|
||||
PartialEq,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::VariantArray,
|
||||
strum::EnumMessage,
|
||||
)]
|
||||
pub enum MipsAbi {
|
||||
#[default]
|
||||
#[strum(message = "Auto (default)")]
|
||||
Auto,
|
||||
#[strum(message = "O32")]
|
||||
O32,
|
||||
#[strum(message = "N32")]
|
||||
N32,
|
||||
#[strum(message = "N64")]
|
||||
N64,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Copy,
|
||||
Clone,
|
||||
Default,
|
||||
Eq,
|
||||
PartialEq,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::VariantArray,
|
||||
strum::EnumMessage,
|
||||
)]
|
||||
pub enum MipsInstrCategory {
|
||||
#[default]
|
||||
#[strum(message = "Auto (default)")]
|
||||
Auto,
|
||||
#[strum(message = "CPU")]
|
||||
Cpu,
|
||||
#[strum(message = "RSP (N64)")]
|
||||
Rsp,
|
||||
#[strum(message = "R3000 GTE (PS1)")]
|
||||
R3000Gte,
|
||||
#[strum(message = "R4000 ALLEGREX (PSP)")]
|
||||
R4000Allegrex,
|
||||
#[strum(message = "R5900 EE (PS2)")]
|
||||
R5900,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
const fn default_true() -> bool { true }
|
||||
|
||||
@@ -35,7 +102,11 @@ pub struct DiffObjConfig {
|
||||
pub relax_reloc_diffs: bool,
|
||||
#[serde(default = "default_true")]
|
||||
pub space_between_args: bool,
|
||||
// x86
|
||||
pub x86_formatter: X86Formatter,
|
||||
// MIPS
|
||||
pub mips_abi: MipsAbi,
|
||||
pub mips_instr_category: MipsInstrCategory,
|
||||
}
|
||||
|
||||
impl DiffObjConfig {
|
||||
|
||||
Reference in New Issue
Block a user