Add PPC COFF tests; fix IMAGE_REL_PPC_PAIR handling

This commit is contained in:
2025-07-17 21:19:06 -06:00
parent 3385f58341
commit 0fb7f3901c
13 changed files with 4485 additions and 41 deletions

View File

@@ -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> {

View File

@@ -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)
}

View File

@@ -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> {

View File

@@ -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 }

View File

@@ -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,
},
}
}

View File

@@ -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)
}

View File

@@ -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:?}"),
},

View File

@@ -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()
};