authorgravatar for corentin.kerisit@gmail.comCorentin Kerisit <corentin.kerisit@gmail.com> 2026-04-11 18:05:24+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-12 01:23:17+02:00
log07f05426fc0c28ad19f87002d5d4d0366e54b7c9
tree9cc7598f550f222ff1894bbd7303a2dbc00caf75
parentbc08199ef1f9419b5b8ed4165458783314934266

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.

1 files changed, 46 insertions(+), 8 deletions(-)

lib/std/debug/MachOFile.zig+46-8
......@@ -158,6 +158,10 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
158158 }
159159
160160 // TODO handle globals N_GSYM, and statics N_STSYM
161 //
162 // NOTE: ld64.lld and Apple's ld differ in STABS layout.
163 // Apple's ld emit N_BNSYM and N_ENSYM to mark the start and end of
164 // functions, while ld64.lld doesn't.
161165 switch (sym.n_type.stab) {
162166 .oso => switch (state) {
163167 .init, .oso_close => {
......@@ -178,6 +182,14 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
178182 else => return error.InvalidMachO,
179183 },
180184 .fun => switch (state) {
185 .oso_open => {
186 state = .fun_strx;
187 last_sym = .{
188 .strx = sym.n_strx,
189 .addr = sym.n_value,
190 .ofile = ofile,
191 };
192 },
181193 .bnsym => {
182194 state = .fun_strx;
183195 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)
185197 .fun_strx => {
186198 state = .fun_size;
187199 },
200 .fun_size => {
201 if (last_sym.strx != 0) {
202 appendStabSymbol(&symbols, &symbol_names, strings, last_sym);
203 }
204 last_sym = .{
205 .strx = sym.n_strx,
206 .addr = sym.n_value,
207 .ofile = ofile,
208 };
209 state = .fun_strx;
210 },
188211 else => return error.InvalidMachO,
189212 },
190213 .ensym => switch (state) {
191214 .fun_size => {
192215 state = .ensym;
193216 if (last_sym.strx != 0) {
194 const name = std.mem.sliceTo(strings[last_sym.strx..], 0);
195 const gop = symbol_names.getOrPutAssumeCapacity(name);
196 if (!gop.found_existing) {
197 assert(gop.index == symbols.items.len);
198 symbols.appendAssumeCapacity(last_sym);
199 } else {
200 symbols.items[gop.index] = last_sym;
201 }
217 appendStabSymbol(&symbols, &symbol_names, strings, last_sym);
202218 }
203219 },
204220 else => return error.InvalidMachO,
......@@ -208,6 +224,12 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
208224 .oso_open, .ensym => {
209225 state = .oso_close;
210226 },
227 .fun_size => {
228 state = .oso_close;
229 if (last_sym.strx != 0) {
230 appendStabSymbol(&symbols, &symbol_names, strings, last_sym);
231 }
232 },
211233 else => return error.InvalidMachO,
212234 },
213235 else => {},
......@@ -356,6 +378,22 @@ test {
356378 _ = Symbol;
357379}
358380
381fn appendStabSymbol(
382 symbols: *std.ArrayList(Symbol),
383 symbol_names: *std.StringArrayHashMapUnmanaged(void),
384 strings: []const u8,
385 last_sym: Symbol,
386) void {
387 const name = std.mem.sliceTo(strings[last_sym.strx..], 0);
388 const gop = symbol_names.getOrPutAssumeCapacity(name);
389 if (!gop.found_existing) {
390 assert(gop.index == symbols.items.len);
391 symbols.appendAssumeCapacity(last_sym);
392 } else {
393 symbols.items[gop.index] = last_sym;
394 }
395}
396
359397fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
360398 const all_mapped_memory, const mapped_ofile = map: {
361399 const open_paren = paren: {