Commit f2214e4371
Changed files (9)
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;
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);
}
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),
};
}
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);
}
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;
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,
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);
}
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
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);