Skip to content

Commit

Permalink
read/macho: support Aarch64_Ilp32 (#545)
Browse files Browse the repository at this point in the history
  • Loading branch information
philipc authored May 9, 2023
1 parent b3436f0 commit 60a75e5
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 39 deletions.
1 change: 1 addition & 0 deletions src/read/macho/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ where
match self.header.cputype(self.endian) {
macho::CPU_TYPE_ARM => Architecture::Arm,
macho::CPU_TYPE_ARM64 => Architecture::Aarch64,
macho::CPU_TYPE_ARM64_32 => Architecture::Aarch64_Ilp32,
macho::CPU_TYPE_X86 => Architecture::I386,
macho::CPU_TYPE_X86_64 => Architecture::X86_64,
macho::CPU_TYPE_MIPS => Architecture::Mips,
Expand Down
16 changes: 9 additions & 7 deletions src/read/macho/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ where
relative: reloc.r_pcrel,
},
},
macho::CPU_TYPE_ARM64 => match (reloc.r_type, reloc.r_pcrel) {
(macho::ARM64_RELOC_UNSIGNED, false) => RelocationKind::Absolute,
_ => RelocationKind::MachO {
value: reloc.r_type,
relative: reloc.r_pcrel,
},
},
macho::CPU_TYPE_ARM64 | macho::CPU_TYPE_ARM64_32 => {
match (reloc.r_type, reloc.r_pcrel) {
(macho::ARM64_RELOC_UNSIGNED, false) => RelocationKind::Absolute,
_ => RelocationKind::MachO {
value: reloc.r_type,
relative: reloc.r_pcrel,
},
}
}
macho::CPU_TYPE_X86 => match (reloc.r_type, reloc.r_pcrel) {
(macho::GENERIC_RELOC_VANILLA, false) => RelocationKind::Absolute,
_ => RelocationKind::MachO {
Expand Down
73 changes: 41 additions & 32 deletions src/write/macho.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,39 +675,48 @@ impl<'a> Object<'a> {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
},
Architecture::Aarch64 => match (reloc.kind, reloc.encoding, reloc.addend) {
(RelocationKind::Absolute, RelocationEncoding::Generic, 0) => {
(false, macho::ARM64_RELOC_UNSIGNED)
}
(RelocationKind::Relative, RelocationEncoding::AArch64Call, 0) => {
(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
r_symbolnum = value as u32;
(false, macho::ARM64_RELOC_ADDEND)
Architecture::Aarch64 | Architecture::Aarch64_Ilp32 => {
match (reloc.kind, reloc.encoding, reloc.addend) {
(RelocationKind::Absolute, RelocationEncoding::Generic, 0) => {
(false, macho::ARM64_RELOC_UNSIGNED)
}
(RelocationKind::Relative, RelocationEncoding::AArch64Call, 0) => {
(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
r_symbolnum = value as u32;
(false, macho::ARM64_RELOC_ADDEND)
}
(
RelocationKind::MachO { value, relative },
RelocationEncoding::Generic,
0,
) => (relative, value),
_ => {
return Err(Error(format!(
"unimplemented relocation {:?}",
reloc
)));
}
}
(
RelocationKind::MachO { value, relative },
RelocationEncoding::Generic,
0,
) => (relative, value),
_ => {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
},
}
_ => {
if let RelocationKind::MachO { value, relative } = reloc.kind {
(relative, value)
Expand Down
90 changes: 90 additions & 0 deletions tests/round_trip/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,96 @@ fn macho_x86_64() {
assert_eq!(map.get(func1_offset - 1), None);
}

#[test]
fn macho_any() {
for (arch, endian) in [
(Architecture::Aarch64, Endianness::Little),
(Architecture::Aarch64_Ilp32, Endianness::Little),
/* TODO:
(Architecture::Arm, Endianness::Little),
*/
(Architecture::I386, Endianness::Little),
(Architecture::X86_64, Endianness::Little),
/* TODO:
(Architecture::PowerPc, Endianness::Big),
(Architecture::PowerPc64, Endianness::Big),
*/
]
.iter()
.copied()
{
let mut object = write::Object::new(BinaryFormat::MachO, arch, endian);

let section = object.section_id(write::StandardSection::Data);
object.append_section_data(section, &[1; 30], 4);
let symbol = object.section_symbol(section);

object
.add_relocation(
section,
write::Relocation {
offset: 8,
size: 32,
kind: RelocationKind::Absolute,
encoding: RelocationEncoding::Generic,
symbol,
addend: 0,
},
)
.unwrap();
if arch.address_size().unwrap().bytes() >= 8 {
object
.add_relocation(
section,
write::Relocation {
offset: 16,
size: 64,
kind: RelocationKind::Absolute,
encoding: RelocationEncoding::Generic,
symbol,
addend: 0,
},
)
.unwrap();
}

let bytes = object.write().unwrap();
let object = read::File::parse(&*bytes).unwrap();
println!("{:?}", object.architecture());
assert_eq!(object.format(), BinaryFormat::MachO);
assert_eq!(object.architecture(), arch);
assert_eq!(object.endianness(), endian);

let mut sections = object.sections();

let data = sections.next().unwrap();
println!("{:?}", data);
assert_eq!(data.segment_name(), Ok(Some("__DATA")));
assert_eq!(data.name(), Ok("__data"));
assert_eq!(data.kind(), SectionKind::Data);

let mut relocations = data.relocations();

let (offset, relocation) = relocations.next().unwrap();
println!("{:?}", relocation);
assert_eq!(offset, 8);
assert_eq!(relocation.kind(), RelocationKind::Absolute);
assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
assert_eq!(relocation.size(), 32);
assert_eq!(relocation.addend(), 0);

if arch.address_size().unwrap().bytes() >= 8 {
let (offset, relocation) = relocations.next().unwrap();
println!("{:?}", relocation);
assert_eq!(offset, 16);
assert_eq!(relocation.kind(), RelocationKind::Absolute);
assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
assert_eq!(relocation.size(), 64);
assert_eq!(relocation.addend(), 0);
}
}
}

#[cfg(feature = "xcoff")]
#[test]
fn xcoff_powerpc() {
Expand Down

0 comments on commit 60a75e5

Please sign in to comment.