Skip to content

Commit 0fb7f39

Browse files
committed
Add PPC COFF tests; fix IMAGE_REL_PPC_PAIR handling
1 parent 3385f58 commit 0fb7f39

File tree

13 files changed

+4485
-41
lines changed

13 files changed

+4485
-41
lines changed

objdiff-core/src/arch/arm.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,10 +363,10 @@ impl Arch for ArchArm {
363363
address: u64,
364364
_relocation: &object::Relocation,
365365
flags: RelocationFlags,
366-
) -> Result<i64> {
366+
) -> Result<Option<i64>> {
367367
let section_data = section.data()?;
368368
let address = address as usize;
369-
Ok(match flags {
369+
Ok(Some(match flags {
370370
// ARM calls
371371
RelocationFlags::Elf(elf::R_ARM_PC24)
372372
| RelocationFlags::Elf(elf::R_ARM_XPC25)
@@ -396,7 +396,7 @@ impl Arch for ArchArm {
396396
}
397397

398398
flags => bail!("Unsupported ARM implicit relocation {flags:?}"),
399-
} as i64)
399+
} as i64))
400400
}
401401

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

objdiff-core/src/arch/arm64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl Arch for ArchArm64 {
115115
address: u64,
116116
_relocation: &object::Relocation,
117117
flags: RelocationFlags,
118-
) -> Result<i64> {
118+
) -> Result<Option<i64>> {
119119
bail!("Unsupported ARM64 implicit relocation {:#x}:{:?}", address, flags)
120120
}
121121

objdiff-core/src/arch/mips.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,22 +232,22 @@ impl Arch for ArchMips {
232232
address: u64,
233233
reloc: &object::Relocation,
234234
flags: RelocationFlags,
235-
) -> Result<i64> {
235+
) -> Result<Option<i64>> {
236236
// Check for paired R_MIPS_HI16 and R_MIPS_LO16 relocations.
237237
if let RelocationFlags::Elf(elf::R_MIPS_HI16 | elf::R_MIPS_LO16) = flags {
238238
if let Some(addend) = self
239239
.paired_relocations
240240
.get(section.index().0)
241241
.and_then(|m| m.get(&address).copied())
242242
{
243-
return Ok(addend);
243+
return Ok(Some(addend));
244244
}
245245
}
246246

247247
let data = section.data()?;
248248
let code = data[address as usize..address as usize + 4].try_into()?;
249249
let addend = self.endianness.read_u32_bytes(code);
250-
Ok(match flags {
250+
Ok(Some(match flags {
251251
RelocationFlags::Elf(elf::R_MIPS_32) => addend as i64,
252252
RelocationFlags::Elf(elf::R_MIPS_26) => ((addend & 0x03FFFFFF) << 2) as i64,
253253
RelocationFlags::Elf(elf::R_MIPS_HI16) => ((addend & 0x0000FFFF) << 16) as i32 as i64,
@@ -271,7 +271,7 @@ impl Arch for ArchMips {
271271
RelocationFlags::Elf(elf::R_MIPS_PC16) => 0, // PC-relative relocation
272272
RelocationFlags::Elf(R_MIPS15_S3) => ((addend & 0x001FFFC0) >> 3) as i64,
273273
flags => bail!("Unsupported MIPS implicit relocation {flags:?}"),
274-
})
274+
}))
275275
}
276276

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

objdiff-core/src/arch/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ pub trait Arch: Send + Sync + Debug {
364364
address: u64,
365365
relocation: &object::Relocation,
366366
flags: RelocationFlags,
367-
) -> Result<i64>;
367+
) -> Result<Option<i64>>;
368368

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

@@ -463,8 +463,8 @@ impl Arch for ArchDummy {
463463
_address: u64,
464464
_relocation: &object::Relocation,
465465
_flags: RelocationFlags,
466-
) -> Result<i64> {
467-
Ok(0)
466+
) -> Result<Option<i64>> {
467+
Ok(Some(0))
468468
}
469469

470470
fn data_reloc_size(&self, _flags: RelocationFlags) -> usize { 0 }

objdiff-core/src/arch/ppc/mod.rs

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ use alloc::{
66
vec::Vec,
77
};
88

9-
use anyhow::{Result, bail, ensure};
9+
use anyhow::{Result, anyhow, bail, ensure};
1010
use cwextab::{ExceptionTableData, decode_extab};
1111
use flagset::Flags;
12-
use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, elf, pe};
12+
use object::{Object as _, ObjectSection as _, ObjectSymbol as _, elf, pe};
1313

