authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-27 09:47:56+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-31 10:19:04+01:00
logcf9434191004e57e1cd3a75dcd91d5ad7e378c63
tree071e004dee01fff3ef720632657fad1ecafc22a9
parentbd99a87dc224b7d84e764fc2a8a8f4e3068078b3

macho: write Mach-O dSym header


2 files changed, 51 insertions(+), 0 deletions(-)

src/link/MachO.zig+6
...@@ -299,6 +299,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -299,6 +299,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
299 }299 }
300300
301 try self.populateMissingMetadata();301 try self.populateMissingMetadata();
302 try self.d_sym.?.populateMissingMetadata(allocator);
302303
303 return self;304 return self;
304}305}
...@@ -352,6 +353,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -352,6 +353,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
352 try self.writeStringTable();353 try self.writeStringTable();
353 try self.updateLinkeditSegmentSizes();354 try self.updateLinkeditSegmentSizes();
354355
356 if (self.d_sym) |*ds| {
357 // Flush debug symbols bundle.
358 try ds.flush();
359 }
360
355 if (target.cpu.arch == .aarch64) {361 if (target.cpu.arch == .aarch64) {
356 // Preallocate space for the code signature.362 // Preallocate space for the code signature.
357 // We need to do this at this stage so that we have the load commands with proper values363 // We need to do this at this stage so that we have the load commands with proper values
src/link/MachO/DebugSymbols.zig+45
...@@ -1,7 +1,9 @@...@@ -1,7 +1,9 @@
1const DebugSymbols = @This();1const DebugSymbols = @This();
22
3const std = @import("std");3const std = @import("std");
4const assert = std.debug.assert;
4const fs = std.fs;5const fs = std.fs;
6const log = std.log.scoped(.link);
5const macho = std.macho;7const macho = std.macho;
6const mem = std.mem;8const mem = std.mem;
7const DW = std.dwarf;9const DW = std.dwarf;
...@@ -35,6 +37,49 @@ symtab_cmd_index: ?u16 = null,...@@ -35,6 +37,49 @@ symtab_cmd_index: ?u16 = null,
35/// UUID load command37/// UUID load command
36uuid_cmd_index: ?u16 = null,38uuid_cmd_index: ?u16 = null,
3739
40header_dirty: bool = false,
41load_commands_dirty: bool = false,
42
43/// You must call this function *after* `MachO.populateMissingMetadata()`
44/// has been called to get a viable debug symbols output.
45pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void {
46 if (self.header == null) {
47 const base_header = self.base.header.?;
48 var header: macho.mach_header_64 = undefined;
49 header.magic = macho.MH_MAGIC_64;
50 header.cputype = base_header.cputype;
51 header.cpusubtype = base_header.cpusubtype;
52 header.filetype = macho.MH_DSYM;
53 // These will get populated at the end of flushing the results to file.
54 header.ncmds = 0;
55 header.sizeofcmds = 0;
56 header.flags = 0;
57 header.reserved = 0;
58 self.header = header;
59 self.header_dirty = true;
60 }
61}
62
63pub fn flush(self: *DebugSymbols) !void {
64 try self.writeHeader();
65 assert(!self.header_dirty);
66 assert(!self.load_commands_dirty);
67}
68
38pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {69pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {
39 self.file.close();70 self.file.close();
40}71}
72
73fn writeHeader(self: *DebugSymbols) !void {
74 if (!self.header_dirty) return;
75
76 self.header.?.ncmds = @intCast(u32, self.load_commands.items.len);
77 var sizeofcmds: u32 = 0;
78 for (self.load_commands.items) |cmd| {
79 sizeofcmds += cmd.cmdsize();
80 }
81 self.header.?.sizeofcmds = sizeofcmds;
82 log.debug("writing Mach-O dSym header {}", .{self.header.?});
83 try self.file.pwriteAll(mem.asBytes(&self.header.?), 0);
84 self.header_dirty = false;
85}