diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-28 13:45:13 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-29 07:26:59 +0100 |
| commit | f2214e43715d1094a2d933c3fe1b6f461391915b (patch) | |
| tree | fef3b2025f353c4be81eeda7d87fbcc314019525 | |
| parent | d53cb284de0486fbb31f6377d3b86d8de5f93cd0 (diff) | |
| download | zig-f2214e43715d1094a2d933c3fe1b6f461391915b.tar.gz zig-f2214e43715d1094a2d933c3fe1b6f461391915b.zip | |
macho: re-enable dSYM but don't write anything to it yet
| -rw-r--r-- | src/link/Dwarf.zig | 1 | ||||
| -rw-r--r-- | src/link/MachO.zig | 14 | ||||
| -rw-r--r-- | src/link/MachO/DebugSymbols.zig | 262 | ||||
| -rw-r--r-- | src/link/MachO/Dylib.zig | 10 | ||||
| -rw-r--r-- | src/link/MachO/InternalObject.zig | 10 | ||||
| -rw-r--r-- | src/link/MachO/Object.zig | 102 | ||||
| -rw-r--r-- | src/link/MachO/ZigObject.zig | 10 | ||||
| -rw-r--r-- | src/link/MachO/file.zig | 4 | ||||
| -rw-r--r-- | src/link/MachO/load_commands.zig | 22 |
9 files changed, 212 insertions, 223 deletions
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 8e730a6eb1..17afe328fe 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1468,7 +1468,6 @@ pub fn commitDeclState( .target = reloc.target, .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off, .addend = 0, - .prev_vaddr = 0, }); }, .elf => {}, // TODO diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 581b6f0570..7edf0d1ec2 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -258,7 +258,7 @@ pub fn createEmpty( switch (comp.config.debug_format) { .strip => {}, - .dwarf => { + .dwarf => if (!self.base.isRelocatable()) { // Create dSYM bundle. log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); @@ -283,6 +283,9 @@ pub fn createEmpty( .file = d_sym_file, }; try self.d_sym.?.initMetadata(self); + } else { + try self.reportUnexpectedError("TODO: implement generating and emitting __DWARF in .o file", .{}); + return error.Unexpected; }, .code_view => unreachable, } @@ -696,6 +699,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node const ncmds, const sizeofcmds, const uuid_cmd_offset = try self.writeLoadCommands(); try self.writeHeader(ncmds, sizeofcmds); try self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()); + if (self.getDebugSymbols()) |dsym| try dsym.flushModule(self); if (codesig) |*csig| { try self.writeCodeSignature(csig); // code signing always comes last @@ -2902,16 +2906,16 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 { try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1); if (self.getZigObject()) |zo| { - zo.writeSymtab(self); + zo.writeSymtab(self, self); } for (self.objects.items) |index| { - try self.getFile(index).?.writeSymtab(self); + try self.getFile(index).?.writeSymtab(self, self); } for (self.dylibs.items) |index| { - try self.getFile(index).?.writeSymtab(self); + try self.getFile(index).?.writeSymtab(self, self); } if (self.getInternalObject()) |internal| { - internal.writeSymtab(self); + internal.writeSymtab(self, self); } assert(self.strtab.items.len == cmd.strsize); diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index a28688a61d..6b3861bc64 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -3,6 +3,7 @@ dwarf: Dwarf, file: fs.File, symtab_cmd: macho.symtab_command = .{}, +uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 }, segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, sections: std.ArrayListUnmanaged(macho.section_64) = .{}, @@ -22,9 +23,12 @@ debug_aranges_section_dirty: bool = false, debug_info_header_dirty: bool = false, debug_line_header_dirty: bool = false, -strtab: StringTable = .{}, relocs: std.ArrayListUnmanaged(Reloc) = .{}, +/// Output synthetic sections +symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, +strtab: std.ArrayListUnmanaged(u8) = .{}, + pub const Reloc = struct { type: enum { direct_load, @@ -33,12 +37,13 @@ pub const Reloc = struct { target: u32, offset: u64, addend: u32, - prev_vaddr: u64, }; /// You must call this function *after* `ZigObject.initMetadata()` /// has been called to get a viable debug symbols output. pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void { + try self.strtab.append(self.allocator, 0); + if (self.dwarf_segment_cmd_index == null) { self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); @@ -202,34 +207,21 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; for (self.relocs.items) |*reloc| { - const sym = switch (reloc.type) { - .direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target }), - .got_load => blk: { - const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?; - const got_entry = macho_file.got_table.entries.items[got_index]; - break :blk macho_file.getSymbol(got_entry); - }, - }; - if (sym.n_value == reloc.prev_vaddr) continue; - - const sym_name = switch (reloc.type) { - .direct_load => macho_file.getSymbolName(.{ .sym_index = reloc.target }), - .got_load => blk: { - const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?; - const got_entry = macho_file.got_table.entries.items[got_index]; - break :blk macho_file.getSymbolName(got_entry); - }, + const sym = macho_file.getSymbol(reloc.target); + const sym_name = sym.getName(macho_file); + const addr = switch (reloc.type) { + .direct_load => sym.getAddress(.{}, macho_file), + .got_load => sym.getGotAddress(macho_file), }; const sect = &self.sections.items[self.debug_info_section_index.?]; const file_offset = sect.offset + reloc.offset; log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{ reloc.target, - sym.n_value, + addr, sym_name, file_offset, }); - try self.file.pwriteAll(mem.asBytes(&sym.n_value), file_offset); - reloc.prev_vaddr = sym.n_value; + try self.file.pwriteAll(mem.asBytes(&addr), file_offset); } if (self.debug_abbrev_section_dirty) { @@ -240,7 +232,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { if (self.debug_info_header_dirty) { // Currently only one compilation unit is supported, so the address range is simply // identical to the main program header virtual address and memory size. - const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; + const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; const low_pc = text_section.addr; const high_pc = text_section.addr + text_section.size; try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc); @@ -250,7 +242,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { if (self.debug_aranges_section_dirty) { // Currently only one compilation unit is supported, so the address range is simply // identical to the main program header virtual address and memory size. - const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; + const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; try self.dwarf.writeDbgAranges(text_section.addr, text_section.size); self.debug_aranges_section_dirty = false; } @@ -274,17 +266,8 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { try self.writeLinkeditSegmentData(macho_file); // Write load commands - var lc_buffer = std.ArrayList(u8).init(self.allocator); - defer lc_buffer.deinit(); - const lc_writer = lc_buffer.writer(); - - try self.writeSegmentHeaders(macho_file, lc_writer); - try lc_writer.writeStruct(self.symtab_cmd); - try lc_writer.writeStruct(macho_file.uuid_cmd); - - const ncmds = load_commands.calcNumOfLCs(lc_buffer.items); - try self.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64)); - try self.writeHeader(macho_file, ncmds, @as(u32, @intCast(lc_buffer.items.len))); + const ncmds, const sizeofcmds = try self.writeLoadCommands(macho_file); + try self.writeHeader(macho_file, ncmds, sizeofcmds); assert(!self.debug_abbrev_section_dirty); assert(!self.debug_aranges_section_dirty); @@ -297,8 +280,9 @@ pub fn deinit(self: *DebugSymbols) void { self.segments.deinit(gpa); self.sections.deinit(gpa); self.dwarf.deinit(); - self.strtab.deinit(gpa); self.relocs.deinit(gpa); + self.symtab.deinit(gpa); + self.strtab.deinit(gpa); } pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { @@ -322,7 +306,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { // however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we // do not want as we want to be able to incrementally move DWARF sections in the // file as we please. - const last_seg = macho_file.getLinkeditSegmentPtr(); + const last_seg = macho_file.getLinkeditSegment(); break :blk last_seg.vmaddr + last_seg.vmsize; }; const dwarf_segment = self.getDwarfSegmentPtr(); @@ -332,8 +316,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { file_size = @max(file_size, header.offset + header.size); } - const target = macho_file.base.comp.root_mod.resolved_target.result; - const page_size = MachO.getPageSize(target.cpu.arch); + const page_size = macho_file.getPageSize(); const aligned_size = mem.alignForward(u64, file_size, page_size); dwarf_segment.vmaddr = base_vmaddr; dwarf_segment.filesize = aligned_size; @@ -353,54 +336,70 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff}); } -fn writeSegmentHeaders(self: *DebugSymbols, macho_file: *MachO, writer: anytype) !void { - // Write segment/section headers from the binary file first. - const end = macho_file.linkedit_segment_cmd_index.?; - for (macho_file.segments.items[0..end], 0..) |seg, i| { - const indexes = macho_file.getSectionIndexes(@as(u8, @intCast(i))); - var out_seg = seg; - out_seg.fileoff = 0; - out_seg.filesize = 0; - out_seg.cmdsize = @sizeOf(macho.segment_command_64); - out_seg.nsects = 0; - - // Update section headers count; any section with size of 0 is excluded - // since it doesn't have any data in the final binary file. - for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| { - if (header.size == 0) continue; - out_seg.cmdsize += @sizeOf(macho.section_64); - out_seg.nsects += 1; - } +fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } { + const gpa = self.allocator; + const needed_size = load_commands.calcLoadCommandsSizeDsym(macho_file, self); + const buffer = try gpa.alloc(u8, needed_size); + defer gpa.free(buffer); + + var stream = std.io.fixedBufferStream(buffer); + var cwriter = std.io.countingWriter(stream.writer()); + const writer = cwriter.writer(); - if (out_seg.nsects == 0 and - (mem.eql(u8, out_seg.segName(), "__DATA_CONST") or - mem.eql(u8, out_seg.segName(), "__DATA"))) continue; + var ncmds: usize = 0; - try writer.writeStruct(out_seg); - for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| { - if (header.size == 0) continue; - var out_header = header; - out_header.offset = 0; - try writer.writeStruct(out_header); + // UUID comes first presumably to speed up lookup by the consumer like lldb. + @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid); + try writer.writeStruct(self.uuid_cmd); + ncmds += 1; + + // Segment and section load commands + { + // Write segment/section headers from the binary file first. + const slice = macho_file.sections.slice(); + var sect_id: usize = 0; + for (macho_file.segments.items, 0..) |seg, seg_id| { + if (seg_id == macho_file.linkedit_seg_index.?) break; + var out_seg = seg; + out_seg.fileoff = 0; + out_seg.filesize = 0; + try writer.writeStruct(out_seg); + for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { + var out_header = header; + out_header.offset = 0; + try writer.writeStruct(out_header); + } + sect_id += seg.nsects; } - } - // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. - for (self.segments.items, 0..) |seg, i| { - const indexes = self.getSectionIndexes(@as(u8, @intCast(i))); - try writer.writeStruct(seg); - for (self.sections.items[indexes.start..indexes.end]) |header| { - try writer.writeStruct(header); + ncmds += macho_file.segments.items.len - 1; + + // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. + sect_id = 0; + for (self.segments.items) |seg| { + try writer.writeStruct(seg); + for (self.sections.items[sect_id..][0..seg.nsects]) |header| { + try writer.writeStruct(header); + } + sect_id += seg.nsects; } + ncmds += self.segments.items.len; } -} -fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: u32) !void { - const target = macho_file.base.comp.root_mod.resolved_target.result; + try writer.writeStruct(self.symtab_cmd); + ncmds += 1; + + assert(cwriter.bytes_written == needed_size); + try self.file.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); + + return .{ ncmds, buffer.len }; +} + +fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void { var header: macho.mach_header_64 = .{}; header.filetype = macho.MH_DSYM; - switch (target.cpu.arch) { + switch (macho_file.getTarget().cpu.arch) { .aarch64 => { header.cputype = macho.CPU_TYPE_ARM64; header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; @@ -412,8 +411,8 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: else => return error.UnsupportedCpuArchitecture, } - header.ncmds = ncmds; - header.sizeofcmds = sizeofcmds; + header.ncmds = @intCast(ncmds); + header.sizeofcmds = @intCast(sizeofcmds); log.debug("writing Mach-O header {}", .{header}); @@ -435,91 +434,56 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - try self.writeSymtab(macho_file); - try self.writeStrtab(); - - const target = macho_file.base.comp.root_mod.resolved_target.result; - const page_size = MachO.getPageSize(target.cpu.arch); + const page_size = macho_file.getPageSize(); const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; + + var off = math.cast(u32, seg.fileoff) orelse return error.Overflow; + off = try self.writeSymtab(off, macho_file); + off = mem.alignForward(u32, off, @alignOf(u64)); + off = try self.writeStrtab(off); + seg.filesize = off - seg.fileoff; + const aligned_size = mem.alignForward(u64, seg.filesize, page_size); seg.vmsize = aligned_size; } -fn writeSymtab(self: *DebugSymbols, macho_file: *MachO) !void { +pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.allocator; + const cmd = &self.symtab_cmd; + cmd.nsyms = macho_file.symtab_cmd.nsyms; + cmd.strsize = macho_file.symtab_cmd.strsize; + cmd.symoff = off; - var locals = std.ArrayList(macho.nlist_64).init(gpa); - defer locals.deinit(); - - for (macho_file.locals.items, 0..) |sym, sym_id| { - if (sym.n_strx == 0) continue; // no name, skip - const sym_loc = MachO.SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)) }; - if (macho_file.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip - if (macho_file.getGlobal(macho_file.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip - var out_sym = sym; - out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(sym_loc)); - try locals.append(out_sym); - } + try self.symtab.resize(gpa, cmd.nsyms); + try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1); - var exports = std.ArrayList(macho.nlist_64).init(gpa); - defer exports.deinit(); - - for (macho_file.globals.items) |global| { - const sym = macho_file.getSymbol(global); - if (sym.undf()) continue; // import, skip - var out_sym = sym; - out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(global)); - try exports.append(out_sym); + if (macho_file.getZigObject()) |zo| { + zo.writeSymtab(macho_file, self); + } + for (macho_file.objects.items) |index| { + try macho_file.getFile(index).?.writeSymtab(macho_file, self); + } + for (macho_file.dylibs.items) |index| { + try macho_file.getFile(index).?.writeSymtab(macho_file, self); + } + if (macho_file.getInternalObject()) |internal| { + internal.writeSymtab(macho_file, self); } - const nlocals = locals.items.len; - const nexports = exports.items.len; - const nsyms = nlocals + nexports; - - const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; - const offset = mem.alignForward(u64, seg.fileoff, @alignOf(macho.nlist_64)); - const needed_size = nsyms * @sizeOf(macho.nlist_64); - seg.filesize = offset + needed_size - seg.fileoff; - - self.symtab_cmd.symoff = @as(u32, @intCast(offset)); - self.symtab_cmd.nsyms = @as(u32, @intCast(nsyms)); - - const locals_off = @as(u32, @intCast(offset)); - const locals_size = nlocals * @sizeOf(macho.nlist_64); - const exports_off = locals_off + locals_size; - const exports_size = nexports * @sizeOf(macho.nlist_64); + assert(self.strtab.items.len == cmd.strsize); - log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off }); - try self.file.pwriteAll(mem.sliceAsBytes(locals.items), locals_off); + try self.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff); - log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); - try self.file.pwriteAll(mem.sliceAsBytes(exports.items), exports_off); + return off + cmd.nsyms * @sizeOf(macho.nlist_64); } -fn writeStrtab(self: *DebugSymbols) !void { - const tracy = trace(@src()); - defer tracy.end(); - - const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; - const symtab_size = @as(u32, @intCast(self.symtab_cmd.nsyms * @sizeOf(macho.nlist_64))); - const offset = mem.alignForward(u64, self.symtab_cmd.symoff + symtab_size, @alignOf(u64)); - const needed_size = mem.alignForward(u64, self.strtab.buffer.items.len, @alignOf(u64)); - - seg.filesize = offset + needed_size - seg.fileoff; - self.symtab_cmd.stroff = @as(u32, @intCast(offset)); - self.symtab_cmd.strsize = @as(u32, @intCast(needed_size)); - - log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); - - try self.file.pwriteAll(self.strtab.buffer.items, offset); - - if (self.strtab.buffer.items.len < needed_size) { - // Ensure we are always padded to the actual length of the file. - try self.file.pwriteAll(&[_]u8{0}, offset + needed_size); - } +pub fn writeStrtab(self: *DebugSymbols, off: u32) !u32 { + const cmd = &self.symtab_cmd; + cmd.stroff = off; + try self.file.pwriteAll(self.strtab.items, cmd.stroff); + return off + cmd.strsize; } pub fn getSectionIndexes(self: *DebugSymbols, segment_index: u8) struct { start: u8, end: u8 } { @@ -559,7 +523,7 @@ const assert = std.debug.assert; const fs = std.fs; const link = @import("../../link.zig"); const load_commands = @import("load_commands.zig"); -const log = std.log.scoped(.dsym); +const log = std.log.scoped(.link_dsym); const macho = std.macho; const makeStaticString = MachO.makeStaticString; const math = std.math; diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index abad323213..32f7a018a2 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -576,7 +576,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) !void { } } -pub fn writeSymtab(self: Dylib, macho_file: *MachO) void { +pub fn writeSymtab(self: Dylib, macho_file: *MachO, ctx: anytype) void { const tracy = trace(@src()); defer tracy.end(); @@ -585,10 +585,10 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void { const file = global.getFile(macho_file) orelse continue; if (file.getIndex() != self.index) continue; const idx = global.getOutputSymtabIndex(macho_file) orelse continue; - const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(global.getName(macho_file)); - macho_file.strtab.appendAssumeCapacity(0); - const out_sym = &macho_file.symtab.items[idx]; + const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(global.getName(macho_file)); + ctx.strtab.appendAssumeCapacity(0); + const out_sym = &ctx.symtab.items[idx]; out_sym.n_strx = n_strx; global.setOutputSym(macho_file, out_sym); } diff --git a/src/link/MachO/InternalObject.zig b/src/link/MachO/InternalObject.zig index bf770f02f0..30b750260c 100644 --- a/src/link/MachO/InternalObject.zig +++ b/src/link/MachO/InternalObject.zig @@ -139,15 +139,15 @@ pub fn calcSymtabSize(self: *InternalObject, macho_file: *MachO) !void { } } -pub fn writeSymtab(self: InternalObject, macho_file: *MachO) void { +pub fn writeSymtab(self: InternalObject, macho_file: *MachO, ctx: anytype) void { for (self.symbols.items) |sym_index| { const sym = macho_file.getSymbol(sym_index); if (sym.getFile(macho_file)) |file| if (file.getIndex() != self.index) continue; const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; - const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); - macho_file.strtab.appendAssumeCapacity(0); - const out_sym = &macho_file.symtab.items[idx]; + const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); + ctx.strtab.appendAssumeCapacity(0); + const out_sym = &ctx.symtab.items[idx]; out_sym.n_strx = n_strx; sym.setOutputSym(macho_file, out_sym); } diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 5f98d490aa..d6c5010b31 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -1320,7 +1320,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { } } -pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void { +pub fn writeSymtab(self: Object, macho_file: *MachO, ctx: anytype) error{Overflow}!void { const tracy = trace(@src()); defer tracy.end(); @@ -1329,19 +1329,19 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void { const file = sym.getFile(macho_file) orelse continue; if (file.getIndex() != self.index) continue; const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; - const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); - macho_file.strtab.appendAssumeCapacity(0); - const out_sym = &macho_file.symtab.items[idx]; + const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); + ctx.strtab.appendAssumeCapacity(0); + const out_sym = &ctx.symtab.items[idx]; out_sym.n_strx = n_strx; sym.setOutputSym(macho_file, out_sym); } if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo()) - try self.writeStabs(macho_file); + try self.writeStabs(macho_file, ctx); } -pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void { +pub fn writeStabs(self: *const Object, macho_file: *MachO, ctx: anytype) error{Overflow}!void { const writeFuncStab = struct { inline fn writeFuncStab( n_strx: u32, @@ -1349,30 +1349,30 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void n_value: u64, size: u64, index: u32, - ctx: *MachO, + context: anytype, ) void { - ctx.symtab.items[index] = .{ + context.symtab.items[index] = .{ .n_strx = 0, .n_type = macho.N_BNSYM, .n_sect = n_sect, .n_desc = 0, .n_value = n_value, }; - ctx.symtab.items[index + 1] = .{ + context.symtab.items[index + 1] = .{ .n_strx = n_strx, .n_type = macho.N_FUN, .n_sect = n_sect, .n_desc = 0, .n_value = n_value, }; - ctx.symtab.items[index + 2] = .{ + context.symtab.items[index + 2] = .{ .n_strx = 0, .n_type = macho.N_FUN, .n_sect = 0, .n_desc = 0, .n_value = size, }; - ctx.symtab.items[index + 3] = .{ + context.symtab.items[index + 3] = .{ .n_strx = 0, .n_type = macho.N_ENSYM, .n_sect = n_sect, @@ -1392,10 +1392,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void // Open scope // N_SO comp_dir - var n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(comp_dir); - macho_file.strtab.appendAssumeCapacity(0); - macho_file.symtab.items[index] = .{ + var n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(comp_dir); + ctx.strtab.appendAssumeCapacity(0); + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_SO, .n_sect = 0, @@ -1404,10 +1404,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void }; index += 1; // N_SO tu_name - n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(tu_name); - macho_file.strtab.appendAssumeCapacity(0); - macho_file.symtab.items[index] = .{ + n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(tu_name); + ctx.strtab.appendAssumeCapacity(0); + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_SO, .n_sect = 0, @@ -1416,18 +1416,18 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void }; index += 1; // N_OSO path - n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); + n_strx = @as(u32, @intCast(ctx.strtab.items.len)); if (self.archive) |ar| { - macho_file.strtab.appendSliceAssumeCapacity(ar.path); - macho_file.strtab.appendAssumeCapacity('('); - macho_file.strtab.appendSliceAssumeCapacity(self.path); - macho_file.strtab.appendAssumeCapacity(')'); - macho_file.strtab.appendAssumeCapacity(0); + ctx.strtab.appendSliceAssumeCapacity(ar.path); + ctx.strtab.appendAssumeCapacity('('); + ctx.strtab.appendSliceAssumeCapacity(self.path); + ctx.strtab.appendAssumeCapacity(')'); + ctx.strtab.appendAssumeCapacity(0); } else { - macho_file.strtab.appendSliceAssumeCapacity(self.path); - macho_file.strtab.appendAssumeCapacity(0); + ctx.strtab.appendSliceAssumeCapacity(self.path); + ctx.strtab.appendAssumeCapacity(0); } - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_OSO, .n_sect = 0, @@ -1448,17 +1448,17 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void const sect = macho_file.sections.items(.header)[sym.out_n_sect]; const sym_n_strx = n_strx: { const symtab_index = sym.getOutputSymtabIndex(macho_file).?; - const osym = macho_file.symtab.items[symtab_index]; + const osym = ctx.symtab.items[symtab_index]; break :n_strx osym.n_strx; }; const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; const sym_n_value = sym.getAddress(.{}, macho_file); const sym_size = sym.getSize(macho_file); if (sect.isCode()) { - writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file); + writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx); index += 4; } else if (sym.visibility == .global) { - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = sym_n_strx, .n_type = macho.N_GSYM, .n_sect = sym_n_sect, @@ -1467,7 +1467,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void }; index += 1; } else { - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = sym_n_strx, .n_type = macho.N_STSYM, .n_sect = sym_n_sect, @@ -1480,7 +1480,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void // Close scope // N_SO - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = 0, .n_type = macho.N_SO, .n_sect = 0, @@ -1493,10 +1493,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void for (self.stab_files.items) |sf| { // Open scope // N_SO comp_dir - var n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(sf.getCompDir(self)); - macho_file.strtab.appendAssumeCapacity(0); - macho_file.symtab.items[index] = .{ + var n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(sf.getCompDir(self)); + ctx.strtab.appendAssumeCapacity(0); + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_SO, .n_sect = 0, @@ -1505,10 +1505,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void }; index += 1; // N_SO tu_name - n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(sf.getTuName(self)); - macho_file.strtab.appendAssumeCapacity(0); - macho_file.symtab.items[index] = .{ + n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(sf.getTuName(self)); + ctx.strtab.appendAssumeCapacity(0); + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_SO, .n_sect = 0, @@ -1517,10 +1517,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void }; index += 1; // N_OSO path - n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self)); - macho_file.strtab.appendAssumeCapacity(0); - macho_file.symtab.items[index] = .{ + n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self)); + ctx.strtab.appendAssumeCapacity(0); + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_OSO, .n_sect = 0, @@ -1536,7 +1536,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void if (!sym.flags.output_symtab) continue; const sym_n_strx = n_strx: { const symtab_index = sym.getOutputSymtabIndex(macho_file).?; - const osym = macho_file.symtab.items[symtab_index]; + const osym = ctx.symtab.items[symtab_index]; break :n_strx osym.n_strx; }; 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 const sym_size = sym.getSize(macho_file); switch (stab.tag) { .func => { - writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file); + writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx); index += 4; }, .global => { - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = sym_n_strx, .n_type = macho.N_GSYM, .n_sect = sym_n_sect, @@ -1558,7 +1558,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void index += 1; }, .static => { - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = sym_n_strx, .n_type = macho.N_STSYM, .n_sect = sym_n_sect, @@ -1572,7 +1572,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void // Close scope // N_SO - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = 0, .n_type = macho.N_SO, .n_sect = 0, diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 3b40b52ce3..52b03eb081 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -310,7 +310,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void { } } -pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void { +pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void { const tracy = trace(@src()); defer tracy.end(); @@ -319,10 +319,10 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void { const file = sym.getFile(macho_file) orelse continue; if (file.getIndex() != self.index) continue; const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; - const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); - macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); - macho_file.strtab.appendAssumeCapacity(0); - const out_sym = &macho_file.symtab.items[idx]; + const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); + ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); + ctx.strtab.appendAssumeCapacity(0); + const out_sym = &ctx.symtab.items[idx]; out_sym.n_strx = n_strx; sym.setOutputSym(macho_file, out_sym); } diff --git a/src/link/MachO/file.zig b/src/link/MachO/file.zig index 67b2b9106e..cb3bbe283a 100644 --- a/src/link/MachO/file.zig +++ b/src/link/MachO/file.zig @@ -90,9 +90,9 @@ pub const File = union(enum) { }; } - pub fn writeSymtab(file: File, macho_file: *MachO) !void { + pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) !void { return switch (file) { - inline else => |x| x.writeSymtab(macho_file), + inline else => |x| x.writeSymtab(macho_file, ctx), }; } diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 7d045779fe..cf8dca92e0 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -5,6 +5,7 @@ const macho = std.macho; const mem = std.mem; const Allocator = mem.Allocator; +const DebugSymbols = @import("DebugSymbols.zig"); const Dylib = @import("Dylib.zig"); const MachO = @import("../MachO.zig"); @@ -97,6 +98,27 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) u32 { return @as(u32, @intCast(sizeofcmds)); } +pub fn calcLoadCommandsSizeDsym(macho_file: *MachO, dsym: *const DebugSymbols) u32 { + var sizeofcmds: u64 = 0; + + // LC_SEGMENT_64 + sizeofcmds += @sizeOf(macho.segment_command_64) * (macho_file.segments.items.len - 1); + for (macho_file.segments.items) |seg| { + sizeofcmds += seg.nsects * @sizeOf(macho.section_64); + } + sizeofcmds += @sizeOf(macho.segment_command_64) * dsym.segments.items.len; + for (dsym.segments.items) |seg| { + sizeofcmds += seg.nsects * @sizeOf(macho.section_64); + } + + // LC_SYMTAB + sizeofcmds += @sizeOf(macho.symtab_command); + // LC_UUID + sizeofcmds += @sizeOf(macho.uuid_command); + + return @as(u32, @intCast(sizeofcmds)); +} + pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { var sizeofcmds: u64 = 0; |
