Skip to content

Commit

Permalink
Support Aarch64Call relocations for Mach-O
Browse files Browse the repository at this point in the history
Including calls with arbitrary addends
  • Loading branch information
nathanwhit committed Sep 30, 2022
1 parent 89eec0a commit 6517a8b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
26 changes: 24 additions & 2 deletions src/write/macho.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ impl<'a> Object<'a> {
debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len());
for reloc in &section.relocations {
let r_extern;
let r_symbolnum;
let mut r_symbolnum;
let symbol = &self.symbols[reloc.symbol.0];
if symbol.kind == SymbolKind::Section {
r_symbolnum = section_offsets[symbol.section.id().unwrap().0].index as u32;
Expand All @@ -546,7 +546,7 @@ impl<'a> Object<'a> {
let r_length = match reloc.size {
8 => 0,
16 => 1,
32 => 2,
12 | 21 | 26 | 32 => 2,
64 => 3,
_ => return Err(Error(format!("unimplemented reloc size {:?}", reloc))),
};
Expand Down Expand Up @@ -590,6 +590,28 @@ impl<'a> Object<'a> {
(RelocationKind::Absolute, RelocationEncoding::Generic, 0) => {
(false, macho::ARM64_RELOC_UNSIGNED)
}
// Due to the fixup an addend of -4 here means the original addend was 0
(RelocationKind::Relative, RelocationEncoding::AArch64Call, -4) => {
(true, macho::ARM64_RELOC_BRANCH26)
}
// Non-zero addend, so we have to encode the addend separately
(RelocationKind::Relative, RelocationEncoding::AArch64Call, value) => {
// first emit the BR26 relocation
let reloc_info = macho::RelocationInfo {
r_address: reloc.offset as u32,
r_symbolnum,
r_pcrel: true,
r_length,
r_extern: true,
r_type: macho::ARM64_RELOC_BRANCH26,
};
buffer.write(&reloc_info.relocation(endian));

// set up a separate relocation for the addend
// we add 4 to undo the fixup of -4
r_symbolnum = (value + 4) as u32;
(false, macho::ARM64_RELOC_ADDEND)
}
(
RelocationKind::MachO { value, relative },
RelocationEncoding::Generic,
Expand Down
8 changes: 8 additions & 0 deletions src/write/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,14 @@ impl<'a> Object<'a> {
match relocation.size {
32 => data.write_at(offset, &U32::new(self.endian, addend as u32)),
64 => data.write_at(offset, &U64::new(self.endian, addend as u64)),

// For aarch64 call relocations in Mach-O, the addend is
// encoded in a separate relocation, so don't write it here
26 if relocation.encoding == RelocationEncoding::AArch64Call
&& self.format == BinaryFormat::MachO =>
{
Ok(())
}
_ => {
return Err(Error(format!(
"unimplemented relocation addend {:?}",
Expand Down

0 comments on commit 6517a8b

Please sign in to comment.