aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2020-12-27 09:47:56 +0100
committerJakub Konka <kubkon@jakubkonka.com>2020-12-31 10:19:04 +0100
commitcf9434191004e57e1cd3a75dcd91d5ad7e378c63 (patch)
tree071e004dee01fff3ef720632657fad1ecafc22a9 /src
parentbd99a87dc224b7d84e764fc2a8a8f4e3068078b3 (diff)
downloadzig-cf9434191004e57e1cd3a75dcd91d5ad7e378c63.tar.gz
zig-cf9434191004e57e1cd3a75dcd91d5ad7e378c63.zip
macho: write Mach-O dSym header
Diffstat (limited to 'src')
-rw-r--r--src/link/MachO.zig6
-rw-r--r--src/link/MachO/DebugSymbols.zig45
2 files changed, 51 insertions, 0 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 5d5a5d76b2..c8449fbe1a 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -299,6 +299,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
}
try self.populateMissingMetadata();
+ try self.d_sym.?.populateMissingMetadata(allocator);
return self;
}
@@ -352,6 +353,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
try self.writeStringTable();
try self.updateLinkeditSegmentSizes();
+ if (self.d_sym) |*ds| {
+ // Flush debug symbols bundle.
+ try ds.flush();
+ }
+
if (target.cpu.arch == .aarch64) {
// Preallocate space for the code signature.
// We need to do this at this stage so that we have the load commands with proper values
diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig
index 1e30bdf564..b485e391af 100644
--- a/src/link/MachO/DebugSymbols.zig
+++ b/src/link/MachO/DebugSymbols.zig
@@ -1,7 +1,9 @@
const DebugSymbols = @This();
const std = @import("std");
+const assert = std.debug.assert;
const fs = std.fs;
+const log = std.log.scoped(.link);
const macho = std.macho;
const mem = std.mem;
const DW = std.dwarf;
@@ -35,6 +37,49 @@ symtab_cmd_index: ?u16 = null,
/// UUID load command
uuid_cmd_index: ?u16 = null,
+header_dirty: bool = false,
+load_commands_dirty: bool = false,
+
+/// You must call this function *after* `MachO.populateMissingMetadata()`
+/// has been called to get a viable debug symbols output.
+pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void {
+ if (self.header == null) {
+ const base_header = self.base.header.?;
+ var header: macho.mach_header_64 = undefined;
+ header.magic = macho.MH_MAGIC_64;
+ header.cputype = base_header.cputype;
+ header.cpusubtype = base_header.cpusubtype;
+ header.filetype = macho.MH_DSYM;
+ // These will get populated at the end of flushing the results to file.
+ header.ncmds = 0;
+ header.sizeofcmds = 0;
+ header.flags = 0;
+ header.reserved = 0;
+ self.header = header;
+ self.header_dirty = true;
+ }
+}
+
+pub fn flush(self: *DebugSymbols) !void {
+ try self.writeHeader();
+ assert(!self.header_dirty);
+ assert(!self.load_commands_dirty);
+}
+
pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {
self.file.close();
}
+
+fn writeHeader(self: *DebugSymbols) !void {
+ if (!self.header_dirty) return;
+
+ self.header.?.ncmds = @intCast(u32, self.load_commands.items.len);
+ var sizeofcmds: u32 = 0;
+ for (self.load_commands.items) |cmd| {
+ sizeofcmds += cmd.cmdsize();
+ }
+ self.header.?.sizeofcmds = sizeofcmds;
+ log.debug("writing Mach-O dSym header {}", .{self.header.?});
+ try self.file.pwriteAll(mem.asBytes(&self.header.?), 0);
+ self.header_dirty = false;
+}