mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-11 14:41:51 +00:00
Add PPC COFF tests; fix IMAGE_REL_PPC_PAIR handling
This commit is contained in:
@@ -363,10 +363,10 @@ impl Arch for ArchArm {
|
||||
address: u64,
|
||||
_relocation: &object::Relocation,
|
||||
flags: RelocationFlags,
|
||||
) -> Result<i64> {
|
||||
) -> Result<Option<i64>> {
|
||||
let section_data = section.data()?;
|
||||
let address = address as usize;
|
||||
Ok(match flags {
|
||||
Ok(Some(match flags {
|
||||
// ARM calls
|
||||
RelocationFlags::Elf(elf::R_ARM_PC24)
|
||||
| RelocationFlags::Elf(elf::R_ARM_XPC25)
|
||||
@@ -396,7 +396,7 @@ impl Arch for ArchArm {
|
||||
}
|
||||
|
||||
flags => bail!("Unsupported ARM implicit relocation {flags:?}"),
|
||||
} as i64)
|
||||
} as i64))
|
||||
}
|
||||
|
||||
fn demangle(&self, name: &str) -> Option<String> {
|
||||
|
||||
@@ -115,7 +115,7 @@ impl Arch for ArchArm64 {
|
||||
address: u64,
|
||||
_relocation: &object::Relocation,
|
||||
flags: RelocationFlags,
|
||||
) -> Result<i64> {
|
||||
) -> Result<Option<i64>> {
|
||||
bail!("Unsupported ARM64 implicit relocation {:#x}:{:?}", address, flags)
|
||||
}
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ impl Arch for ArchMips {
|
||||
address: u64,
|
||||
reloc: &object::Relocation,
|
||||
flags: RelocationFlags,
|
||||
) -> Result<i64> {
|
||||
) -> Result<Option<i64>> {
|
||||
// Check for paired R_MIPS_HI16 and R_MIPS_LO16 relocations.
|
||||
if let RelocationFlags::Elf(elf::R_MIPS_HI16 | elf::R_MIPS_LO16) = flags {
|
||||
if let Some(addend) = self
|
||||
@@ -240,14 +240,14 @@ impl Arch for ArchMips {
|
||||
.get(section.index().0)
|
||||
.and_then(|m| m.get(&address).copied())
|
||||
{
|
||||
return Ok(addend);
|
||||
return Ok(Some(addend));
|
||||
}
|
||||
}
|
||||
|
||||
let data = section.data()?;
|
||||
let code = data[address as usize..address as usize + 4].try_into()?;
|
||||
let addend = self.endianness.read_u32_bytes(code);
|
||||
Ok(match flags {
|
||||
Ok(Some(match flags {
|
||||
RelocationFlags::Elf(elf::R_MIPS_32) => addend as i64,
|
||||
RelocationFlags::Elf(elf::R_MIPS_26) => ((addend & 0x03FFFFFF) << 2) as i64,
|
||||
RelocationFlags::Elf(elf::R_MIPS_HI16) => ((addend & 0x0000FFFF) << 16) as i32 as i64,
|
||||
@@ -271,7 +271,7 @@ impl Arch for ArchMips {
|
||||
RelocationFlags::Elf(elf::R_MIPS_PC16) => 0, // PC-relative relocation
|
||||
RelocationFlags::Elf(R_MIPS15_S3) => ((addend & 0x001FFFC0) >> 3) as i64,
|
||||
flags => bail!("Unsupported MIPS implicit relocation {flags:?}"),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn demangle(&self, name: &str) -> Option<String> {
|
||||
|
||||
@@ -364,7 +364,7 @@ pub trait Arch: Send + Sync + Debug {
|
||||
address: u64,
|
||||
relocation: &object::Relocation,
|
||||
flags: RelocationFlags,
|
||||
) -> Result<i64>;
|
||||
) -> Result<Option<i64>>;
|
||||
|
||||
fn demangle(&self, _name: &str) -> Option<String> { None }
|
||||
|
||||
@@ -463,8 +463,8 @@ impl Arch for ArchDummy {
|
||||
_address: u64,
|
||||
_relocation: &object::Relocation,
|
||||
_flags: RelocationFlags,
|
||||
) -> Result<i64> {
|
||||
Ok(0)
|
||||
) -> Result<Option<i64>> {
|
||||
Ok(Some(0))
|
||||
}
|
||||
|
||||
fn data_reloc_size(&self, _flags: RelocationFlags) -> usize { 0 }
|
||||
|
||||
@@ -6,10 +6,10 @@ use alloc::{
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use anyhow::{Result, bail, ensure};
|
||||
use anyhow::{Result, anyhow, bail, ensure};
|
||||
use cwextab::{ExceptionTableData, decode_extab};
|
||||
use flagset::Flags;
|
||||
use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, elf, pe};
|
||||
use object::{Object as _, ObjectSection as _, ObjectSymbol as _, elf, pe};
|
||||
|
||||
use crate::{
|
||||
arch::{Arch, DataType},
|
||||
@@ -210,32 +210,35 @@ impl Arch for ArchPpc {
|
||||
|
||||
fn implcit_addend(
|
||||
&self,
|
||||
file: &object::File<'_>,
|
||||
_file: &object::File<'_>,
|
||||
section: &object::Section,
|
||||
address: u64,
|
||||
_relocation: &object::Relocation,
|
||||
flags: RelocationFlags,
|
||||
) -> Result<i64> {
|
||||
let section_data = section.data()?;
|
||||
let address = address as usize;
|
||||
let data = section_data
|
||||
.get(address..address + 4)
|
||||
.ok_or_else(|| anyhow::anyhow!("Invalid address {address} for section data"))?
|
||||
.try_into()?;
|
||||
let code = file.endianness().read_u32_bytes(data);
|
||||
Ok(match flags {
|
||||
) -> Result<Option<i64>> {
|
||||
match flags {
|
||||
// IMAGE_REL_PPC_PAIR contains the REF{HI,LO} displacement instead of a symbol index
|
||||
RelocationFlags::Coff(pe::IMAGE_REL_PPC_REFHI)
|
||||
| RelocationFlags::Coff(pe::IMAGE_REL_PPC_REFLO) => (code & 0xffff) as i16 as i32,
|
||||
RelocationFlags::Coff(pe::IMAGE_REL_PPC_REL24) => {
|
||||
// let addend = (((code & 0x3fffffc) << 6) as i32) >> 6;
|
||||
// println!("PPC_REL24 addend: {data:?} => {addend}");
|
||||
// addend
|
||||
0
|
||||
}
|
||||
RelocationFlags::Coff(pe::IMAGE_REL_PPC_ADDR32) => code as i32,
|
||||
RelocationFlags::Coff(pe::IMAGE_REL_PPC_PAIR) => 0,
|
||||
flags => bail!("Unsupported PPC implicit relocation {flags:?}"),
|
||||
} as i64)
|
||||
| RelocationFlags::Coff(pe::IMAGE_REL_PPC_REFLO) => section
|
||||
.relocations()
|
||||
.skip_while(|&(a, _)| a < address)
|
||||
.take_while(|&(a, _)| a == address)
|
||||
.find(|(_, reloc)| {
|
||||
matches!(reloc.flags(), object::RelocationFlags::Coff {
|
||||
typ: pe::IMAGE_REL_PPC_PAIR
|
||||
})
|
||||
})
|
||||
.map_or(Ok(Some(0)), |(_, reloc)| match reloc.target() {
|
||||
object::RelocationTarget::Symbol(index) => {
|
||||
Ok(Some(index.0 as u16 as i16 as i64))
|
||||
}
|
||||
target => Err(anyhow!("Unsupported IMAGE_REL_PPC_PAIR target {target:?}")),
|
||||
}),
|
||||
// Skip PAIR relocations as they are handled by the previous case
|
||||
RelocationFlags::Coff(pe::IMAGE_REL_PPC_PAIR) => Ok(None),
|
||||
RelocationFlags::Coff(_) => Ok(Some(0)),
|
||||
flags => Err(anyhow!("Unsupported PPC implicit relocation {flags:?}")),
|
||||
}
|
||||
}
|
||||
|
||||
fn demangle(&self, name: &str) -> Option<String> {
|
||||
@@ -263,7 +266,15 @@ impl Arch for ArchPpc {
|
||||
elf::R_PPC_REL14 => Some("R_PPC_REL14"),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
RelocationFlags::Coff(r_type) => match r_type {
|
||||
pe::IMAGE_REL_PPC_ADDR32 => Some("IMAGE_REL_PPC_ADDR32"),
|
||||
pe::IMAGE_REL_PPC_REFHI => Some("IMAGE_REL_PPC_REFHI"),
|
||||
pe::IMAGE_REL_PPC_REFLO => Some("IMAGE_REL_PPC_REFLO"),
|
||||
pe::IMAGE_REL_PPC_REL24 => Some("IMAGE_REL_PPC_REL24"),
|
||||
pe::IMAGE_REL_PPC_REL14 => Some("IMAGE_REL_PPC_REL14"),
|
||||
pe::IMAGE_REL_PPC_PAIR => Some("IMAGE_REL_PPC_PAIR"),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ impl Arch for ArchSuperH {
|
||||
address: u64,
|
||||
_relocation: &object::Relocation,
|
||||
flags: RelocationFlags,
|
||||
) -> Result<i64> {
|
||||
) -> Result<Option<i64>> {
|
||||
bail!("Unsupported SuperH implicit relocation {:#x}:{:?}", address, flags)
|
||||
}
|
||||
|
||||
|
||||
@@ -232,14 +232,14 @@ impl Arch for ArchX86 {
|
||||
address: u64,
|
||||
_relocation: &object::Relocation,
|
||||
flags: RelocationFlags,
|
||||
) -> Result<i64> {
|
||||
) -> Result<Option<i64>> {
|
||||
match self.arch {
|
||||
Architecture::X86 => match flags {
|
||||
RelocationFlags::Coff(pe::IMAGE_REL_I386_DIR32 | pe::IMAGE_REL_I386_REL32)
|
||||
| RelocationFlags::Elf(elf::R_386_32 | elf::R_386_PC32) => {
|
||||
let data =
|
||||
section.data()?[address as usize..address as usize + 4].try_into()?;
|
||||
Ok(self.endianness.read_i32_bytes(data) as i64)
|
||||
Ok(Some(self.endianness.read_i32_bytes(data) as i64))
|
||||
}
|
||||
flags => bail!("Unsupported x86 implicit relocation {flags:?}"),
|
||||
},
|
||||
@@ -248,13 +248,13 @@ impl Arch for ArchX86 {
|
||||
| RelocationFlags::Elf(elf::R_X86_64_32 | elf::R_X86_64_PC32) => {
|
||||
let data =
|
||||
section.data()?[address as usize..address as usize + 4].try_into()?;
|
||||
Ok(self.endianness.read_i32_bytes(data) as i64)
|
||||
Ok(Some(self.endianness.read_i32_bytes(data) as i64))
|
||||
}
|
||||
RelocationFlags::Coff(pe::IMAGE_REL_AMD64_ADDR64)
|
||||
| RelocationFlags::Elf(elf::R_X86_64_64) => {
|
||||
let data =
|
||||
section.data()?[address as usize..address as usize + 8].try_into()?;
|
||||
Ok(self.endianness.read_i64_bytes(data))
|
||||
Ok(Some(self.endianness.read_i64_bytes(data)))
|
||||
}
|
||||
flags => bail!("Unsupported x86-64 implicit relocation {flags:?}"),
|
||||
},
|
||||
|
||||
@@ -338,7 +338,10 @@ fn map_section_relocations(
|
||||
};
|
||||
// TODO validate reloc here?
|
||||
let mut addend = if reloc.has_implicit_addend() {
|
||||
arch.implcit_addend(obj_file, obj_section, address, &reloc, flags)?
|
||||
match arch.implcit_addend(obj_file, obj_section, address, &reloc, flags)? {
|
||||
Some(addend) => addend,
|
||||
None => continue, // Skip relocation (e.g. COFF PAIR relocations)
|
||||
}
|
||||
} else {
|
||||
reloc.addend()
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user