Skip to content

Commit 00ad0d8

Browse files
committed
Support PPC64 ELFs (PS3); refactor relocation processing
1 parent 8fac63c commit 00ad0d8

File tree

10 files changed

+330
-190
lines changed

10 files changed

+330
-190
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Supports:
1919
- ARM (GBA, DS, 3DS)
2020
- ARM64 (Switch)
2121
- MIPS (N64, PS1, PS2, PSP)
22-
- PowerPC (GameCube, Wii, Xbox 360)
22+
- PowerPC (GameCube, Wii, PS3, Xbox 360)
2323
- SuperH (Saturn, Dreamcast)
2424
- x86, x86_64 (PC)
2525

objdiff-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ itertools = { version = "0.14", default-features = false, features = ["use_alloc
128128
log = { version = "0.4", default-features = false, optional = true }
129129
memmap2 = { version = "0.9", optional = true }
130130
num-traits = { version = "0.2", default-features = false, optional = true }
131-
object = { git = "https://github.com/gimli-rs/object", rev = "16ff70aa6fbd97d6bb7b92375929f4d72414c32b", default-features = false, features = ["read_core", "elf", "pe"] }
131+
object = { git = "https://github.com/gimli-rs/object", rev = "16ff70aa6fbd97d6bb7b92375929f4d72414c32b", default-features = false, features = ["read_core", "elf", "coff"] }
132132
pbjson = { version = "0.7", default-features = false, optional = true }
133133
prost = { version = "0.13", default-features = false, features = ["prost-derive"], optional = true }
134134
regex = { version = "1.11", default-features = false, features = [], optional = true }

objdiff-core/src/arch/arm.rs

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, el
1111
use unarm::{args, arm, thumb};
1212

1313
use crate::{
14-
arch::Arch,
14+
arch::{Arch, RelocationOverride, RelocationOverrideTarget},
1515
diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig, display::InstructionPart},
1616
obj::{
1717
InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
@@ -356,47 +356,57 @@ impl Arch for ArchArm {
356356
Ok(())
357357
}
358358

359-
fn implcit_addend(
359+
fn relocation_override(
360360
&self,
361361
_file: &object::File<'_>,
362362
section: &object::Section,
363363
address: u64,
364-
_relocation: &object::Relocation,
365-
flags: RelocationFlags,
366-
) -> Result<Option<i64>> {
367-
let section_data = section.data()?;
368-
let address = address as usize;
369-
Ok(Some(match flags {
370-
// ARM calls
371-
RelocationFlags::Elf(elf::R_ARM_PC24)
372-
| RelocationFlags::Elf(elf::R_ARM_XPC25)
373-
| RelocationFlags::Elf(elf::R_ARM_CALL) => {
374-
let data = section_data[address..address + 4].try_into()?;
375-
let addend = self.endianness.read_i32_bytes(data);
376-
let imm24 = addend & 0xffffff;
377-
(imm24 << 2) << 8 >> 8
378-
}
364+
relocation: &object::Relocation,
365+
) -> Result<Option<RelocationOverride>> {
366+
match relocation.flags() {
367+
// Handle ELF implicit relocations
368+
object::RelocationFlags::Elf { r_type } => {
369+
if relocation.has_implicit_addend() {
370+
let section_data = section.data()?;
371+
let address = address as usize;
372+
let addend = match r_type {
373+
// ARM calls
374+
elf::R_ARM_PC24 | elf::R_ARM_XPC25 | elf::R_ARM_CALL => {
375+
let data = section_data[address..address + 4].try_into()?;
376+
let addend = self.endianness.read_i32_bytes(data);
377+
let imm24 = addend & 0xffffff;
378+
(imm24 << 2) << 8 >> 8
379+
}
379380

380-
// Thumb calls
381-
RelocationFlags::Elf(elf::R_ARM_THM_PC22)
382-
| RelocationFlags::Elf(elf::R_ARM_THM_XPC22) => {
383-
let data = section_data[address..address + 2].try_into()?;
384-
let high = self.endianness.read_i16_bytes(data) as i32;
385-
let data = section_data[address + 2..address + 4].try_into()?;
386-
let low = self.endianness.read_i16_bytes(data) as i32;
381+
// Thumb calls
382+
elf::R_ARM_THM_PC22 | elf::R_ARM_THM_XPC22 => {
383+
let data = section_data[address..address + 2].try_into()?;
384+
let high = self.endianness.read_i16_bytes(data) as i32;
385+
let data = section_data[address + 2..address + 4].try_into()?;
386+
let low = self.endianness.read_i16_bytes(data) as i32;
387387

388-
let imm22 = ((high & 0x7ff) << 11) | (low & 0x7ff);
389-
(imm22 << 1) << 9 >> 9
390-
}
388+
let imm22 = ((high & 0x7ff) << 11) | (low & 0x7ff);
389+
(imm22 << 1) << 9 >> 9
390+
}
391391

392-
// Data
393-
RelocationFlags::Elf(elf::R_ARM_ABS32) => {
394-
let data = section_data[address..address + 4].try_into()?;
395-
self.endianness.read_i32_bytes(data)
396-
}
392+
// Data
393+
elf::R_ARM_ABS32 => {
394+
let data = section_data[address..address + 4].try_into()?;
395+
self.endianness.read_i32_bytes(data)
396+
}
397397

398-
flags => bail!("Unsupported ARM implicit relocation {flags:?}"),
399-
} as i64))
398+
flags => bail!("Unsupported ARM implicit relocation {flags:?}"),
399+
};
400+
Ok(Some(RelocationOverride {
401+
target: RelocationOverrideTarget::Keep,
402+
addend: addend as i64,
403+
}))
404+
} else {
405+
Ok(None)
406+
}
407+
}
408+
_ => Ok(None),
409+
}
400410
}
401411

402412
fn demangle(&self, name: &str) -> Option<String> {

objdiff-core/src/arch/arm64.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use alloc::{
55
};
66
use core::cmp::Ordering;
77

8-
use anyhow::{Result, bail};
8+
use anyhow::Result;
99
use object::elf;
1010
use yaxpeax_arch::{Arch as YaxpeaxArch, Decoder, Reader, U8Reader};
1111
use yaxpeax_arm::armv8::a64::{
@@ -108,17 +108,6 @@ impl Arch for ArchArm64 {
108108
Ok(())
109109
}
110110

111-
fn implcit_addend(
112-
&self,
113-
_file: &object::File<'_>,
114-
_section: &object::Section,
115-
address: u64,
116-
_relocation: &object::Relocation,
117-
flags: RelocationFlags,
118-
) -> Result<Option<i64>> {
119-
bail!("Unsupported ARM64 implicit relocation {:#x}:{:?}", address, flags)
120-
}
121-
122111
fn demangle(&self, name: &str) -> Option<String> {
123112
cpp_demangle::Symbol::new(name)
124113
.ok()

objdiff-core/src/arch/mips.rs

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rabbitizer::{
1414
};
1515

1616
use crate::{
17-
arch::Arch,
17+
arch::{Arch, RelocationOverride, RelocationOverrideTarget},
1818
diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart},
1919
obj::{
2020
InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags,
@@ -225,53 +225,67 @@ impl Arch for ArchMips {
225225
Ok(())
226226
}
227227

228-
fn implcit_addend(
228+
fn relocation_override(
229229
&self,
230230
file: &object::File<'_>,
231231
section: &object::Section,
232232
address: u64,
233-
reloc: &object::Relocation,
234-
flags: RelocationFlags,
235-
) -> Result<Option<i64>> {
236-
// Check for paired R_MIPS_HI16 and R_MIPS_LO16 relocations.
237-
if let RelocationFlags::Elf(elf::R_MIPS_HI16 | elf::R_MIPS_LO16) = flags {
238-
if let Some(addend) = self
239-
.paired_relocations
240-
.get(section.index().0)
241-
.and_then(|m| m.get(&address).copied())
242-
{
243-
return Ok(Some(addend));
244-
}
245-
}
233+
relocation: &object::Relocation,
234+
) -> Result<Option<RelocationOverride>> {
235+
match relocation.flags() {
236+
// Handle ELF implicit relocations
237+
object::RelocationFlags::Elf { r_type } => {
238+
if relocation.has_implicit_addend() {
239+
// Check for paired R_MIPS_HI16 and R_MIPS_LO16 relocations.
240+
if let elf::R_MIPS_HI16 | elf::R_MIPS_LO16 = r_type {
241+
if let Some(addend) = self
242+
.paired_relocations
243+
.get(section.index().0)
244+
.and_then(|m| m.get(&address).copied())
245+
{
246+
return Ok(Some(RelocationOverride {
247+
target: RelocationOverrideTarget::Keep,
248+
addend,
249+
}));
250+
}
251+
}
246252

247-
let data = section.data()?;
248-
let code = data[address as usize..address as usize + 4].try_into()?;
249-
let addend = self.endianness.read_u32_bytes(code);
250-
Ok(Some(match flags {
251-
RelocationFlags::Elf(elf::R_MIPS_32) => addend as i64,
252-
RelocationFlags::Elf(elf::R_MIPS_26) => ((addend & 0x03FFFFFF) << 2) as i64,
253-
RelocationFlags::Elf(elf::R_MIPS_HI16) => ((addend & 0x0000FFFF) << 16) as i32 as i64,
254-
RelocationFlags::Elf(elf::R_MIPS_LO16 | elf::R_MIPS_GOT16 | elf::R_MIPS_CALL16) => {
255-
(addend & 0x0000FFFF) as i16 as i64
256-
}
257-
RelocationFlags::Elf(elf::R_MIPS_GPREL16 | elf::R_MIPS_LITERAL) => {
258-
let object::RelocationTarget::Symbol(idx) = reloc.target() else {
259-
bail!("Unsupported R_MIPS_GPREL16 relocation against a non-symbol");
260-
};
261-
let sym = file.symbol_by_index(idx)?;
253+
let data = section.data()?;
254+
let code = self
255+
.endianness
256+
.read_u32_bytes(data[address as usize..address as usize + 4].try_into()?);
257+
let addend = match r_type {
258+
elf::R_MIPS_32 => code as i64,
259+
elf::R_MIPS_26 => ((code & 0x03FFFFFF) << 2) as i64,
260+
elf::R_MIPS_HI16 => ((code & 0x0000FFFF) << 16) as i32 as i64,
261+
elf::R_MIPS_LO16 | elf::R_MIPS_GOT16 | elf::R_MIPS_CALL16 => {
262+
(code & 0x0000FFFF) as i16 as i64
263+
}
264+
elf::R_MIPS_GPREL16 | elf::R_MIPS_LITERAL => {
265+
let object::RelocationTarget::Symbol(idx) = relocation.target() else {
266+
bail!("Unsupported R_MIPS_GPREL16 relocation against a non-symbol");
267+
};
268+
let sym = file.symbol_by_index(idx)?;
262269

263-
// if the symbol we are relocating against is in a local section we need to add
264-
// the ri_gp_value from .reginfo to the addend.
265-
if sym.section().index().is_some() {
266-
((addend & 0x0000FFFF) as i16 as i64) + self.ri_gp_value as i64
270+
// if the symbol we are relocating against is in a local section we need to add
271+
// the ri_gp_value from .reginfo to the addend.
272+
if sym.section().index().is_some() {
273+
((code & 0x0000FFFF) as i16 as i64) + self.ri_gp_value as i64
274+
} else {
275+
(code & 0x0000FFFF) as i16 as i64
276+
}
277+
}
278+
elf::R_MIPS_PC16 => 0, // PC-relative relocation
279+
R_MIPS15_S3 => ((code & 0x001FFFC0) >> 3) as i64,
280+
flags => bail!("Unsupported MIPS implicit relocation {flags:?}"),
281+
};
282+
Ok(Some(RelocationOverride { target: RelocationOverrideTarget::Keep, addend }))
267283
} else {
268-
(addend & 0x0000FFFF) as i16 as i64
284+
Ok(None)
269285
}
270286
}
271-
RelocationFlags::Elf(elf::R_MIPS_PC16) => 0, // PC-relative relocation
272-
RelocationFlags::Elf(R_MIPS15_S3) => ((addend & 0x001FFFC0) >> 3) as i64,
273-
flags => bail!("Unsupported MIPS implicit relocation {flags:?}"),
274-
}))
287+
_ => Ok(None),
288+
}
275289
}
276290

277291
fn demangle(&self, name: &str) -> Option<String> {

objdiff-core/src/arch/mod.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,15 @@ pub trait Arch: Send + Sync + Debug {
357357
None
358358
}
359359

360-
fn implcit_addend(
360+
fn relocation_override(
361361
&self,
362-
file: &object::File<'_>,
363-
section: &object::Section,
364-
address: u64,
365-
relocation: &object::Relocation,
366-
flags: RelocationFlags,
367-
) -> Result<Option<i64>>;
362+
_file: &object::File<'_>,
363+
_section: &object::Section,
364+
_address: u64,
365+
_relocation: &object::Relocation,
366+
) -> Result<Option<RelocationOverride>> {
367+
Ok(None)
368+
}
368369

369370
fn demangle(&self, _name: &str) -> Option<String> { None }
370371

@@ -411,7 +412,9 @@ pub fn new_arch(object: &object::File) -> Result<Box<dyn Arch>> {
411412
use object::Object as _;
412413
Ok(match object.architecture() {
413414
#[cfg(feature = "ppc")]
414-
object::Architecture::PowerPc => Box::new(ppc::ArchPpc::new(object)?),
415+
object::Architecture::PowerPc | object::Architecture::PowerPc64 => {
416+
Box::new(ppc::ArchPpc::new(object)?)
417+
}
415418
#[cfg(feature = "mips")]
416419
object::Architecture::Mips => Box::new(mips::ArchMips::new(object)?),
417420
#[cfg(feature = "x86")]
@@ -456,16 +459,17 @@ impl Arch for ArchDummy {
456459
Ok(())
457460
}
458461

459-
fn implcit_addend(
460-
&self,
461-
_file: &object::File<'_>,
462-
_section: &object::Section,
463-
_address: u64,
464-
_relocation: &object::Relocation,
465-
_flags: RelocationFlags,
466-
) -> Result<Option<i64>> {
467-
Ok(Some(0))
468-
}
469-
470462
fn data_reloc_size(&self, _flags: RelocationFlags) -> usize { 0 }
471463
}
464+
465+
pub enum RelocationOverrideTarget {
466+
Keep,
467+
Skip,
468+
Symbol(object::SymbolIndex),
469+
Section(object::SectionIndex),
470+
}
471+
472+
pub struct RelocationOverride {
473+
pub target: RelocationOverrideTarget,
474+
pub addend: i64,
475+
}

0 commit comments

Comments
 (0)