macho: create dSym bundle next to final artefact

macOS requires the debug symbols to either be part of the intermediate
object file `whatever.o` or a companion `whatever.dSym` bundle. The
former case seems ill-suited for our needs since it subscribes to
the old-fashioned compilation strategy using intermediate compilation
units; the latter is what we need however on macOS the debug symbols
unlike in Elf are not part of the final artefact; rather they sit
next to it in its own Mach-O file.
This commit is contained in:
Jakub Konka 2020-12-27 09:30:03 +01:00
parent 0ff56e8bb1
commit bd99a87dc2
2 changed files with 62 additions and 0 deletions

View File

@ -3,6 +3,7 @@ const MachO = @This();
const std = @import("std");
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const fmt = std.fmt;
const fs = std.fs;
const log = std.log.scoped(.link);
const macho = std.macho;
@ -21,6 +22,7 @@ const File = link.File;
const Cache = @import("../Cache.zig");
const target_util = @import("../target.zig");
const DebugSymbols = @import("MachO/DebugSymbols.zig");
const Trie = @import("MachO/Trie.zig");
const CodeSignature = @import("MachO/CodeSignature.zig");
@ -31,6 +33,9 @@ pub const base_tag: File.Tag = File.Tag.macho;
base: File,
/// Debug symbols bundle (or dSym).
d_sym: ?DebugSymbols = null,
/// Page size is dependent on the target cpu architecture.
/// For x86_64 that's 4KB, whereas for aarch64, that's 16KB.
page_size: u16,
@ -264,6 +269,20 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
self.base.file = file;
// Create dSym bundle.
const d_sym_path = try fmt.allocPrint(allocator, "{}.dSym/Contents/Resources/DWARF/", .{sub_path});
defer allocator.free(d_sym_path);
var d_sym_bundle = try options.emit.?.directory.handle.makeOpenPath(d_sym_path, .{});
defer d_sym_bundle.close();
const d_sym_file = try d_sym_bundle.createFile(sub_path, .{
.truncate = false,
.read = true,
});
self.d_sym = .{
.base = self,
.file = d_sym_file,
};
// Index 0 is always a null symbol.
try self.local_symbols.append(allocator, .{
.n_strx = 0,
@ -943,6 +962,9 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 {
}
pub fn deinit(self: *MachO) void {
if (self.d_sym) |*ds| {
ds.deinit(self.base.allocator);
}
self.binding_info_table.deinit(self.base.allocator);
self.lazy_binding_info_table.deinit(self.base.allocator);
self.pie_fixups.deinit(self.base.allocator);

View File

@ -0,0 +1,40 @@
const DebugSymbols = @This();
const std = @import("std");
const fs = std.fs;
const macho = std.macho;
const mem = std.mem;
const DW = std.dwarf;
const leb = std.leb;
const Allocator = mem.Allocator;
const MachO = @import("../MachO.zig");
usingnamespace @import("commands.zig");
base: *MachO,
file: fs.File,
/// Mach header
header: ?macho.mach_header_64 = null,
/// Table of all load commands
load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
/// __PAGEZERO segment
pagezero_segment_cmd_index: ?u16 = null,
/// __TEXT segment
text_segment_cmd_index: ?u16 = null,
/// __DWARF segment
dwarf_segment_cmd_index: ?u16 = null,
/// __DATA segment
data_segment_cmd_index: ?u16 = null,
/// __LINKEDIT segment
linkedit_segment_cmd_index: ?u16 = null,
/// Symbol table
symtab_cmd_index: ?u16 = null,
/// UUID load command
uuid_cmd_index: ?u16 = null,
pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {
self.file.close();
}