Skip to content

Commit f3f89e7

Browse files
committed
Mach-O Object Support
1 parent 2cd1e2e commit f3f89e7

6 files changed

Lines changed: 33 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.14", 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.8", 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: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ fn map_symbol(
133133
if symbol.is_weak() {
134134
flags |= SymbolFlag::Weak;
135135
}
136-
if file.format() == object::BinaryFormat::Elf && symbol.scope() == object::SymbolScope::Linkage
136+
if matches!(file.format(), object::BinaryFormat::Elf | object::BinaryFormat::MachO)
137+
&& symbol.scope() == object::SymbolScope::Linkage
137138
{
138139
flags |= SymbolFlag::Hidden;
139140
}
@@ -252,20 +253,22 @@ fn add_section_symbols(sections: &[Section], symbols: &mut Vec<Symbol>) {
252253

253254
// `section.size` can include extra padding, so instead prefer using the address that the
254255
// last symbol ends at when there are any symbols in the section.
256+
// Compute size as a section-relative offset (important for non-zero section.address, e.g. Mach-O).
255257
let size = symbols
256258
.iter()
257259
.filter(|s| {
258260
s.section == Some(section_idx) && s.kind == SymbolKind::Object && s.size > 0
259261
})
260262
.map(|s| s.address + s.size)
261263
.max()
262-
.unwrap_or(section.size);
264+
.unwrap_or(section.address + section.size)
265+
.saturating_sub(section.address);
263266

264267
symbols.push(Symbol {
265268
name,
266269
demangled_name: None,
267270
normalized_name: None,
268-
address: 0,
271+
address: section.address,
269272
size,
270273
kind: SymbolKind::Section,
271274
section: Some(section_idx),
@@ -579,6 +582,9 @@ fn map_section_relocations(
579582
let flags = match reloc.flags() {
580583
object::RelocationFlags::Elf { r_type } => RelocationFlags::Elf(r_type),
581584
object::RelocationFlags::Coff { typ } => RelocationFlags::Coff(typ),
585+
object::RelocationFlags::MachO { r_type, r_pcrel, r_length } => {
586+
RelocationFlags::MachO { r_type, r_pcrel, r_length }
587+
}
582588
flags => bail!("Unhandled relocation flags: {:?}", flags),
583589
};
584590
let target_symbol = match symbol_indices.get(symbol_index.0).copied() {

0 commit comments

Comments
 (0)