1414
use crate::{
1515
arch::{Arch, DataType},
@@ -210,32 +210,35 @@ impl Arch for ArchPpc {
210210

211211
fn implcit_addend(
212212
&self,
213-
file: &object::File<'_>,
213+
_file: &object::File<'_>,
214214
section: &object::Section,
215215
address: u64,
216216
_relocation: &object::Relocation,
217217
flags: RelocationFlags,
218-
) -> Result<i64> {
219-
let section_data = section.data()?;
220-
let address = address as usize;
221-
let data = section_data
222-
.get(address..address + 4)
223-
.ok_or_else(|| anyhow::anyhow!("Invalid address {address} for section data"))?
224-
.try_into()?;
225-
let code = file.endianness().read_u32_bytes(data);
226-
Ok(match flags {
218+
) -> Result<Option<i64>> {
219+
match flags {
220+
// IMAGE_REL_PPC_PAIR contains the REF{HI,LO} displacement instead of a symbol index
227221
RelocationFlags::Coff(pe::IMAGE_REL_PPC_REFHI)
228-
| RelocationFlags::Coff(pe::IMAGE_REL_PPC_REFLO) => (code & 0xffff) as i16 as i32,
229-
RelocationFlags::Coff(pe::IMAGE_REL_PPC_REL24) => {
230-
// let addend = (((code & 0x3fffffc) << 6) as i32) >> 6;
231-
// println!("PPC_REL24 addend: {data:?} => {addend}");
232-
// addend
233-
0
234-
}
235-
RelocationFlags::Coff(pe::IMAGE_REL_PPC_ADDR32) => code as i32,
236-
RelocationFlags::Coff(pe::IMAGE_REL_PPC_PAIR) => 0,
237-
flags => bail!("Unsupported PPC implicit relocation {flags:?}"),
238-
} as i64)
222+
| RelocationFlags::Coff(pe::IMAGE_REL_PPC_REFLO) => section
223+
.relocations()
224+
.skip_while(|&(a, _)| a < address)
225+
.take_while(|&(a, _)| a == address)
226+
.find(|(_, reloc)| {
227+
matches!(reloc.flags(), object::RelocationFlags::Coff {
228+
typ: pe::IMAGE_REL_PPC_PAIR
229+
})
230+
})
231+
.map_or(Ok(Some(0)), |(_, reloc)| match reloc.target() {
232+
object::RelocationTarget::Symbol(index) => {
233+
Ok(Some(index.0 as u16 as i16 as i64))
234+
}
235+
target => Err(anyhow!("Unsupported IMAGE_REL_PPC_PAIR target {target:?}")),
236+
}),
237+
// Skip PAIR relocations as they are handled by the previous case
238+
RelocationFlags::Coff(pe::IMAGE_REL_PPC_PAIR) => Ok(None),
239+
RelocationFlags::Coff(_) => Ok(Some(0)),
240+
flags => Err(anyhow!("Unsupported PPC implicit relocation {flags:?}")),
241+
}
239242
}
240243

241244
fn demangle(&self, name: &str) -> Option<String> {
@@ -263,7 +266,15 @@ impl Arch for ArchPpc {
263266
elf::R_PPC_REL14 => Some("R_PPC_REL14"),
264267
_ => None,
265268
},
266-
_ => None,
269+
RelocationFlags::Coff(r_type) => match r_type {
270+
pe::IMAGE_REL_PPC_ADDR32 => Some("IMAGE_REL_PPC_ADDR32"),
271+
pe::IMAGE_REL_PPC_REFHI => Some("IMAGE_REL_PPC_REFHI"),
272+
pe::IMAGE_REL_PPC_REFLO => Some("IMAGE_REL_PPC_REFLO"),
273+
pe::IMAGE_REL_PPC_REL24 => Some("IMAGE_REL_PPC_REL24"),
274+
pe::IMAGE_REL_PPC_REL14 => Some("IMAGE_REL_PPC_REL14"),
275+
pe::IMAGE_REL_PPC_PAIR => Some("IMAGE_REL_PPC_PAIR"),
276+
_ => None,
277+
},
267278
}
268279
}
269280

objdiff-core/src/arch/superh/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl Arch for ArchSuperH {
139139
address: u64,
140140
_relocation: &object::Relocation,
141141
flags: RelocationFlags,
142-
) -> Result<i64> {
142+
) -> Result<Option<i64>> {
143143
bail!("Unsupported SuperH implicit relocation {:#x}:{:?}", address, flags)
144144
}
145145

objdiff-core/src/arch/x86.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,14 @@ impl Arch for ArchX86 {
232232
address: u64,
233233
_relocation: &object::Relocation,
234234
flags: RelocationFlags,
235-
) -> Result<i64> {
235+
) -> Result<Option<i64>> {
236236
match self.arch {
237237
Architecture::X86 => match flags {
238238
RelocationFlags::Coff(pe::IMAGE_REL_I386_DIR32 | pe::IMAGE_REL_I386_REL32)
239239
| RelocationFlags::Elf(elf::R_386_32 | elf::R_386_PC32) => {
240240
let data =
241241
section.data()?[address as usize..address as usize + 4].try_into()?;
242-
Ok(self.endianness.read_i32_bytes(data) as i64)
242+
Ok(Some(self.endianness.read_i32_bytes(data) as i64))
243243
}
244244
flags => bail!("Unsupported x86 implicit relocation {flags:?}"),
245245
},
@@ -248,13 +248,13 @@ impl Arch for ArchX86 {
248248
| RelocationFlags::Elf(elf::R_X86_64_32 | elf::R_X86_64_PC32) => {
249249
let data =
250250
section.data()?[address as usize..address as usize + 4].try_into()?;
251-
Ok(self.endianness.read_i32_bytes(data) as i64)
251+
Ok(Some(self.endianness.read_i32_bytes(data) as i64))
252252
}
253253
RelocationFlags::Coff(pe::IMAGE_REL_AMD64_ADDR64)
254254
| RelocationFlags::Elf(elf::R_X86_64_64) => {
255255
let data =
256256
section.data()?[address as usize..address as usize + 8].try_into()?;
257-
Ok(self.endianness.read_i64_bytes(data))
257+
Ok(Some(self.endianness.read_i64_bytes(data)))
258258
}
259259
flags => bail!("Unsupported x86-64 implicit relocation {flags:?}"),
260260
},

objdiff-core/src/obj/read.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,10 @@ fn map_section_relocations(
338338
};
339339
// TODO validate reloc here?
340340
let mut addend = if reloc.has_implicit_addend() {
341-
arch.implcit_addend(obj_file, obj_section, address, &reloc, flags)?
341+
match arch.implcit_addend(obj_file, obj_section, address, &reloc, flags)? {
342+
Some(addend) => addend,
343+
None => continue, // Skip relocation (e.g. COFF PAIR relocations)
344+
}
342345
} else {
343346
reloc.addend()
344347
};

objdiff-core/tests/arch_ppc.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,31 @@ fn diff_ppc() {
8585
assert_eq!(base_symbol_diff.target_symbol, Some(target_symbol_idx));
8686
insta::assert_debug_snapshot!((target_symbol_diff, base_symbol_diff));
8787
}
88+
89+
#[test]
90+
#[cfg(feature = "ppc")]
91+
fn read_vmx128_coff() {
92+
let diff_config = diff::DiffObjConfig { combine_data_sections: true, ..Default::default() };
93+
let obj = obj::read::parse(include_object!("data/ppc/vmx128.obj"), &diff_config).unwrap();
94+
insta::assert_debug_snapshot!(obj);
95+
let symbol_idx =
96+
obj.symbols.iter().position(|s| s.name == "?FloatingPointExample@@YAXXZ").unwrap();
97+
let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap();
98+
insta::assert_debug_snapshot!(diff.instruction_rows);
99+
let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config);
100+
insta::assert_snapshot!(output);
101+
}
102+
103+
#[test]
104+
#[cfg(feature = "ppc")]
105+
fn read_dummy() {
106+
let diff_config = diff::DiffObjConfig { combine_data_sections: true, ..Default::default() };
107+
let obj = obj::read::parse(include_object!("data/ppc/dummy.obj"), &diff_config).unwrap();
108+
insta::assert_debug_snapshot!(obj);
109+
let symbol_idx =
110+
obj.symbols.iter().position(|s| s.name == "?FloatingPointExample@@YAXXZ").unwrap();
111+
let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap();
112+
insta::assert_debug_snapshot!(diff.instruction_rows);
113+
let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config);
114+
insta::assert_snapshot!(output);
115+
}
11.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)