Skip to content

Commit 5f77a4e

Browse files
committed
Mach-O Object Support
1 parent 9c1dad4 commit 5f77a4e

6 files changed

Lines changed: 32 additions & 4 deletions

File tree

objdiff-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ itertools = { version = "0.15", default-features = false, features = ["use_alloc
132132
log = { version = "0.4", default-features = false, optional = true }
133133
memmap2 = { version = "0.9", optional = true }
134134
num-traits = { version = "0.2", default-features = false, optional = true }
135-
object = { version = "0.39.1", default-features = false, features = ["read_core", "elf", "coff"] }
135+
object = { version = "0.39.1", default-features = false, features = ["read_core", "elf", "coff", "macho"] }
136136
pbjson = { version = "0.9", default-features = false, optional = true }
137137
prost = { version = "0.14", default-features = false, features = ["derive"], optional = true }
138138
regex = { version = "1.12", default-features = false, features = [], optional = true }

objdiff-core/src/arch/ppc/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ impl Arch for ArchPpc {
332332
pe::IMAGE_REL_PPC_PAIR => Some("IMAGE_REL_PPC_PAIR"),
333333
_ => None,
334334
},
335+
RelocationFlags::MachO { .. } => None,
335336
}
336337
}
337338

@@ -346,6 +347,7 @@ impl Arch for ArchPpc {
346347
pe::IMAGE_REL_PPC_ADDR32 => 4,
347348
_ => 1,
348349
},
350+
RelocationFlags::MachO { .. } => 1,
349351
}
350352
}
351353

objdiff-core/src/arch/x86.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ impl ArchX86 {
7777
elf::R_386_16 => Some(2),
7878
_ => None,
7979
},
80+
RelocationFlags::MachO { r_length, .. } => Some(1 << r_length as usize),
8081
},
8182
Architecture::X86_64 => match flags {
8283
RelocationFlags::Coff(typ) => match typ {
@@ -96,6 +97,7 @@ impl ArchX86 {
9697
elf::R_X86_64_64 => Some(8),
9798
_ => None,
9899
},
100+
RelocationFlags::MachO { .. } => None,
99101
},
100102
}
101103
}
@@ -303,6 +305,22 @@ impl Arch for ArchX86 {
303305
section.data()?[address as usize..address as usize + 4].try_into()?;
304306
self.endianness.read_i32(data) as i64
305307
}
308+
object::RelocationFlags::MachO { r_length, .. } => {
309+
let size = 1usize << r_length as usize;
310+
match size {
311+
4 => {
312+
let data = section.data()?[address as usize..address as usize + 4]
313+
.try_into()?;
314+
self.endianness.read_i32(data) as i64
315+
}
316+
8 => {
317+
let data = section.data()?[address as usize..address as usize + 8]
318+
.try_into()?;
319+
self.endianness.read_i64(data)
320+
}
321+
_ => bail!("Unsupported MachO x86 implicit relocation length: {r_length}"),
322+
}
323+
}
306324
flags => bail!("Unsupported x86 implicit relocation {flags:?}"),
307325
},
308326
Architecture::X86_64 => match relocation.flags() {
@@ -352,6 +370,7 @@ impl Arch for ArchX86 {
352370
elf::R_386_16 => Some("R_386_16"),
353371
_ => None,
354372
},
373+
RelocationFlags::MachO { .. } => None,
355374
},
356375
Architecture::X86_64 => match flags {
357376
RelocationFlags::Coff(typ) => match typ {

objdiff-core/src/bindings/diff.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ fn relocation_type(flags: obj::RelocationFlags) -> u32 {
294294
match flags {
295295
obj::RelocationFlags::Elf(r_type) => r_type,
296296
obj::RelocationFlags::Coff(typ) => typ as u32,
297+
obj::RelocationFlags::MachO { r_type, .. } => r_type as u32,
297298
}
298299
}
299300

objdiff-core/src/obj/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ pub struct Relocation {
374374
pub enum RelocationFlags {
375375
Elf(u32),
376376
Coff(u16),
377+
MachO { r_type: u8, r_pcrel: bool, r_length: u8 },
377378
}
378379

379380
#[derive(Debug, Copy, Clone)]

objdiff-core/src/obj/read.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ fn map_symbol(
133133
if symbol.is_weak() {
134134
flags |= SymbolFlag::Weak;
135135
}
136-
if file.format() == object::BinaryFormat::Elf
136+
if matches!(file.format(), object::BinaryFormat::Elf | object::BinaryFormat::MachO)
137137
&& symbol.scope() == object::SymbolScope::Linkage
138138
&& (file.architecture() != Architecture::Arm || !symbol.is_global())
139139
{
@@ -250,20 +250,22 @@ fn add_section_symbols(sections: &[Section], symbols: &mut Vec<Symbol>) {
250250

251251
// `section.size` can include extra padding, so instead prefer using the address that the
252252
// last symbol ends at when there are any symbols in the section.
253+
// Compute size as a section-relative offset (important for non-zero section.address, e.g. Mach-O).
253254
let size = symbols
254255
.iter()
255256
.filter(|s| {
256257
s.section == Some(section_idx) && s.kind == SymbolKind::Object && s.size > 0
257258
})
258259
.map(|s| s.address + s.size)
259260
.max()
260-
.unwrap_or(section.size);
261+
.unwrap_or(section.address + section.size)
262+
.saturating_sub(section.address);
261263

262264
symbols.push(Symbol {
263265
name,
264266
demangled_name: None,
265267
normalized_name: None,
266-
address: 0,
268+
address: section.address,
267269
size,
268270
kind: SymbolKind::Section,
269271
section: Some(section_idx),
@@ -577,6 +579,9 @@ fn map_section_relocations(
577579
let flags = match reloc.flags() {
578580
object::RelocationFlags::Elf { r_type } => RelocationFlags::Elf(r_type),
579581
object::RelocationFlags::Coff { typ } => RelocationFlags::Coff(typ),
582+
object::RelocationFlags::MachO { r_type, r_pcrel, r_length } => {
583+
RelocationFlags::MachO { r_type, r_pcrel, r_length }
584+
}
580585
flags => bail!("Unhandled relocation flags: {:?}", flags),
581586
};
582587
let target_symbol = match symbol_indices.get(symbol_index.0).copied() {

0 commit comments

Comments
 (0)