Skip to content

Commit

Permalink
Auto-detect MIPS ABI/category & add config
Browse files Browse the repository at this point in the history
Under Diff Options -> Arch Settings, one
can override the ABI/instruction category
  • Loading branch information
encounter committed May 22, 2024
1 parent e254af5 commit 9e57a66
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 34 deletions.
8 changes: 5 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion objdiff-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "objdiff-cli"
version = "2.0.0-alpha.1"
version = "2.0.0-alpha.2"
edition = "2021"
rust-version = "1.70"
authors = ["Luke Street <[email protected]>"]
Expand Down
6 changes: 4 additions & 2 deletions objdiff-cli/src/cmd/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,8 +821,10 @@ impl FunctionDiffUi {
.transpose()?;
let config = diff::DiffObjConfig {
relax_reloc_diffs: self.relax_reloc_diffs,
space_between_args: true, // TODO
x86_formatter: Default::default(), // TODO
space_between_args: true, // TODO
x86_formatter: Default::default(), // TODO
mips_abi: Default::default(), // TODO
mips_instr_category: Default::default(), // TODO
};
let result = diff::diff_objs(&config, target.as_ref(), base.as_ref(), prev.as_ref())?;

Expand Down
3 changes: 2 additions & 1 deletion objdiff-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>"]
Expand Down Expand Up @@ -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 }
Expand Down
59 changes: 51 additions & 8 deletions objdiff-core/src/arch/mips.rs
Original file line number Diff line number Diff line change
@@ -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 })
}
}

Expand All @@ -39,6 +66,22 @@ impl ObjArch for ObjArchMips {
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,
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;
Expand All @@ -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;
Expand Down
73 changes: 72 additions & 1 deletion objdiff-core/src/diff/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }

Expand All @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion objdiff-gui/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "objdiff-gui"
version = "2.0.0-alpha.1"
version = "2.0.0-alpha.2"
edition = "2021"
rust-version = "1.70"
authors = ["Luke Street <[email protected]>"]
Expand Down Expand Up @@ -46,6 +46,7 @@ ron = "0.8.1"
serde = { version = "1", features = ["derive"] }
serde_json = "1.0.116"
shell-escape = "0.1.5"
strum = { version = "0.26.2", features = ["derive"] }
tempfile = "3.10.1"
time = { version = "0.3.36", features = ["formatting", "local-offset"] }

Expand Down
12 changes: 6 additions & 6 deletions objdiff-gui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
views::{
appearance::{appearance_window, Appearance},
config::{
config_ui, diff_config_window, project_window, ConfigViewState, CONFIG_DISABLED_TEXT,
arch_config_window, config_ui, project_window, ConfigViewState, CONFIG_DISABLED_TEXT,
},
data_diff::data_diff_ui,
debug::debug_window,
Expand All @@ -52,7 +52,7 @@ pub struct ViewState {
pub show_appearance_config: bool,
pub show_demangle: bool,
pub show_project_config: bool,
pub show_diff_config: bool,
pub show_arch_config: bool,
pub show_debug: bool,
}

Expand Down Expand Up @@ -414,7 +414,7 @@ impl eframe::App for App {
show_appearance_config,
show_demangle,
show_project_config,
show_diff_config,
show_arch_config,
show_debug,
} = view_state;

Expand Down Expand Up @@ -468,8 +468,8 @@ impl eframe::App for App {
}
});
ui.menu_button("Diff Options", |ui| {
if ui.button("More…").clicked() {
*show_diff_config = !*show_diff_config;
if ui.button("Arch Settings…").clicked() {
*show_arch_config = !*show_arch_config;
ui.close_menu();
}
let mut config = config.write().unwrap();
Expand Down Expand Up @@ -541,7 +541,7 @@ impl eframe::App for App {
project_window(ctx, config, show_project_config, config_state, appearance);
appearance_window(ctx, show_appearance_config, appearance);
demangle_window(ctx, show_demangle, demangle_state, appearance);
diff_config_window(ctx, config, show_diff_config, appearance);
arch_config_window(ctx, config, show_arch_config, appearance);
debug_window(ctx, show_debug, frame_history, appearance);

self.post_update(ctx);
Expand Down
Loading

0 comments on commit 9e57a66

Please sign in to comment.