mirror of
https://github.com/encounter/object.git
synced 2026-03-30 11:32:22 -07:00
read/macho: support Aarch64_Ilp32 (#545)
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+40
-31
@@ -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));
|
||||
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)
|
||||
// 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)
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user