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(...@@ -1468,7 +1468,6 @@ pub fn commitDeclState(
1468 .target = reloc.target,1468 .target = reloc.target,
1469 .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off,1469 .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off,
1470 .addend = 0,1470 .addend = 0,
1471 .prev_vaddr = 0,
1472 });1471 });
1473 },1472 },
1474 .elf => {}, // TODO1473 .elf => {}, // TODO
src/link/MachO.zig+9-5
...@@ -258,7 +258,7 @@ pub fn createEmpty(...@@ -258,7 +258,7 @@ pub fn createEmpty(
258258
259 switch (comp.config.debug_format) {259 switch (comp.config.debug_format) {
260 .strip => {},260 .strip => {},
261 .dwarf => {261 .dwarf => if (!self.base.isRelocatable()) {
262 // Create dSYM bundle.262 // Create dSYM bundle.
263 log.debug("creating {s}.dSYM bundle", .{emit.sub_path});263 log.debug("creating {s}.dSYM bundle", .{emit.sub_path});
264264
...@@ -283,6 +283,9 @@ pub fn createEmpty(...@@ -283,6 +283,9 @@ pub fn createEmpty(
283 .file = d_sym_file,283 .file = d_sym_file,
284 };284 };
285 try self.d_sym.?.initMetadata(self);285 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;
286 },289 },
287 .code_view => unreachable,290 .code_view => unreachable,
288 }291 }
...@@ -696,6 +699,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node...@@ -696,6 +699,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
696 const ncmds, const sizeofcmds, const uuid_cmd_offset = try self.writeLoadCommands();699 const ncmds, const sizeofcmds, const uuid_cmd_offset = try self.writeLoadCommands();
697 try self.writeHeader(ncmds, sizeofcmds);700 try self.writeHeader(ncmds, sizeofcmds);
698 try self.writeUuid(uuid_cmd_offset, self.requiresCodeSig());701 try self.writeUuid(uuid_cmd_offset, self.requiresCodeSig());
702 if (self.getDebugSymbols()) |dsym| try dsym.flushModule(self);
699703
700 if (codesig) |*csig| {704 if (codesig) |*csig| {
701 try self.writeCodeSignature(csig); // code signing always comes last705 try self.writeCodeSignature(csig); // code signing always comes last
...@@ -2902,16 +2906,16 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 {...@@ -2902,16 +2906,16 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 {
2902 try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);2906 try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);
29032907
2904 if (self.getZigObject()) |zo| {2908 if (self.getZigObject()) |zo| {
2905 zo.writeSymtab(self);2909 zo.writeSymtab(self, self);
2906 }2910 }
2907 for (self.objects.items) |index| {2911 for (self.objects.items) |index| {
2908 try self.getFile(index).?.writeSymtab(self);2912 try self.getFile(index).?.writeSymtab(self, self);
2909 }2913 }
2910 for (self.dylibs.items) |index| {2914 for (self.dylibs.items) |index| {
2911 try self.getFile(index).?.writeSymtab(self);2915 try self.getFile(index).?.writeSymtab(self, self);
2912 }2916 }
2913 if (self.getInternalObject()) |internal| {2917 if (self.getInternalObject()) |internal| {
2914 internal.writeSymtab(self);2918 internal.writeSymtab(self, self);
2915 }2919 }
29162920
2917 assert(self.strtab.items.len == cmd.strsize);2921 assert(self.strtab.items.len == cmd.strsize);
src/link/MachO/DebugSymbols.zig+113-149
...@@ -3,6 +3,7 @@ dwarf: Dwarf,...@@ -3,6 +3,7 @@ dwarf: Dwarf,
3file: fs.File,3file: fs.File,
44
5symtab_cmd: macho.symtab_command = .{},5symtab_cmd: macho.symtab_command = .{},
6uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 },
67
7segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{},8segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{},
8sections: std.ArrayListUnmanaged(macho.section_64) = .{},9sections: std.ArrayListUnmanaged(macho.section_64) = .{},
...@@ -22,9 +23,12 @@ debug_aranges_section_dirty: bool = false,...@@ -22,9 +23,12 @@ debug_aranges_section_dirty: bool = false,
22debug_info_header_dirty: bool = false,23debug_info_header_dirty: bool = false,
23debug_line_header_dirty: bool = false,24debug_line_header_dirty: bool = false,
2425
25strtab: StringTable = .{},
26relocs: std.ArrayListUnmanaged(Reloc) = .{},26relocs: std.ArrayListUnmanaged(Reloc) = .{},
2727
28/// Output synthetic sections
29symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
30strtab: std.ArrayListUnmanaged(u8) = .{},
31
28pub const Reloc = struct {32pub const Reloc = struct {
29 type: enum {33 type: enum {
30 direct_load,34 direct_load,
...@@ -33,12 +37,13 @@ pub const Reloc = struct {...@@ -33,12 +37,13 @@ pub const Reloc = struct {
33 target: u32,37 target: u32,
34 offset: u64,38 offset: u64,
35 addend: u32,39 addend: u32,
36 prev_vaddr: u64,
37};40};
3841
39/// You must call this function *after* `ZigObject.initMetadata()`42/// You must call this function *after* `ZigObject.initMetadata()`
40/// has been called to get a viable debug symbols output.43/// has been called to get a viable debug symbols output.
41pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void {44pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void {
45 try self.strtab.append(self.allocator, 0);
46
42 if (self.dwarf_segment_cmd_index == null) {47 if (self.dwarf_segment_cmd_index == null) {
43 self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len));48 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 {...@@ -202,34 +207,21 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
202 const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;207 const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
203208
204 for (self.relocs.items) |*reloc| {209 for (self.relocs.items) |*reloc| {
205 const sym = switch (reloc.type) {210 const sym = macho_file.getSymbol(reloc.target);
206 .direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target }),211 const sym_name = sym.getName(macho_file);
207 .got_load => blk: {212 const addr = switch (reloc.type) {
208 const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?;213 .direct_load => sym.getAddress(.{}, macho_file),
209 const got_entry = macho_file.got_table.entries.items[got_index];214 .got_load => sym.getGotAddress(macho_file),
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 },
222 };215 };
223 const sect = &self.sections.items[self.debug_info_section_index.?];216 const sect = &self.sections.items[self.debug_info_section_index.?];
224 const file_offset = sect.offset + reloc.offset;217 const file_offset = sect.offset + reloc.offset;
225 log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{218 log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{
226 reloc.target,219 reloc.target,
227 sym.n_value,220 addr,
228 sym_name,221 sym_name,
229 file_offset,222 file_offset,
230 });223 });
231 try self.file.pwriteAll(mem.asBytes(&sym.n_value), file_offset);224 try self.file.pwriteAll(mem.asBytes(&addr), file_offset);
232 reloc.prev_vaddr = sym.n_value;
233 }225 }
234226
235 if (self.debug_abbrev_section_dirty) {227 if (self.debug_abbrev_section_dirty) {
...@@ -240,7 +232,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {...@@ -240,7 +232,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
240 if (self.debug_info_header_dirty) {232 if (self.debug_info_header_dirty) {
241 // Currently only one compilation unit is supported, so the address range is simply233 // Currently only one compilation unit is supported, so the address range is simply
242 // identical to the main program header virtual address and memory size.234 // 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.?];
244 const low_pc = text_section.addr;236 const low_pc = text_section.addr;
245 const high_pc = text_section.addr + text_section.size;237 const high_pc = text_section.addr + text_section.size;
246 try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc);238 try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc);
...@@ -250,7 +242,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {...@@ -250,7 +242,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
250 if (self.debug_aranges_section_dirty) {242 if (self.debug_aranges_section_dirty) {
251 // Currently only one compilation unit is supported, so the address range is simply243 // Currently only one compilation unit is supported, so the address range is simply
252 // identical to the main program header virtual address and memory size.244 // 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.?];
254 try self.dwarf.writeDbgAranges(text_section.addr, text_section.size);246 try self.dwarf.writeDbgAranges(text_section.addr, text_section.size);
255 self.debug_aranges_section_dirty = false;247 self.debug_aranges_section_dirty = false;
256 }248 }
...@@ -274,17 +266,8 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {...@@ -274,17 +266,8 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
274 try self.writeLinkeditSegmentData(macho_file);266 try self.writeLinkeditSegmentData(macho_file);
275267
276 // Write load commands268 // Write load commands
277 var lc_buffer = std.ArrayList(u8).init(self.allocator);269 const ncmds, const sizeofcmds = try self.writeLoadCommands(macho_file);
278 defer lc_buffer.deinit();270 try self.writeHeader(macho_file, ncmds, sizeofcmds);
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)));
288271
289 assert(!self.debug_abbrev_section_dirty);272 assert(!self.debug_abbrev_section_dirty);
290 assert(!self.debug_aranges_section_dirty);273 assert(!self.debug_aranges_section_dirty);
...@@ -297,8 +280,9 @@ pub fn deinit(self: *DebugSymbols) void {...@@ -297,8 +280,9 @@ pub fn deinit(self: *DebugSymbols) void {
297 self.segments.deinit(gpa);280 self.segments.deinit(gpa);
298 self.sections.deinit(gpa);281 self.sections.deinit(gpa);
299 self.dwarf.deinit();282 self.dwarf.deinit();
300 self.strtab.deinit(gpa);
301 self.relocs.deinit(gpa);283 self.relocs.deinit(gpa);
284 self.symtab.deinit(gpa);
285 self.strtab.deinit(gpa);
302}286}
303287
304pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void {288pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void {
...@@ -322,7 +306,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {...@@ -322,7 +306,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
322 // however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we306 // however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we
323 // do not want as we want to be able to incrementally move DWARF sections in the307 // do not want as we want to be able to incrementally move DWARF sections in the
324 // file as we please.308 // file as we please.
325 const last_seg = macho_file.getLinkeditSegmentPtr();309 const last_seg = macho_file.getLinkeditSegment();
326 break :blk last_seg.vmaddr + last_seg.vmsize;310 break :blk last_seg.vmaddr + last_seg.vmsize;
327 };311 };
328 const dwarf_segment = self.getDwarfSegmentPtr();312 const dwarf_segment = self.getDwarfSegmentPtr();
...@@ -332,8 +316,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {...@@ -332,8 +316,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
332 file_size = @max(file_size, header.offset + header.size);316 file_size = @max(file_size, header.offset + header.size);
333 }317 }
334318
335 const target = macho_file.base.comp.root_mod.resolved_target.result;319 const page_size = macho_file.getPageSize();
336 const page_size = MachO.getPageSize(target.cpu.arch);
337 const aligned_size = mem.alignForward(u64, file_size, page_size);320 const aligned_size = mem.alignForward(u64, file_size, page_size);
338 dwarf_segment.vmaddr = base_vmaddr;321 dwarf_segment.vmaddr = base_vmaddr;
339 dwarf_segment.filesize = aligned_size;322 dwarf_segment.filesize = aligned_size;
...@@ -353,54 +336,70 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {...@@ -353,54 +336,70 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
353 log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff});336 log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff});
354}337}
355338
356fn writeSegmentHeaders(self: *DebugSymbols, macho_file: *MachO, writer: anytype) !void {339fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } {
357 // Write segment/section headers from the binary file first.340 const gpa = self.allocator;
358 const end = macho_file.linkedit_segment_cmd_index.?;341 const needed_size = load_commands.calcLoadCommandsSizeDsym(macho_file, self);
359 for (macho_file.segments.items[0..end], 0..) |seg, i| {342 const buffer = try gpa.alloc(u8, needed_size);
360 const indexes = macho_file.getSectionIndexes(@as(u8, @intCast(i)));343 defer gpa.free(buffer);
361 var out_seg = seg;344
362 out_seg.fileoff = 0;345 var stream = std.io.fixedBufferStream(buffer);
363 out_seg.filesize = 0;346 var cwriter = std.io.countingWriter(stream.writer());
364 out_seg.cmdsize = @sizeOf(macho.segment_command_64);347 const writer = cwriter.writer();
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 }
374348
375 if (out_seg.nsects == 0 and349 var ncmds: usize = 0;
376 (mem.eql(u8, out_seg.segName(), "__DATA_CONST") or
377 mem.eql(u8, out_seg.segName(), "__DATA"))) continue;
378350
379 try writer.writeStruct(out_seg);351 // UUID comes first presumably to speed up lookup by the consumer like lldb.
380 for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| {352 @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid);
381 if (header.size == 0) continue;353 try writer.writeStruct(self.uuid_cmd);
382 var out_header = header;354 ncmds += 1;
383 out_header.offset = 0;355
384 try writer.writeStruct(out_header);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;
385 }373 }
386 }374 ncmds += macho_file.segments.items.len - 1;
387 // Next, commit DSYM's __LINKEDIT and __DWARF segments headers.375
388 for (self.segments.items, 0..) |seg, i| {376 // Next, commit DSYM's __LINKEDIT and __DWARF segments headers.
389 const indexes = self.getSectionIndexes(@as(u8, @intCast(i)));377 sect_id = 0;
390 try writer.writeStruct(seg);378 for (self.segments.items) |seg| {
391 for (self.sections.items[indexes.start..indexes.end]) |header| {379 try writer.writeStruct(seg);
392 try writer.writeStruct(header);380 for (self.sections.items[sect_id..][0..seg.nsects]) |header| {
381 try writer.writeStruct(header);
382 }
383 sect_id += seg.nsects;
393 }384 }
385 ncmds += self.segments.items.len;
394 }386 }
395}
396387
397fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: u32) !void {388 try writer.writeStruct(self.symtab_cmd);
398 const target = macho_file.base.comp.root_mod.resolved_target.result;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 {
400 var header: macho.mach_header_64 = .{};399 var header: macho.mach_header_64 = .{};
401 header.filetype = macho.MH_DSYM;400 header.filetype = macho.MH_DSYM;
402401
403 switch (target.cpu.arch) {402 switch (macho_file.getTarget().cpu.arch) {
404 .aarch64 => {403 .aarch64 => {
405 header.cputype = macho.CPU_TYPE_ARM64;404 header.cputype = macho.CPU_TYPE_ARM64;
406 header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;405 header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
...@@ -412,8 +411,8 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds:...@@ -412,8 +411,8 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds:
412 else => return error.UnsupportedCpuArchitecture,411 else => return error.UnsupportedCpuArchitecture,
413 }412 }
414413
415 header.ncmds = ncmds;414 header.ncmds = @intCast(ncmds);
416 header.sizeofcmds = sizeofcmds;415 header.sizeofcmds = @intCast(sizeofcmds);
417416
418 log.debug("writing Mach-O header {}", .{header});417 log.debug("writing Mach-O header {}", .{header});
419418
...@@ -435,91 +434,56 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void {...@@ -435,91 +434,56 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void {
435 const tracy = trace(@src());434 const tracy = trace(@src());
436 defer tracy.end();435 defer tracy.end();
437436
438 try self.writeSymtab(macho_file);437 const page_size = macho_file.getPageSize();
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);
443 const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];438 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
444 const aligned_size = mem.alignForward(u64, seg.filesize, page_size);446 const aligned_size = mem.alignForward(u64, seg.filesize, page_size);
445 seg.vmsize = aligned_size;447 seg.vmsize = aligned_size;
446}448}
447449
448fn writeSymtab(self: *DebugSymbols, macho_file: *MachO) !void {450pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 {
449 const tracy = trace(@src());451 const tracy = trace(@src());
450 defer tracy.end();452 defer tracy.end();
451
452 const gpa = self.allocator;453 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);459 try self.symtab.resize(gpa, cmd.nsyms);
455 defer locals.deinit();460 try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);
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 }
466461
467 var exports = std.ArrayList(macho.nlist_64).init(gpa);462 if (macho_file.getZigObject()) |zo| {
468 defer exports.deinit();463 zo.writeSymtab(macho_file, self);
469464 }
470 for (macho_file.globals.items) |global| {465 for (macho_file.objects.items) |index| {
471 const sym = macho_file.getSymbol(global);466 try macho_file.getFile(index).?.writeSymtab(macho_file, self);
472 if (sym.undf()) continue; // import, skip467 }
473 var out_sym = sym;468 for (macho_file.dylibs.items) |index| {
474 out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(global));469 try macho_file.getFile(index).?.writeSymtab(macho_file, self);
475 try exports.append(out_sym);470 }
471 if (macho_file.getInternalObject()) |internal| {
472 internal.writeSymtab(macho_file, self);
476 }473 }
477474
478 const nlocals = locals.items.len;475 assert(self.strtab.items.len == cmd.strsize);
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);
494476
495 log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });477 try self.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
496 try self.file.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
497478
498 log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });479 return off + cmd.nsyms * @sizeOf(macho.nlist_64);
499 try self.file.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
500}480}
501481
502fn writeStrtab(self: *DebugSymbols) !void {482pub fn writeStrtab(self: *DebugSymbols, off: u32) !u32 {
503 const tracy = trace(@src());483 const cmd = &self.symtab_cmd;
504 defer tracy.end();484 cmd.stroff = off;
505485 try self.file.pwriteAll(self.strtab.items, cmd.stroff);
506 const seg = &self.segments.items[self.linkedit_segment_cmd_index.?];486 return off + cmd.strsize;
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 }
523}487}
524488
525pub fn getSectionIndexes(self: *DebugSymbols, segment_index: u8) struct { start: u8, end: u8 } {489pub fn getSectionIndexes(self: *DebugSymbols, segment_index: u8) struct { start: u8, end: u8 } {
...@@ -559,7 +523,7 @@ const assert = std.debug.assert;...@@ -559,7 +523,7 @@ const assert = std.debug.assert;
559const fs = std.fs;523const fs = std.fs;
560const link = @import("../../link.zig");524const link = @import("../../link.zig");
561const load_commands = @import("load_commands.zig");525const load_commands = @import("load_commands.zig");
562const log = std.log.scoped(.dsym);526const log = std.log.scoped(.link_dsym);
563const macho = std.macho;527const macho = std.macho;
564const makeStaticString = MachO.makeStaticString;528const makeStaticString = MachO.makeStaticString;
565const math = std.math;529const math = std.math;
src/link/MachO/Dylib.zig+5-5
...@@ -576,7 +576,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) !void {...@@ -576,7 +576,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) !void {
576 }576 }
577}577}
578578
579pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {579pub fn writeSymtab(self: Dylib, macho_file: *MachO, ctx: anytype) void {
580 const tracy = trace(@src());580 const tracy = trace(@src());
581 defer tracy.end();581 defer tracy.end();
582582
...@@ -585,10 +585,10 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {...@@ -585,10 +585,10 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void {
585 const file = global.getFile(macho_file) orelse continue;585 const file = global.getFile(macho_file) orelse continue;
586 if (file.getIndex() != self.index) continue;586 if (file.getIndex() != self.index) continue;
587 const idx = global.getOutputSymtabIndex(macho_file) orelse continue;587 const idx = global.getOutputSymtabIndex(macho_file) orelse continue;
588 const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));588 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
589 macho_file.strtab.appendSliceAssumeCapacity(global.getName(macho_file));589 ctx.strtab.appendSliceAssumeCapacity(global.getName(macho_file));
590 macho_file.strtab.appendAssumeCapacity(0);590 ctx.strtab.appendAssumeCapacity(0);
591 const out_sym = &macho_file.symtab.items[idx];591 const out_sym = &ctx.symtab.items[idx];
592 out_sym.n_strx = n_strx;592 out_sym.n_strx = n_strx;
593 global.setOutputSym(macho_file, out_sym);593 global.setOutputSym(macho_file, out_sym);
594 }594 }
src/link/MachO/InternalObject.zig+5-5
...@@ -139,15 +139,15 @@ pub fn calcSymtabSize(self: *InternalObject, macho_file: *MachO) !void {...@@ -139,15 +139,15 @@ pub fn calcSymtabSize(self: *InternalObject, macho_file: *MachO) !void {
139 }139 }
140}140}
141141
142pub fn writeSymtab(self: InternalObject, macho_file: *MachO) void {142pub fn writeSymtab(self: InternalObject, macho_file: *MachO, ctx: anytype) void {
143 for (self.symbols.items) |sym_index| {143 for (self.symbols.items) |sym_index| {
144 const sym = macho_file.getSymbol(sym_index);144 const sym = macho_file.getSymbol(sym_index);
145 if (sym.getFile(macho_file)) |file| if (file.getIndex() != self.index) continue;145 if (sym.getFile(macho_file)) |file| if (file.getIndex() != self.index) continue;
146 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;146 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
147 const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));147 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
148 macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));148 ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
149 macho_file.strtab.appendAssumeCapacity(0);149 ctx.strtab.appendAssumeCapacity(0);
150 const out_sym = &macho_file.symtab.items[idx];150 const out_sym = &ctx.symtab.items[idx];
151 out_sym.n_strx = n_strx;151 out_sym.n_strx = n_strx;
152 sym.setOutputSym(macho_file, out_sym);152 sym.setOutputSym(macho_file, out_sym);
153 }153 }
src/link/MachO/Object.zig+51-51
...@@ -1320,7 +1320,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void {...@@ -1320,7 +1320,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void {
1320 }1320 }
1321}1321}
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 {
1324 const tracy = trace(@src());1324 const tracy = trace(@src());
1325 defer tracy.end();1325 defer tracy.end();
13261326
...@@ -1329,19 +1329,19 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void {...@@ -1329,19 +1329,19 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void {
1329 const file = sym.getFile(macho_file) orelse continue;1329 const file = sym.getFile(macho_file) orelse continue;
1330 if (file.getIndex() != self.index) continue;1330 if (file.getIndex() != self.index) continue;
1331 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;1331 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
1332 const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));1332 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1333 macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));1333 ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
1334 macho_file.strtab.appendAssumeCapacity(0);1334 ctx.strtab.appendAssumeCapacity(0);
1335 const out_sym = &macho_file.symtab.items[idx];1335 const out_sym = &ctx.symtab.items[idx];
1336 out_sym.n_strx = n_strx;1336 out_sym.n_strx = n_strx;
1337 sym.setOutputSym(macho_file, out_sym);1337 sym.setOutputSym(macho_file, out_sym);
1338 }1338 }
13391339
1340 if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo())1340 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);
1342}1342}
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 {
1345 const writeFuncStab = struct {1345 const writeFuncStab = struct {
1346 inline fn writeFuncStab(1346 inline fn writeFuncStab(
1347 n_strx: u32,1347 n_strx: u32,
...@@ -1349,30 +1349,30 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1349,30 +1349,30 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1349 n_value: u64,1349 n_value: u64,
1350 size: u64,1350 size: u64,
1351 index: u32,1351 index: u32,
1352 ctx: *MachO,1352 context: anytype,
1353 ) void {1353 ) void {
1354 ctx.symtab.items[index] = .{1354 context.symtab.items[index] = .{
1355 .n_strx = 0,1355 .n_strx = 0,
1356 .n_type = macho.N_BNSYM,1356 .n_type = macho.N_BNSYM,
1357 .n_sect = n_sect,1357 .n_sect = n_sect,
1358 .n_desc = 0,1358 .n_desc = 0,
1359 .n_value = n_value,1359 .n_value = n_value,
1360 };1360 };
1361 ctx.symtab.items[index + 1] = .{1361 context.symtab.items[index + 1] = .{
1362 .n_strx = n_strx,1362 .n_strx = n_strx,
1363 .n_type = macho.N_FUN,1363 .n_type = macho.N_FUN,
1364 .n_sect = n_sect,1364 .n_sect = n_sect,
1365 .n_desc = 0,1365 .n_desc = 0,
1366 .n_value = n_value,1366 .n_value = n_value,
1367 };1367 };
1368 ctx.symtab.items[index + 2] = .{1368 context.symtab.items[index + 2] = .{
1369 .n_strx = 0,1369 .n_strx = 0,
1370 .n_type = macho.N_FUN,1370 .n_type = macho.N_FUN,
1371 .n_sect = 0,1371 .n_sect = 0,
1372 .n_desc = 0,1372 .n_desc = 0,
1373 .n_value = size,1373 .n_value = size,
1374 };1374 };
1375 ctx.symtab.items[index + 3] = .{1375 context.symtab.items[index + 3] = .{
1376 .n_strx = 0,1376 .n_strx = 0,
1377 .n_type = macho.N_ENSYM,1377 .n_type = macho.N_ENSYM,
1378 .n_sect = n_sect,1378 .n_sect = n_sect,
...@@ -1392,10 +1392,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1392,10 +1392,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
13921392
1393 // Open scope1393 // Open scope
1394 // N_SO comp_dir1394 // N_SO comp_dir
1395 var n_strx = @as(u32, @intCast(macho_file.strtab.items.len));1395 var n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1396 macho_file.strtab.appendSliceAssumeCapacity(comp_dir);1396 ctx.strtab.appendSliceAssumeCapacity(comp_dir);
1397 macho_file.strtab.appendAssumeCapacity(0);1397 ctx.strtab.appendAssumeCapacity(0);
1398 macho_file.symtab.items[index] = .{1398 ctx.symtab.items[index] = .{
1399 .n_strx = n_strx,1399 .n_strx = n_strx,
1400 .n_type = macho.N_SO,1400 .n_type = macho.N_SO,
1401 .n_sect = 0,1401 .n_sect = 0,
...@@ -1404,10 +1404,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1404,10 +1404,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1404 };1404 };
1405 index += 1;1405 index += 1;
1406 // N_SO tu_name1406 // N_SO tu_name
1407 n_strx = @as(u32, @intCast(macho_file.strtab.items.len));1407 n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1408 macho_file.strtab.appendSliceAssumeCapacity(tu_name);1408 ctx.strtab.appendSliceAssumeCapacity(tu_name);
1409 macho_file.strtab.appendAssumeCapacity(0);1409 ctx.strtab.appendAssumeCapacity(0);
1410 macho_file.symtab.items[index] = .{1410 ctx.symtab.items[index] = .{
1411 .n_strx = n_strx,1411 .n_strx = n_strx,
1412 .n_type = macho.N_SO,1412 .n_type = macho.N_SO,
1413 .n_sect = 0,1413 .n_sect = 0,
...@@ -1416,18 +1416,18 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1416,18 +1416,18 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1416 };1416 };
1417 index += 1;1417 index += 1;
1418 // N_OSO path1418 // N_OSO path
1419 n_strx = @as(u32, @intCast(macho_file.strtab.items.len));1419 n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1420 if (self.archive) |ar| {1420 if (self.archive) |ar| {
1421 macho_file.strtab.appendSliceAssumeCapacity(ar.path);1421 ctx.strtab.appendSliceAssumeCapacity(ar.path);
1422 macho_file.strtab.appendAssumeCapacity('(');1422 ctx.strtab.appendAssumeCapacity('(');
1423 macho_file.strtab.appendSliceAssumeCapacity(self.path);1423 ctx.strtab.appendSliceAssumeCapacity(self.path);
1424 macho_file.strtab.appendAssumeCapacity(')');1424 ctx.strtab.appendAssumeCapacity(')');
1425 macho_file.strtab.appendAssumeCapacity(0);1425 ctx.strtab.appendAssumeCapacity(0);
1426 } else {1426 } else {
1427 macho_file.strtab.appendSliceAssumeCapacity(self.path);1427 ctx.strtab.appendSliceAssumeCapacity(self.path);
1428 macho_file.strtab.appendAssumeCapacity(0);1428 ctx.strtab.appendAssumeCapacity(0);
1429 }1429 }
1430 macho_file.symtab.items[index] = .{1430 ctx.symtab.items[index] = .{
1431 .n_strx = n_strx,1431 .n_strx = n_strx,
1432 .n_type = macho.N_OSO,1432 .n_type = macho.N_OSO,
1433 .n_sect = 0,1433 .n_sect = 0,
...@@ -1448,17 +1448,17 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1448,17 +1448,17 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1448 const sect = macho_file.sections.items(.header)[sym.out_n_sect];1448 const sect = macho_file.sections.items(.header)[sym.out_n_sect];
1449 const sym_n_strx = n_strx: {1449 const sym_n_strx = n_strx: {
1450 const symtab_index = sym.getOutputSymtabIndex(macho_file).?;1450 const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
1451 const osym = macho_file.symtab.items[symtab_index];1451 const osym = ctx.symtab.items[symtab_index];
1452 break :n_strx osym.n_strx;1452 break :n_strx osym.n_strx;
1453 };1453 };
1454 const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;1454 const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;
1455 const sym_n_value = sym.getAddress(.{}, macho_file);1455 const sym_n_value = sym.getAddress(.{}, macho_file);
1456 const sym_size = sym.getSize(macho_file);1456 const sym_size = sym.getSize(macho_file);
1457 if (sect.isCode()) {1457 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);
1459 index += 4;1459 index += 4;
1460 } else if (sym.visibility == .global) {1460 } else if (sym.visibility == .global) {
1461 macho_file.symtab.items[index] = .{1461 ctx.symtab.items[index] = .{
1462 .n_strx = sym_n_strx,1462 .n_strx = sym_n_strx,
1463 .n_type = macho.N_GSYM,1463 .n_type = macho.N_GSYM,
1464 .n_sect = sym_n_sect,1464 .n_sect = sym_n_sect,
...@@ -1467,7 +1467,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1467,7 +1467,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1467 };1467 };
1468 index += 1;1468 index += 1;
1469 } else {1469 } else {
1470 macho_file.symtab.items[index] = .{1470 ctx.symtab.items[index] = .{
1471 .n_strx = sym_n_strx,1471 .n_strx = sym_n_strx,
1472 .n_type = macho.N_STSYM,1472 .n_type = macho.N_STSYM,
1473 .n_sect = sym_n_sect,1473 .n_sect = sym_n_sect,
...@@ -1480,7 +1480,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1480,7 +1480,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
14801480
1481 // Close scope1481 // Close scope
1482 // N_SO1482 // N_SO
1483 macho_file.symtab.items[index] = .{1483 ctx.symtab.items[index] = .{
1484 .n_strx = 0,1484 .n_strx = 0,
1485 .n_type = macho.N_SO,1485 .n_type = macho.N_SO,
1486 .n_sect = 0,1486 .n_sect = 0,
...@@ -1493,10 +1493,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1493,10 +1493,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1493 for (self.stab_files.items) |sf| {1493 for (self.stab_files.items) |sf| {
1494 // Open scope1494 // Open scope
1495 // N_SO comp_dir1495 // N_SO comp_dir
1496 var n_strx = @as(u32, @intCast(macho_file.strtab.items.len));1496 var n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1497 macho_file.strtab.appendSliceAssumeCapacity(sf.getCompDir(self));1497 ctx.strtab.appendSliceAssumeCapacity(sf.getCompDir(self));
1498 macho_file.strtab.appendAssumeCapacity(0);1498 ctx.strtab.appendAssumeCapacity(0);
1499 macho_file.symtab.items[index] = .{1499 ctx.symtab.items[index] = .{
1500 .n_strx = n_strx,1500 .n_strx = n_strx,
1501 .n_type = macho.N_SO,1501 .n_type = macho.N_SO,
1502 .n_sect = 0,1502 .n_sect = 0,
...@@ -1505,10 +1505,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1505,10 +1505,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1505 };1505 };
1506 index += 1;1506 index += 1;
1507 // N_SO tu_name1507 // N_SO tu_name
1508 n_strx = @as(u32, @intCast(macho_file.strtab.items.len));1508 n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1509 macho_file.strtab.appendSliceAssumeCapacity(sf.getTuName(self));1509 ctx.strtab.appendSliceAssumeCapacity(sf.getTuName(self));
1510 macho_file.strtab.appendAssumeCapacity(0);1510 ctx.strtab.appendAssumeCapacity(0);
1511 macho_file.symtab.items[index] = .{1511 ctx.symtab.items[index] = .{
1512 .n_strx = n_strx,1512 .n_strx = n_strx,
1513 .n_type = macho.N_SO,1513 .n_type = macho.N_SO,
1514 .n_sect = 0,1514 .n_sect = 0,
...@@ -1517,10 +1517,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1517,10 +1517,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1517 };1517 };
1518 index += 1;1518 index += 1;
1519 // N_OSO path1519 // N_OSO path
1520 n_strx = @as(u32, @intCast(macho_file.strtab.items.len));1520 n_strx = @as(u32, @intCast(ctx.strtab.items.len));
1521 macho_file.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self));1521 ctx.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self));
1522 macho_file.strtab.appendAssumeCapacity(0);1522 ctx.strtab.appendAssumeCapacity(0);
1523 macho_file.symtab.items[index] = .{1523 ctx.symtab.items[index] = .{
1524 .n_strx = n_strx,1524 .n_strx = n_strx,
1525 .n_type = macho.N_OSO,1525 .n_type = macho.N_OSO,
1526 .n_sect = 0,1526 .n_sect = 0,
...@@ -1536,7 +1536,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1536,7 +1536,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1536 if (!sym.flags.output_symtab) continue;1536 if (!sym.flags.output_symtab) continue;
1537 const sym_n_strx = n_strx: {1537 const sym_n_strx = n_strx: {
1538 const symtab_index = sym.getOutputSymtabIndex(macho_file).?;1538 const symtab_index = sym.getOutputSymtabIndex(macho_file).?;
1539 const osym = macho_file.symtab.items[symtab_index];1539 const osym = ctx.symtab.items[symtab_index];
1540 break :n_strx osym.n_strx;1540 break :n_strx osym.n_strx;
1541 };1541 };
1542 const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0;1542 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...@@ -1544,11 +1544,11 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1544 const sym_size = sym.getSize(macho_file);1544 const sym_size = sym.getSize(macho_file);
1545 switch (stab.tag) {1545 switch (stab.tag) {
1546 .func => {1546 .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);
1548 index += 4;1548 index += 4;
1549 },1549 },
1550 .global => {1550 .global => {
1551 macho_file.symtab.items[index] = .{1551 ctx.symtab.items[index] = .{
1552 .n_strx = sym_n_strx,1552 .n_strx = sym_n_strx,
1553 .n_type = macho.N_GSYM,1553 .n_type = macho.N_GSYM,
1554 .n_sect = sym_n_sect,1554 .n_sect = sym_n_sect,
...@@ -1558,7 +1558,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1558,7 +1558,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
1558 index += 1;1558 index += 1;
1559 },1559 },
1560 .static => {1560 .static => {
1561 macho_file.symtab.items[index] = .{1561 ctx.symtab.items[index] = .{
1562 .n_strx = sym_n_strx,1562 .n_strx = sym_n_strx,
1563 .n_type = macho.N_STSYM,1563 .n_type = macho.N_STSYM,
1564 .n_sect = sym_n_sect,1564 .n_sect = sym_n_sect,
...@@ -1572,7 +1572,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void...@@ -1572,7 +1572,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void
15721572
1573 // Close scope1573 // Close scope
1574 // N_SO1574 // N_SO
1575 macho_file.symtab.items[index] = .{1575 ctx.symtab.items[index] = .{
1576 .n_strx = 0,1576 .n_strx = 0,
1577 .n_type = macho.N_SO,1577 .n_type = macho.N_SO,
1578 .n_sect = 0,1578 .n_sect = 0,
src/link/MachO/ZigObject.zig+5-5
...@@ -310,7 +310,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {...@@ -310,7 +310,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {
310 }310 }
311}311}
312312
313pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {313pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void {
314 const tracy = trace(@src());314 const tracy = trace(@src());
315 defer tracy.end();315 defer tracy.end();
316316
...@@ -319,10 +319,10 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {...@@ -319,10 +319,10 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
319 const file = sym.getFile(macho_file) orelse continue;319 const file = sym.getFile(macho_file) orelse continue;
320 if (file.getIndex() != self.index) continue;320 if (file.getIndex() != self.index) continue;
321 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;321 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
322 const n_strx = @as(u32, @intCast(macho_file.strtab.items.len));322 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
323 macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));323 ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
324 macho_file.strtab.appendAssumeCapacity(0);324 ctx.strtab.appendAssumeCapacity(0);
325 const out_sym = &macho_file.symtab.items[idx];325 const out_sym = &ctx.symtab.items[idx];
326 out_sym.n_strx = n_strx;326 out_sym.n_strx = n_strx;
327 sym.setOutputSym(macho_file, out_sym);327 sym.setOutputSym(macho_file, out_sym);
328 }328 }
src/link/MachO/file.zig+2-2
...@@ -90,9 +90,9 @@ pub const File = union(enum) {...@@ -90,9 +90,9 @@ pub const File = union(enum) {
90 };90 };
91 }91 }
9292
93 pub fn writeSymtab(file: File, macho_file: *MachO) !void {93 pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) !void {
94 return switch (file) {94 return switch (file) {
95 inline else => |x| x.writeSymtab(macho_file),95 inline else => |x| x.writeSymtab(macho_file, ctx),
96 };96 };
97 }97 }
9898
src/link/MachO/load_commands.zig+22
...@@ -5,6 +5,7 @@ const macho = std.macho;...@@ -5,6 +5,7 @@ const macho = std.macho;
5const mem = std.mem;5const mem = std.mem;
66
7const Allocator = mem.Allocator;7const Allocator = mem.Allocator;
8const DebugSymbols = @import("DebugSymbols.zig");
8const Dylib = @import("Dylib.zig");9const Dylib = @import("Dylib.zig");
9const MachO = @import("../MachO.zig");10const MachO = @import("../MachO.zig");
1011
...@@ -97,6 +98,27 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) u32 {...@@ -97,6 +98,27 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) u32 {
97 return @as(u32, @intCast(sizeofcmds));98 return @as(u32, @intCast(sizeofcmds));
98}99}
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
100pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {122pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 {
101 var sizeofcmds: u64 = 0;123 var sizeofcmds: u64 = 0;
102124