macho: write Mach-O dSym header

This commit is contained in:
Jakub Konka 2020-12-27 09:47:56 +01:00
parent bd99a87dc2
commit cf94341910
2 changed files with 51 additions and 0 deletions

View File

@ -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

View File

@ -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;
}