authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-28 13:45:13+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-29 07:26:59+01:00
logf2214e43715d1094a2d933c3fe1b6f461391915b
treefef3b2025f353c4be81eeda7d87fbcc314019525
parentd53cb284de0486fbb31f6377d3b86d8de5f93cd0

macho: re-enable dSYM but don't write anything to it yet


9 files changed, 212 insertions(+), 223 deletions(-)

src/link/Dwarf.zig-1
......@@ -1468,7 +1468,6 @@ pub fn commitDeclState(
14681468 .target = reloc.target,
14691469 .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off,
14701470 .addend = 0,
1471 .prev_vaddr = 0,
14721471 });
14731472 },
14741473 .elf => {}, // TODO
src/link/MachO.zig+9-5
......@@ -258,7 +258,7 @@ pub fn createEmpty(
258258
259259 switch (comp.config.debug_format) {
260260 .strip => {},
261 .dwarf => {
261 .dwarf => if (!self.base.isRelocatable()) {
262262 // Create dSYM bundle.
263263 log.debug("creating {s}.dSYM bundle", .{emit.sub_path});
264264
......@@ -283,6 +283,9 @@ pub fn createEmpty(
283283 .file = d_sym_file,
284284 };
285285 try self.d_sym.?.initMetadata(self);
286 } else {
287 try self.reportUnexpectedError("TODO: implement generating and emitting __DWARF in .o file", .{});
288 return error.Unexpected;
286289 },
287290 .code_view => unreachable,
288291 }
......@@ -696,6 +699,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
696699 const ncmds, const sizeofcmds, const uuid_cmd_offset = try self.writeLoadCommands();
697700 try self.writeHeader(ncmds, sizeofcmds);
698701 try self.writeUuid(uuid_cmd_offset, self.requiresCodeSig());
702 if (self.getDebugSymbols()) |dsym| try dsym.flushModule(self);
699703
700704 if (codesig) |*csig| {
701705 try self.writeCodeSignature(csig); // code signing always comes last
......@@ -2902,16 +2906,16 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 {
29022906 try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);
29032907
29042908 if (self.getZigObject()) |zo| {
2905 zo.writeSymtab(self);
2909 zo.writeSymtab(self, self);
29062910 }
29072911 for (self.objects.items) |index| {
2908 try self.getFile(index).?.writeSymtab(self);
2912 try self.getFile(index).?.writeSymtab(self, self);
29092913 }
29102914 for (self.dylibs.items) |index| {
2911 try self.getFile(index).?.writeSymtab(self);
2915 try self.getFile(index).?.writeSymtab(self, self);
29122916 }
29132917 if (self.getInternalObject()) |internal| {
2914 internal.writeSymtab(self);
2918 internal.writeSymtab(self, self);
29152919 }
29162920
29172921 assert(self.strtab.items.len == cmd.strsize);
src/link/MachO/DebugSymbols.zig+113-149
......@@ -3,6 +3,7 @@ dwarf: Dwarf,
33file: fs.File,
44
55symtab_cmd: macho.symtab_command = .{},
6uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 },
67
78segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{},
89sections: std.ArrayListUnmanaged(macho.section_64) = .{},
......@@ -22,9 +23,12 @@ debug_aranges_section_dirty: bool = false,
2223debug_info_header_dirty: bool = false,
2324debug_line_header_dirty: bool = false,
2425
25strtab: StringTable = .{},
2626relocs: std.ArrayListUnmanaged(Reloc) = .{},
2727
28/// Output synthetic sections
29symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
30strtab: std.ArrayListUnmanaged(u8) = .{},
31
2832pub const Reloc = struct {
2933 type: enum {
3034 direct_load,
......@@ -33,12 +37,13 @@ pub const Reloc = struct {
3337 target: u32,
3438 offset: u64,
3539 addend: u32,
36 prev_vaddr: u64,
3740};
3841
3942/// You must call this function *after* `ZigObject.initMetadata()`
4043/// has been called to get a viable debug symbols output.
4144pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void {
45 try self.strtab.append(self.allocator, 0);
46
4247 if (self.dwarf_segment_cmd_index == null) {
4348 self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len));
4449
......@@ -202,34 +207,21 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
202207 const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
203208
204209 for (self.relocs.items) |*reloc| {
205 const sym = switch (reloc.type) {
206 .direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target }),
207 .got_load => blk: {
208 const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?;
209 const got_entry = macho_file.got_table.entries.items[got_index];
210 break :blk macho_file.getSymbol(got_entry);
211 },
212 };
213 if (sym.n_value == reloc.prev_vaddr) continue;
214
215 const sym_name = switch (reloc.type) {
216 .direct_load => macho_file.getSymbolName(.{ .sym_index = reloc.target }),
217 .got_load => blk: {
218 const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?;
219 const got_entry = macho_file.got_table.entries.items[got_index];
220 break :blk macho_file.getSymbolName(got_entry);
221 },
210 const sym = macho_file.getSymbol(reloc.target);
211 const sym_name = sym.getName(macho_file);
212 const addr = switch (reloc.type) {
213 .direct_load => sym.getAddress(.{}, macho_file),
214 .got_load => sym.getGotAddress(macho_file),
222215 };
223216 const sect = &self.sections.items[self.debug_info_section_index.?];
224217 const file_offset = sect.offset + reloc.offset;
225218 log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{
226219 reloc.target,
227 sym.n_value,
220 addr,
228221 sym_name,
229222 file_offset,
230223 });
231 try self.file.pwriteAll(mem.asBytes(&sym.n_value), file_offset);
232 reloc.prev_vaddr = sym.n_value;
224 try self.file.pwriteAll(mem.asBytes(&addr), file_offset);
233225 }
234226
235227 if (self.debug_abbrev_section_dirty) {
......@@ -240,7 +232,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
240232 if (self.debug_info_header_dirty) {
241233 // Currently only one compilation unit is supported, so the address range is simply
242234 // identical to the main program header virtual address and memory size.
243 const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?];
235 const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?];
244236 const low_pc = text_section.addr;
245237 const high_pc = text_section.addr + text_section.size;
246238 try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc);
......@@ -250,7 +242,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
250242 if (self.debug_aranges_section_dirty) {
251243 // Currently only one compilation unit is supported, so the address range is simply
252244 // identical to the main program header virtual address and memory size.
253 const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?];
245 const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?];
254246 try self.dwarf.writeDbgAranges(text_section.addr, text_section.size);
255247 self.debug_aranges_section_dirty = false;
256248 }
......@@ -274,17 +266,8 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
274266 try self.writeLinkeditSegmentData(macho_file);
275267
276268 // Write load commands
277 var lc_buffer = std.ArrayList(u8).init(self.allocator);
278 defer lc_buffer.deinit();
279 const lc_writer = lc_buffer.writer();
280
281 try self.writeSegmentHeaders(macho_file, lc_writer);
282 try lc_writer.writeStruct(self.symtab_cmd);
283 try lc_writer.writeStruct(macho_file.uuid_cmd);
284
285 const ncmds = load_commands.calcNumOfLCs(lc_buffer.items);
286 try self.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64));
287 try self.writeHeader(macho_file, ncmds, @as(u32, @intCast(lc_buffer.items.len)));
269 const ncmds, const sizeofcmds = try self.writeLoadCommands(macho_file);
270 try self.writeHeader(macho_file, ncmds, sizeofcmds);
288271
289272 assert(!self.debug_abbrev_section_dirty);
290273 assert(!self.debug_aranges_section_dirty);
......@@ -297,8 +280,9 @@ pub fn deinit(self: *DebugSymbols) void {
297280 self.segments.deinit(gpa);
298281 self.sections.deinit(gpa);
299282 self.dwarf.deinit();
300 self.strtab.deinit(gpa);
301283 self.relocs.deinit(gpa);
284 self.symtab.deinit(gpa);
285 self.strtab.deinit(gpa);
302286}
303287
304288pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void {
......@@ -322,7 +306,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
322306 // however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we
323307 // do not want as we want to be able to incrementally move DWARF sections in the
324308 // file as we please.
325 const last_seg = macho_file.getLinkeditSegmentPtr();
309 const last_seg = macho_file.getLinkeditSegment();
326310 break :blk last_seg.vmaddr + last_seg.vmsize;
327311 };
328312 const dwarf_segment = self.getDwarfSegmentPtr();
......@@ -332,8 +316,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
332316 file_size = @max(file_size, header.offset + header.size);
333317 }
334318
335 const target = macho_file.base.comp.root_mod.resolved_target.result;
336 const page_size = MachO.getPageSize(target.cpu.arch);
319 const page_size = macho_file.getPageSize();
337320 const aligned_size = mem.alignForward(u64, file_size, page_size);
338321 dwarf_segment.vmaddr = base_vmaddr;
339322 dwarf_segment.filesize = aligned_size;
......@@ -353,54 +336,70 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
353336 log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff});
354337}
355338
356fn writeSegmentHeaders(self: *DebugSymbols, macho_file: *MachO, writer: anytype) !void {
357 // Write segment/section headers from the binary file first.
358 const end = macho_file.linkedit_segment_cmd_index.?;
359 for (macho_file.segments.items[0..end], 0..) |seg, i| {
360 const indexes = macho_file.getSectionIndexes(@as(u8, @intCast(i)));
361 var out_seg = seg;
362 out_seg.fileoff = 0;
363 out_seg.filesize = 0;
364 out_seg.cmdsize = @sizeOf(macho.segment_command_64);
365 out_seg.nsects = 0;
366
367 // Update section headers count; any section with size of 0 is excluded
368 // since it doesn't have any data in the final binary file.
369 for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| {
370 if (header.size == 0) continue;
371 out_seg.cmdsize += @sizeOf(macho.section_64);
372 out_seg.nsects += 1;
373 }
339fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } {
340 const gpa = self.allocator;
341 const needed_size = load_commands.calcLoadCommandsSizeDsym(macho_file, self);
342 const buffer = try gpa.alloc(u8, needed_size);
343 defer gpa.free(buffer);
344
345 var stream = std.io.fixedBufferStream(buffer);
346 var cwriter = std.io.countingWriter(stream.writer());
347 const writer = cwriter.writer();
374348
375 if (out_seg.nsects == 0 and
376 (mem.eql(u8, out_seg.segName(), "__DATA_CONST") or
377 mem.eql(u8, out_seg.segName(), "__DATA"))) continue;
349 var ncmds: usize = 0;
378350
379 try writer.writeStruct(out_seg);
380 for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| {
381 if (header.size == 0) continue;
382 var out_header = header;
383 out_header.offset = 0;
384 try writer.writeStruct(out_header);
351 // UUID comes first presumably to speed up lookup by the consumer like lldb.
352 @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid);
353 try writer.writeStruct(self.uuid_cmd);
354 ncmds += 1;
355
356 // Segment and section load commands
357 {
358 // Write segment/section headers from the binary file first.
359 const slice = macho_file.sections.slice();
360 var sect_id: usize = 0;
361 for (macho_file.segments.items, 0..) |seg, seg_id| {
362 if (seg_id == macho_file.linkedit_seg_index.?) break;
363 var out_seg = seg;
364 out_seg.fileoff = 0;
365 out_seg.filesize = 0;
366 try writer.writeStruct(out_seg);
367 for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| {
368 var out_header = header;
369 out_header.offset = 0;
370 try writer.writeStruct(out_header);
371 }
372 sect_id += seg.nsects;
385373 }
386 }
387 // Next, commit DSYM's __LINKEDIT and __DWARF segments headers.
388 for (self.segments.items, 0..) |seg, i| {
389 const indexes = self.getSectionIndexes(@as(u8, @intCast(i)));
390 try writer.writeStruct(seg);
391 for (self.sections.items[indexes.start..indexes.end]) |header| {
392 try writer.writeStruct(header);
374 ncmds += macho_file.segments.items.len - 1;
375
376 // Next, commit DSYM's __LINKEDIT and __DWARF segments headers.
377 sect_id = 0;
378 for (self.segments.items) |seg| {
379 try writer.writeStruct(seg);
380 for (self.sections.items[sect_id..][0..seg.nsects]) |header| {
381 try writer.writeStruct(header);
382 }
383 sect_id += seg.nsects;
393384 }
385 ncmds += self.segments.items.len;
394386 }
395}
396387
397fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: u32) !void {
398 const target = macho_file.base.comp.root_mod.resolved_target.result;
388 try writer.writeStruct(self.symtab_cmd);
389 ncmds += 1;
390
391 assert(cwriter.bytes_written == needed_size);
399392
393 try self.file.pwriteAll(buffer, @sizeOf(macho.mach_header_64));
394
395 return .{ ncmds, buffer.len };
396}
397
398fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {
400399 var header: macho.mach_header_64 = .{};
401400 header.filetype = macho.MH_DSYM;
402401
403 switch (target.cpu.arch) {
402 switch (macho_file.getTarget().cpu.arch) {
404403 .aarch64 => {
405404 header.cputype = macho.CPU_TYPE_ARM64;
406405 header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
......@@ -412,8 +411,8 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds:
412411 else => return error.UnsupportedCpuArchitecture,
413412 }
414413
415 header.ncmds = ncmds;
416 header.sizeofcmds = sizeofcmds;
414 header.ncmds = @intCast(ncmds);
415 header.sizeofcmds = @intCast(sizeofcmds);
417416
418417 log.debug("writing Mach-O header {}", .{header});
419418
......@@ -435,91 +434,56 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void {
435434 const tracy = trace(@src());
436435 defer tracy.end();
437436
438 try self.writeSymtab(macho_file);
439 try self.writeStrtab();
440
441 const target = macho_file.base.comp.root_mod.resolved_target.result;
442 const page_size = MachO.getPageSize(target.cpu.arch);
437 const page_size = macho_file.getPageSize();
443438 const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];
439
440 var off = math.cast(u32, seg.fileoff) orelse return error.Overflow;
441 off = try self.writeSymtab(off, macho_file);
442 off = mem.alignForward(u32, off, @alignOf(u64));
443 off = try self.writeStrtab(off);
444 seg.filesize = off - seg.fileoff;
445
444446 const aligned_size = mem.alignForward(u64, seg.filesize, page_size);
445447 seg.vmsize = aligned_size;
446448}
447449
448fn writeSymtab(self: *DebugSymbols, macho_file: *MachO) !void {
450pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 {
449451 const tracy = trace(@src());
450452 defer tracy.end();
451
452453 const gpa = self.allocator;
454 const cmd = &self.symtab_cmd;
455 cmd.nsyms = macho_file.symtab_cmd.nsyms;
456 cmd.strsize = macho_file.symtab_cmd.strsize;
457 cmd.symoff = off;
453458
454 var locals = std.ArrayList(macho.nlist_64).init(gpa);
455 defer locals.deinit();
456
457 for (macho_file.locals.items, 0..) |sym, sym_id| {
458 if (sym.n_strx == 0) continue; // no name, skip
459 const sym_loc = MachO.SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)) };
460 if (macho_file.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip
461 if (macho_file.getGlobal(macho_file.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
462 var out_sym = sym;
463 out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(sym_loc));
464 try locals.append(out_sym);
465 }
459 try self.symtab.resize(gpa, cmd.nsyms);
460 try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);
466461
467 var exports = std.ArrayList(macho.nlist_64).init(gpa);
468 defer exports.deinit();
469
470 for (macho_file.globals.items) |global| {
471 const sym = macho_file.getSymbol(global);
472 if (sym.undf()) continue; // import, skip
473 var out_sym = sym;
474 out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(global));
475 try exports.append(out_sym);
462 if (macho_file.getZigObject()) |zo| {
463 zo.writeSymtab(macho_file, self);
464 }
465 for (macho_file.objects.items) |index| {
466 try macho_file.getFile(index).?.writeSymtab(macho_file, self);
467 }
468 for (macho_file.dylibs.items) |index| {
469 try macho_file.getFile(index).?.writeSymtab(macho_file, self);
470 }
471 if (macho_file.getInternalObject()) |internal| {
472 internal.writeSymtab(macho_file, self);
476473 }
477474
478 const nlocals = locals.items.len;
479 const nexports = exports.items.len;
480 const nsyms = nlocals + nexports;
481
482 const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];
483 const offset = mem.alignForward(u64, seg.fileoff, @alignOf(macho.nlist_64));
484 const needed_size = nsyms * @sizeOf(macho.nlist_64);
485 seg.filesize = offset + needed_size - seg.fileoff;
486
487 self.symtab_cmd.symoff = @as(u32, @intCast(offset));
488 self.symtab_cmd.nsyms = @as(u32, @intCast(nsyms));
489
490 const locals_off = @as(u32, @intCast(offset));
491 const locals_size = nlocals * @sizeOf(macho.nlist_64);
492 const exports_off = locals_off + locals_size;
493 const exports_size = nexports * @sizeOf(macho.nlist_64);
475 assert(self.strtab.items.len == cmd.strsize);
494476
495 log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });
496 try self.file.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
477 try self.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
497478
498 log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });
499 try self.file.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
479 return off + cmd.nsyms * @sizeOf(macho.nlist_64);
500480}
501481
502fn writeStrtab(self: *DebugSymbols) !void {
503 const tracy = trace(@src());
504 defer tracy.end();
505
506 const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];
507 const symtab_size = @as(u32, @intCast(self.symtab_cmd.nsyms * @sizeOf(macho.nlist_64)));
508 const offset = mem.alignForward(u64, self.symtab_cmd.symoff + symtab_size, @alignOf(u64));
509 const needed_size = mem.alignForward(u64, self.strtab.buffer.items.len, @alignOf(u64));
510
511 seg.filesize = offset + needed_size - seg.fileoff;
512 self.symtab_cmd.stroff = @as(u32, @intCast(offset));
513 self.symtab_cmd.strsize = @as(u32, @intCast(needed_size));
514
515 log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size });
516
517 try self.file.pwriteAll(self.strtab.buffer.items, offset);
518
519 if (self.strtab.buffer.items.len < needed_size) {
520 // Ensure we are always padded to the actual length of the file.
521 try self.file.pwriteAll(&[_]u8{0}, offset + needed_size);
522 }
482pub fn writeStrtab(self: *DebugSymbols, off: u32) !u32 {
483 const cmd = &self.symtab_cmd;
484 cmd.stroff = off;
485 try self.file.pwriteAll(self.strtab.items, cmd.stroff);
486 return off + cmd.strsize;
523487}
524488
525489pub fn getSectionIndexes(self: *DebugSymbols, segment_index: u8) struct { start: u8, end: u8 } {
......@@ -559,7 +523,7 @@ const assert = std.debug.assert;
559523const fs = std.fs;
560524const link = @import("../../link.zig");
561525const load_commands = @import("load_commands.zig");
562const log = std.log.scoped(.dsym);
526const log = std.log.scoped(.link_dsym);
563527const macho = std.macho;
564528const makeStaticString = MachO.makeStaticString;
565529const math = std.math;
src/link/MachO/Dylib.zig+5-5
......@@ -576,7 +576,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) !void {
576576 }
577577}
578578
579pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {
579pub fn writeSymtab(self: Dylib, macho_file: *MachO, ctx: anytype) void {
580580 const tracy = trace(@src());
581581 defer tracy.end();
582582
......@@ -585,10 +585,10 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {
585585 const file = global.getFile(macho_file) orelse continue;
586586 if (file.getIndex() != self.index) continue;
587587 const idx = global.getOutputSymtabIndex(macho_file) orelse continue;
588 const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
589 macho_file.strtab.appendSliceAssumeCapacity(global.getName(macho_file));
590 macho_file.strtab.appendAssumeCapacity(0);
591 const out_sym = &macho_file.symtab.items[idx];
588 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
589 ctx.strtab.appendSliceAssumeCapacity(global.getName(macho_file));
590 ctx.strtab.appendAssumeCapacity(0);
591 const out_sym = &ctx.symtab.items[idx];
592592 out_sym.n_strx = n_strx;
593593 global.setOutputSym(macho_file, out_sym);
594594 }
src/link/MachO/InternalObject.zig+5-5
......@@ -139,15 +139,15 @@ pub fn calcSymtabSize(self: *InternalObject, macho_file: *MachO) !void {
139139 }
140140}
141141
142pub fn writeSymtab(self: InternalObject, macho_file: *MachO) void {
142pub fn writeSymtab(self: InternalObject, macho_file: *MachO, ctx: anytype) void {
143143 for (self.symbols.items) |sym_index| {
144144 const sym = macho_file.getSymbol(sym_index);
145145 if (sym.getFile(macho_file)) |file| if (file.getIndex() != self.index) continue;
146146 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
147 const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
148 macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
149 macho_file.strtab.appendAssumeCapacity(0);
150 const out_sym = &macho_file.symtab.items[idx];
147 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
148 ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
149 ctx.strtab.appendAssumeCapacity(0);
150 const out_sym = &ctx.symtab.items[idx];
151151 out_sym.n_strx = n_strx;
152152 sym.setOutputSym(macho_file, out_sym);
153153 }
src/link/MachO/Object.zig+51-51
......@@ -1320,7 +1320,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void {
13201320 }
13211321}
13221322
1323pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void {
1323pub fn writeSymtab(self: Object, macho_file: *MachO, ctx: anytype) error{Overflow}!void {
13241324 const tracy = trace(@src());
13251325 defer tracy.end();
13261326
......@@ -1329,19 +1329,19 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void {
13291329 const file = sym.getFile(macho_file) orelse continue;
13301330 if (file.getIndex() != self.index) continue;
13311331 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
1332 const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
1333 macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
1334 macho_file.strtab.appendAssumeCapacity(0);
1335 const out_sym = &macho_file.symtab.items[idx];
1332 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1333 ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
1334 ctx.strtab.appendAssumeCapacity(0);
1335 const out_sym = &ctx.symtab.items[idx];
13361336 out_sym.n_strx = n_strx;
13371337 sym.setOutputSym(macho_file, out_sym);
13381338 }
13391339
13401340 if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo())
1341 try self.writeStabs(macho_file);
1341 try self.writeStabs(macho_file, ctx);
13421342}
13431343
1344pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void {
1344pub fn writeStabs(self: *const Object, macho_file: *MachO, ctx: anytype) error{Overflow}!void {
13451345 const writeFuncStab = struct {
13461346 inline fn writeFuncStab(
13471347 n_strx: u32,
......@@ -1349,30 +1349,30 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
13491349 n_value: u64,
13501350 size: u64,
13511351 index: u32,
1352 ctx: *MachO,
1352 context: anytype,
13531353 ) void {
1354 ctx.symtab.items[index] = .{
1354 context.symtab.items[index] = .{
13551355 .n_strx = 0,
13561356 .n_type = macho.N_BNSYM,
13571357 .n_sect = n_sect,
13581358 .n_desc = 0,
13591359 .n_value = n_value,
13601360 };
1361 ctx.symtab.items[index + 1] = .{
1361 context.symtab.items[index + 1] = .{
13621362 .n_strx = n_strx,
13631363 .n_type = macho.N_FUN,
13641364 .n_sect = n_sect,
13651365 .n_desc = 0,
13661366 .n_value = n_value,
13671367 };
1368 ctx.symtab.items[index + 2] = .{
1368 context.symtab.items[index + 2] = .{
13691369 .n_strx = 0,
13701370 .n_type = macho.N_FUN,
13711371 .n_sect = 0,
13721372 .n_desc = 0,
13731373 .n_value = size,
13741374 };
1375 ctx.symtab.items[index + 3] = .{
1375 context.symtab.items[index + 3] = .{
13761376 .n_strx = 0,
13771377 .n_type = macho.N_ENSYM,
13781378 .n_sect = n_sect,
......@@ -1392,10 +1392,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
13921392
13931393 // Open scope
13941394 // N_SO comp_dir
1395 var n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
1396 macho_file.strtab.appendSliceAssumeCapacity(comp_dir);
1397 macho_file.strtab.appendAssumeCapacity(0);
1398 macho_file.symtab.items[index] = .{
1395 var n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1396 ctx.strtab.appendSliceAssumeCapacity(comp_dir);
1397 ctx.strtab.appendAssumeCapacity(0);
1398 ctx.symtab.items[index] = .{
13991399 .n_strx = n_strx,
14001400 .n_type = macho.N_SO,
14011401 .n_sect = 0,
......@@ -1404,10 +1404,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
14041404 };
14051405 index += 1;
14061406 // N_SO tu_name
1407 n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
1408 macho_file.strtab.appendSliceAssumeCapacity(tu_name);
1409 macho_file.strtab.appendAssumeCapacity(0);
1410 macho_file.symtab.items[index] = .{
1407 n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1408 ctx.strtab.appendSliceAssumeCapacity(tu_name);
1409 ctx.strtab.appendAssumeCapacity(0);
1410 ctx.symtab.items[index] = .{
14111411 .n_strx = n_strx,
14121412 .n_type = macho.N_SO,
14131413 .n_sect = 0,
......@@ -1416,18 +1416,18 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
14161416 };
14171417 index += 1;
14181418 // N_OSO path
1419 n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
1419 n_strx = @as(u32, @intCast(ctx.strtab.items.len));
14201420 if (self.archive) |ar| {
1421 macho_file.strtab.appendSliceAssumeCapacity(ar.path);
1422 macho_file.strtab.appendAssumeCapacity('(');
1423 macho_file.strtab.appendSliceAssumeCapacity(self.path);
1424 macho_file.strtab.appendAssumeCapacity(')');
1425 macho_file.strtab.appendAssumeCapacity(0);
1421 ctx.strtab.appendSliceAssumeCapacity(ar.path);
1422 ctx.strtab.appendAssumeCapacity('(');
1423 ctx.strtab.appendSliceAssumeCapacity(self.path);
1424 ctx.strtab.appendAssumeCapacity(')');
1425 ctx.strtab.appendAssumeCapacity(0);
14261426 } else {
1427 macho_file.strtab.appendSliceAssumeCapacity(self.path);
1428 macho_file.strtab.appendAssumeCapacity(0);
1427 ctx.strtab.appendSliceAssumeCapacity(self.path);
1428 ctx.strtab.appendAssumeCapacity(0);
14291429 }
1430 macho_file.symtab.items[index] = .{
1430 ctx.symtab.items[index] = .{
14311431 .n_strx = n_strx,
14321432 .n_type = macho.N_OSO,
14331433 .n_sect = 0,
......@@ -1448,17 +1448,17 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
14481448 const sect = macho_file.sections.items(.header)[sym.out_n_sect];
14491449 const sym_n_strx = n_strx: {
14501450 const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
1451 const osym = macho_file.symtab.items[symtab_index];
1451 const osym = ctx.symtab.items[symtab_index];
14521452 break :n_strx osym.n_strx;
14531453 };
14541454 const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;
14551455 const sym_n_value = sym.getAddress(.{}, macho_file);
14561456 const sym_size = sym.getSize(macho_file);
14571457 if (sect.isCode()) {
1458 writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file);
1458 writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx);
14591459 index += 4;
14601460 } else if (sym.visibility == .global) {
1461 macho_file.symtab.items[index] = .{
1461 ctx.symtab.items[index] = .{
14621462 .n_strx = sym_n_strx,
14631463 .n_type = macho.N_GSYM,
14641464 .n_sect = sym_n_sect,
......@@ -1467,7 +1467,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
14671467 };
14681468 index += 1;
14691469 } else {
1470 macho_file.symtab.items[index] = .{
1470 ctx.symtab.items[index] = .{
14711471 .n_strx = sym_n_strx,
14721472 .n_type = macho.N_STSYM,
14731473 .n_sect = sym_n_sect,
......@@ -1480,7 +1480,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
14801480
14811481 // Close scope
14821482 // N_SO
1483 macho_file.symtab.items[index] = .{
1483 ctx.symtab.items[index] = .{
14841484 .n_strx = 0,
14851485 .n_type = macho.N_SO,
14861486 .n_sect = 0,
......@@ -1493,10 +1493,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
14931493 for (self.stab_files.items) |sf| {
14941494 // Open scope
14951495 // N_SO comp_dir
1496 var n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
1497 macho_file.strtab.appendSliceAssumeCapacity(sf.getCompDir(self));
1498 macho_file.strtab.appendAssumeCapacity(0);
1499 macho_file.symtab.items[index] = .{
1496 var n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1497 ctx.strtab.appendSliceAssumeCapacity(sf.getCompDir(self));
1498 ctx.strtab.appendAssumeCapacity(0);
1499 ctx.symtab.items[index] = .{
15001500 .n_strx = n_strx,
15011501 .n_type = macho.N_SO,
15021502 .n_sect = 0,
......@@ -1505,10 +1505,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
15051505 };
15061506 index += 1;
15071507 // N_SO tu_name
1508 n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
1509 macho_file.strtab.appendSliceAssumeCapacity(sf.getTuName(self));
1510 macho_file.strtab.appendAssumeCapacity(0);
1511 macho_file.symtab.items[index] = .{
1508 n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1509 ctx.strtab.appendSliceAssumeCapacity(sf.getTuName(self));
1510 ctx.strtab.appendAssumeCapacity(0);
1511 ctx.symtab.items[index] = .{
15121512 .n_strx = n_strx,
15131513 .n_type = macho.N_SO,
15141514 .n_sect = 0,
......@@ -1517,10 +1517,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
15171517 };
15181518 index += 1;
15191519 // N_OSO path
1520 n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
1521 macho_file.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self));
1522 macho_file.strtab.appendAssumeCapacity(0);
1523 macho_file.symtab.items[index] = .{
1520 n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1521 ctx.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self));
1522 ctx.strtab.appendAssumeCapacity(0);
1523 ctx.symtab.items[index] = .{
15241524 .n_strx = n_strx,
15251525 .n_type = macho.N_OSO,
15261526 .n_sect = 0,
......@@ -1536,7 +1536,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
15361536 if (!sym.flags.output_symtab) continue;
15371537 const sym_n_strx = n_strx: {
15381538 const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
1539 const osym = macho_file.symtab.items[symtab_index];
1539 const osym = ctx.symtab.items[symtab_index];
15401540 break :n_strx osym.n_strx;
15411541 };
15421542 const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;
......@@ -1544,11 +1544,11 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
15441544 const sym_size = sym.getSize(macho_file);
15451545 switch (stab.tag) {
15461546 .func => {
1547 writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file);
1547 writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx);
15481548 index += 4;
15491549 },
15501550 .global => {
1551 macho_file.symtab.items[index] = .{
1551 ctx.symtab.items[index] = .{
15521552 .n_strx = sym_n_strx,
15531553 .n_type = macho.N_GSYM,
15541554 .n_sect = sym_n_sect,
......@@ -1558,7 +1558,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
15581558 index += 1;
15591559 },
15601560 .static => {
1561 macho_file.symtab.items[index] = .{
1561 ctx.symtab.items[index] = .{
15621562 .n_strx = sym_n_strx,
15631563 .n_type = macho.N_STSYM,
15641564 .n_sect = sym_n_sect,
......@@ -1572,7 +1572,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
15721572
15731573 // Close scope
15741574 // N_SO
1575 macho_file.symtab.items[index] = .{
1575 ctx.symtab.items[index] = .{
15761576 .n_strx = 0,
15771577 .n_type = macho.N_SO,
15781578 .n_sect = 0,
src/link/MachO/ZigObject.zig+5-5
......@@ -310,7 +310,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {
310310 }
311311}
312312
313pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
313pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void {
314314 const tracy = trace(@src());
315315 defer tracy.end();
316316
......@@ -319,10 +319,10 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
319319 const file = sym.getFile(macho_file) orelse continue;
320320 if (file.getIndex() != self.index) continue;
321321 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
322 const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));
323 macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
324 macho_file.strtab.appendAssumeCapacity(0);
325 const out_sym = &macho_file.symtab.items[idx];
322 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
323 ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
324 ctx.strtab.appendAssumeCapacity(0);
325 const out_sym = &ctx.symtab.items[idx];
326326 out_sym.n_strx = n_strx;
327327 sym.setOutputSym(macho_file, out_sym);
328328 }
src/link/MachO/file.zig+2-2
......@@ -90,9 +90,9 @@ pub const File = union(enum) {
9090 };
9191 }
9292
93 pub fn writeSymtab(file: File, macho_file: *MachO) !void {
93 pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) !void {
9494 return switch (file) {
95 inline else => |x| x.writeSymtab(macho_file),
95 inline else => |x| x.writeSymtab(macho_file, ctx),
9696 };
9797 }
9898
src/link/MachO/load_commands.zig+22
......@@ -5,6 +5,7 @@ const macho = std.macho;
55const mem = std.mem;
66
77const Allocator = mem.Allocator;
8const DebugSymbols = @import("DebugSymbols.zig");
89const Dylib = @import("Dylib.zig");
910const MachO = @import("../MachO.zig");
1011
......@@ -97,6 +98,27 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) u32 {
9798 return @as(u32, @intCast(sizeofcmds));
9899}
99100
101pub fn calcLoadCommandsSizeDsym(macho_file: *MachO, dsym: *const DebugSymbols) u32 {
102 var sizeofcmds: u64 = 0;
103
104 // LC_SEGMENT_64
105 sizeofcmds += @sizeOf(macho.segment_command_64) * (macho_file.segments.items.len - 1);
106 for (macho_file.segments.items) |seg| {
107 sizeofcmds += seg.nsects * @sizeOf(macho.section_64);
108 }
109 sizeofcmds += @sizeOf(macho.segment_command_64) * dsym.segments.items.len;
110 for (dsym.segments.items) |seg| {
111 sizeofcmds += seg.nsects * @sizeOf(macho.section_64);
112 }
113
114 // LC_SYMTAB
115 sizeofcmds += @sizeOf(macho.symtab_command);
116 // LC_UUID
117 sizeofcmds += @sizeOf(macho.uuid_command);
118
119 return @as(u32, @intCast(sizeofcmds));
120}
121
100122pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {
101123 var sizeofcmds: u64 = 0;
102124