commit 07f05426fc0c28ad19f87002d5d4d0366e54b7c9 (tree)
parent bc08199ef1f9419b5b8ed4165458783314934266
Author: Corentin Kerisit <corentin.kerisit@gmail.com>
Date: Sat, 11 Apr 2026 18:05:24 +0200
Support ld64.ldd STABS layout in MachOFile.load
Apple's ld emit N_BNSYM and N_ENSYM to mark the start and end of
functions, while ld64.lld doesn't.
This resulted in MachOFile.load bailing out on unsupported STABS
layout when the linker used is ld64.lld.
This commit supports both layouts.
Diffstat:
1 file changed, 46 insertions(+), 8 deletions(-)
diff --git a/lib/std/debug/MachOFile.zig b/lib/std/debug/MachOFile.zig
@@ -158,6 +158,10 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
}
// TODO handle globals N_GSYM, and statics N_STSYM
+ //
+ // NOTE: ld64.lld and Apple's ld differ in STABS layout.
+ // Apple's ld emit N_BNSYM and N_ENSYM to mark the start and end of
+ // functions, while ld64.lld doesn't.
switch (sym.n_type.stab) {
.oso => switch (state) {
.init, .oso_close => {
@@ -178,6 +182,14 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
else => return error.InvalidMachO,
},
.fun => switch (state) {
+ .oso_open => {
+ state = .fun_strx;
+ last_sym = .{
+ .strx = sym.n_strx,
+ .addr = sym.n_value,
+ .ofile = ofile,
+ };
+ },
.bnsym => {
state = .fun_strx;
last_sym.strx = sym.n_strx;
@@ -185,20 +197,24 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
.fun_strx => {
state = .fun_size;
},
+ .fun_size => {
+ if (last_sym.strx != 0) {
+ appendStabSymbol(&symbols, &symbol_names, strings, last_sym);
+ }
+ last_sym = .{
+ .strx = sym.n_strx,
+ .addr = sym.n_value,
+ .ofile = ofile,
+ };
+ state = .fun_strx;
+ },
else => return error.InvalidMachO,
},
.ensym => switch (state) {
.fun_size => {
state = .ensym;
if (last_sym.strx != 0) {
- const name = std.mem.sliceTo(strings[last_sym.strx..], 0);
- const gop = symbol_names.getOrPutAssumeCapacity(name);
- if (!gop.found_existing) {
- assert(gop.index == symbols.items.len);
- symbols.appendAssumeCapacity(last_sym);
- } else {
- symbols.items[gop.index] = last_sym;
- }
+ appendStabSymbol(&symbols, &symbol_names, strings, last_sym);
}
},
else => return error.InvalidMachO,
@@ -208,6 +224,12 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
.oso_open, .ensym => {
state = .oso_close;
},
+ .fun_size => {
+ state = .oso_close;
+ if (last_sym.strx != 0) {
+ appendStabSymbol(&symbols, &symbol_names, strings, last_sym);
+ }
+ },
else => return error.InvalidMachO,
},
else => {},
@@ -356,6 +378,22 @@ test {
_ = Symbol;
}
+fn appendStabSymbol(
+ symbols: *std.ArrayList(Symbol),
+ symbol_names: *std.StringArrayHashMapUnmanaged(void),
+ strings: []const u8,
+ last_sym: Symbol,
+) void {
+ const name = std.mem.sliceTo(strings[last_sym.strx..], 0);
+ const gop = symbol_names.getOrPutAssumeCapacity(name);
+ if (!gop.found_existing) {
+ assert(gop.index == symbols.items.len);
+ symbols.appendAssumeCapacity(last_sym);
+ } else {
+ symbols.items[gop.index] = last_sym;
+ }
+}
+
fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
const all_mapped_memory, const mapped_ofile = map: {
const open_paren = paren: {