mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-09 13:37:55 +00:00
Updates & initial MIPS support
This commit is contained in:
74
src/obj/mips.rs
Normal file
74
src/obj/mips.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use anyhow::Result;
|
||||
use rabbitizer::{config_set_register_fpr_abi_names, Abi, Instruction, SimpleOperandType};
|
||||
|
||||
use crate::obj::{ObjIns, ObjInsArg, ObjReloc};
|
||||
|
||||
pub fn process_code(
|
||||
data: &[u8],
|
||||
start_address: u64,
|
||||
end_address: u64,
|
||||
relocs: &[ObjReloc],
|
||||
) -> Result<(Vec<u8>, Vec<ObjIns>)> {
|
||||
config_set_register_fpr_abi_names(Abi::RABBITIZER_ABI_O32);
|
||||
|
||||
let ins_count = data.len() / 4;
|
||||
let mut ops = Vec::<u8>::with_capacity(ins_count);
|
||||
let mut insts = Vec::<ObjIns>::with_capacity(ins_count);
|
||||
let mut cur_addr = start_address as u32;
|
||||
for chunk in data.chunks_exact(4) {
|
||||
let reloc = relocs.iter().find(|r| (r.address as u32 & !3) == cur_addr);
|
||||
let code = u32::from_be_bytes(chunk.try_into()?);
|
||||
let mut instruction = Instruction::new(code, cur_addr);
|
||||
|
||||
let op = instruction.instr_id() as u8;
|
||||
ops.push(op);
|
||||
|
||||
let mnemonic = instruction.instr_id().get_opcode_name().unwrap_or_default().to_string();
|
||||
let is_branch = instruction.is_branch();
|
||||
let branch_offset = instruction.branch_offset();
|
||||
let branch_dest =
|
||||
if is_branch { Some((cur_addr as i32 + branch_offset) as u32) } else { None };
|
||||
let args = instruction
|
||||
.simple_operands()
|
||||
.iter()
|
||||
.map(|op| match op.kind {
|
||||
SimpleOperandType::Imm | SimpleOperandType::Label => {
|
||||
if is_branch {
|
||||
ObjInsArg::BranchOffset(branch_offset)
|
||||
} else if let Some(reloc) = reloc {
|
||||
if matches!(&reloc.target_section, Some(s) if s == ".text")
|
||||
&& reloc.target.address > start_address
|
||||
&& reloc.target.address < end_address
|
||||
{
|
||||
// Inter-function reloc, convert to branch offset
|
||||
ObjInsArg::BranchOffset(reloc.target.address as i32 - cur_addr as i32)
|
||||
} else {
|
||||
ObjInsArg::Reloc
|
||||
}
|
||||
} else {
|
||||
ObjInsArg::MipsArg(op.disassembled.clone())
|
||||
}
|
||||
}
|
||||
SimpleOperandType::ImmBase => {
|
||||
if reloc.is_some() {
|
||||
ObjInsArg::RelocWithBase
|
||||
} else {
|
||||
ObjInsArg::MipsArg(op.disassembled.clone())
|
||||
}
|
||||
}
|
||||
_ => ObjInsArg::MipsArg(op.disassembled.clone()),
|
||||
})
|
||||
.collect();
|
||||
insts.push(ObjIns {
|
||||
address: cur_addr,
|
||||
code,
|
||||
op,
|
||||
mnemonic,
|
||||
args,
|
||||
reloc: reloc.cloned(),
|
||||
branch_dest,
|
||||
});
|
||||
cur_addr += 4;
|
||||
}
|
||||
Ok((ops, insts))
|
||||
}
|
||||
89
src/obj/ppc.rs
Normal file
89
src/obj/ppc.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use anyhow::Result;
|
||||
use ppc750cl::{disasm_iter, Argument};
|
||||
|
||||
use crate::obj::{ObjIns, ObjInsArg, ObjReloc, ObjRelocKind};
|
||||
|
||||
// Relative relocation, can be Simm or BranchOffset
|
||||
fn is_relative_arg(arg: &ObjInsArg) -> bool {
|
||||
matches!(arg, ObjInsArg::PpcArg(Argument::Simm(_)) | ObjInsArg::BranchOffset(_))
|
||||
}
|
||||
|
||||
// Relative or absolute relocation, can be Uimm, Simm or Offset
|
||||
fn is_rel_abs_arg(arg: &ObjInsArg) -> bool {
|
||||
matches!(arg, ObjInsArg::PpcArg(arg) if matches!(arg, Argument::Uimm(_) | Argument::Simm(_) | Argument::Offset(_)))
|
||||
}
|
||||
|
||||
fn is_offset_arg(arg: &ObjInsArg) -> bool { matches!(arg, ObjInsArg::PpcArg(Argument::Offset(_))) }
|
||||
|
||||
pub fn process_code(
|
||||
data: &[u8],
|
||||
address: u64,
|
||||
relocs: &[ObjReloc],
|
||||
) -> Result<(Vec<u8>, Vec<ObjIns>)> {
|
||||
let ins_count = data.len() / 4;
|
||||
let mut ops = Vec::<u8>::with_capacity(ins_count);
|
||||
let mut insts = Vec::<ObjIns>::with_capacity(ins_count);
|
||||
for mut ins in disasm_iter(data, address as u32) {
|
||||
let reloc = relocs.iter().find(|r| (r.address as u32 & !3) == ins.addr);
|
||||
if let Some(reloc) = reloc {
|
||||
// Zero out relocations
|
||||
ins.code = match reloc.kind {
|
||||
ObjRelocKind::PpcEmbSda21 => ins.code & !0x1FFFFF,
|
||||
ObjRelocKind::PpcRel24 => ins.code & !0x3FFFFFC,
|
||||
ObjRelocKind::PpcRel14 => ins.code & !0xFFFC,
|
||||
ObjRelocKind::PpcAddr16Hi
|
||||
| ObjRelocKind::PpcAddr16Ha
|
||||
| ObjRelocKind::PpcAddr16Lo => ins.code & !0xFFFF,
|
||||
_ => ins.code,
|
||||
};
|
||||
}
|
||||
let simplified = ins.simplified();
|
||||
let mut args: Vec<ObjInsArg> = simplified
|
||||
.args
|
||||
.iter()
|
||||
.map(|a| match a {
|
||||
Argument::BranchDest(dest) => ObjInsArg::BranchOffset(dest.0),
|
||||
_ => ObjInsArg::PpcArg(a.clone()),
|
||||
})
|
||||
.collect();
|
||||
if let Some(reloc) = reloc {
|
||||
match reloc.kind {
|
||||
ObjRelocKind::PpcEmbSda21 => {
|
||||
args = vec![args[0].clone(), ObjInsArg::Reloc];
|
||||
}
|
||||
ObjRelocKind::PpcRel24 | ObjRelocKind::PpcRel14 => {
|
||||
let arg = args
|
||||
.iter_mut()
|
||||
.rfind(|a| is_relative_arg(a))
|
||||
.ok_or_else(|| anyhow::Error::msg("Failed to locate rel arg for reloc"))?;
|
||||
*arg = ObjInsArg::Reloc;
|
||||
}
|
||||
ObjRelocKind::PpcAddr16Hi
|
||||
| ObjRelocKind::PpcAddr16Ha
|
||||
| ObjRelocKind::PpcAddr16Lo => {
|
||||
let arg = args.iter_mut().rfind(|a| is_rel_abs_arg(a)).ok_or_else(|| {
|
||||
anyhow::Error::msg("Failed to locate rel/abs arg for reloc")
|
||||
})?;
|
||||
*arg = if is_offset_arg(arg) {
|
||||
ObjInsArg::RelocWithBase
|
||||
} else {
|
||||
ObjInsArg::Reloc
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ops.push(simplified.ins.op as u8);
|
||||
let suffix = simplified.ins.suffix();
|
||||
insts.push(ObjIns {
|
||||
address: simplified.ins.addr,
|
||||
code: simplified.ins.code,
|
||||
mnemonic: format!("{}{}", simplified.mnemonic, suffix),
|
||||
args,
|
||||
reloc: reloc.cloned(),
|
||||
op: 0,
|
||||
branch_dest: None,
|
||||
});
|
||||
}
|
||||
Ok((ops, insts))
|
||||
}
|
||||
Reference in New Issue
Block a user