mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 08:33:06 +00:00
zld: clean up logic for creating mach header
This commit is contained in:
parent
e08f7ba889
commit
9c3ebe0216
@ -41,8 +41,6 @@ d_sym: ?DebugSymbols = null,
|
||||
/// For x86_64 that's 4KB, whereas for aarch64, that's 16KB.
|
||||
page_size: u16,
|
||||
|
||||
/// Mach-O header
|
||||
header: ?macho.mach_header_64 = null,
|
||||
/// We commit 0x1000 = 4096 bytes of space to the header and
|
||||
/// the table of load commands. This should be plenty for any
|
||||
/// potential future extensions.
|
||||
@ -128,7 +126,6 @@ offset_table: std.ArrayListUnmanaged(GOTEntry) = .{},
|
||||
error_flags: File.ErrorFlags = File.ErrorFlags{},
|
||||
|
||||
offset_table_count_dirty: bool = false,
|
||||
header_dirty: bool = false,
|
||||
load_commands_dirty: bool = false,
|
||||
rebase_info_dirty: bool = false,
|
||||
binding_info_dirty: bool = false,
|
||||
@ -497,7 +494,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
assert(!self.offset_table_count_dirty);
|
||||
assert(!self.header_dirty);
|
||||
assert(!self.load_commands_dirty);
|
||||
assert(!self.rebase_info_dirty);
|
||||
assert(!self.binding_info_dirty);
|
||||
@ -1488,54 +1484,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.Lib => return error.TODOImplementWritingLibFiles,
|
||||
}
|
||||
|
||||
if (self.header == null) {
|
||||
var header: macho.mach_header_64 = undefined;
|
||||
header.magic = macho.MH_MAGIC_64;
|
||||
|
||||
const CpuInfo = struct {
|
||||
cpu_type: macho.cpu_type_t,
|
||||
cpu_subtype: macho.cpu_subtype_t,
|
||||
};
|
||||
|
||||
const cpu_info: CpuInfo = switch (self.base.options.target.cpu.arch) {
|
||||
.aarch64 => .{
|
||||
.cpu_type = macho.CPU_TYPE_ARM64,
|
||||
.cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL,
|
||||
},
|
||||
.x86_64 => .{
|
||||
.cpu_type = macho.CPU_TYPE_X86_64,
|
||||
.cpu_subtype = macho.CPU_SUBTYPE_X86_64_ALL,
|
||||
},
|
||||
else => return error.UnsupportedMachOArchitecture,
|
||||
};
|
||||
header.cputype = cpu_info.cpu_type;
|
||||
header.cpusubtype = cpu_info.cpu_subtype;
|
||||
|
||||
const filetype: u32 = switch (self.base.options.output_mode) {
|
||||
.Exe => macho.MH_EXECUTE,
|
||||
.Obj => macho.MH_OBJECT,
|
||||
.Lib => switch (self.base.options.link_mode) {
|
||||
.Static => return error.TODOStaticLibMachOType,
|
||||
.Dynamic => macho.MH_DYLIB,
|
||||
},
|
||||
};
|
||||
header.filetype = filetype;
|
||||
// These will get populated at the end of flushing the results to file.
|
||||
header.ncmds = 0;
|
||||
header.sizeofcmds = 0;
|
||||
|
||||
switch (self.base.options.output_mode) {
|
||||
.Exe => {
|
||||
header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE;
|
||||
},
|
||||
else => {
|
||||
header.flags = 0;
|
||||
},
|
||||
}
|
||||
header.reserved = 0;
|
||||
self.header = header;
|
||||
self.header_dirty = true;
|
||||
}
|
||||
if (self.pagezero_segment_cmd_index == null) {
|
||||
self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
try self.load_commands.append(self.base.allocator, .{
|
||||
@ -1543,7 +1491,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.vmsize = 0x100000000, // size always set to 4GB
|
||||
}),
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.text_segment_cmd_index == null) {
|
||||
@ -1567,7 +1514,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.initprot = initprot,
|
||||
}),
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.text_section_index == null) {
|
||||
@ -1592,7 +1538,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.@"align" = alignment,
|
||||
.flags = flags,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.stubs_section_index == null) {
|
||||
@ -1624,7 +1569,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.flags = flags,
|
||||
.reserved2 = stub_size,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.stub_helper_section_index == null) {
|
||||
@ -1650,7 +1594,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.@"align" = alignment,
|
||||
.flags = flags,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.data_const_segment_cmd_index == null) {
|
||||
@ -1674,7 +1617,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.initprot = initprot,
|
||||
}),
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.got_section_index == null) {
|
||||
@ -1695,7 +1637,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.@"align" = 3, // 2^3 = @sizeOf(u64)
|
||||
.flags = flags,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.data_segment_cmd_index == null) {
|
||||
@ -1719,7 +1660,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.initprot = initprot,
|
||||
}),
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.la_symbol_ptr_section_index == null) {
|
||||
@ -1740,7 +1680,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.@"align" = 3, // 2^3 = @sizeOf(u64)
|
||||
.flags = flags,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.data_section_index == null) {
|
||||
@ -1759,7 +1698,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.offset = @intCast(u32, off),
|
||||
.@"align" = 3, // 2^3 = @sizeOf(u64)
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.linkedit_segment_cmd_index == null) {
|
||||
@ -1779,7 +1717,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.initprot = initprot,
|
||||
}),
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.dyld_info_cmd_index == null) {
|
||||
@ -1826,7 +1763,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
dyld.export_off = @intCast(u32, export_off);
|
||||
dyld.export_size = expected_size;
|
||||
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.symtab_cmd_index == null) {
|
||||
@ -1858,7 +1794,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
symtab.stroff = @intCast(u32, strtab_off);
|
||||
symtab.strsize = @intCast(u32, strtab_size);
|
||||
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
self.string_table_dirty = true;
|
||||
}
|
||||
@ -1895,7 +1830,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.nlocrel = 0,
|
||||
},
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.dylinker_cmd_index == null) {
|
||||
@ -1914,7 +1848,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
mem.set(u8, dylinker_cmd.data, 0);
|
||||
mem.copy(u8, dylinker_cmd.data, mem.spanZ(DEFAULT_DYLD_PATH));
|
||||
try self.load_commands.append(self.base.allocator, .{ .Dylinker = dylinker_cmd });
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.libsystem_cmd_index == null) {
|
||||
@ -1925,7 +1858,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
|
||||
try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
|
||||
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.main_cmd_index == null) {
|
||||
@ -1938,7 +1870,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.stacksize = 0,
|
||||
},
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.version_min_cmd_index == null) {
|
||||
@ -1960,7 +1891,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.sdk = version,
|
||||
},
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.source_version_cmd_index == null) {
|
||||
@ -1972,7 +1902,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.version = 0x0,
|
||||
},
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.uuid_cmd_index == null) {
|
||||
@ -1984,7 +1913,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
};
|
||||
std.crypto.random.bytes(&uuid_cmd.uuid);
|
||||
try self.load_commands.append(self.base.allocator, .{ .Uuid = uuid_cmd });
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.code_signature_cmd_index == null) {
|
||||
@ -1997,7 +1925,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.datasize = 0,
|
||||
},
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (!self.nonlazy_imports.contains("dyld_stub_binder")) {
|
||||
@ -3224,24 +3151,57 @@ fn writeLoadCommands(self: *MachO) !void {
|
||||
}
|
||||
|
||||
const off = @sizeOf(macho.mach_header_64);
|
||||
|
||||
log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
|
||||
|
||||
try self.base.file.?.pwriteAll(buffer, off);
|
||||
self.load_commands_dirty = false;
|
||||
}
|
||||
|
||||
/// Writes Mach-O file header.
|
||||
fn writeHeader(self: *MachO) !void {
|
||||
if (!self.header_dirty) return;
|
||||
var header = emptyHeader(.{
|
||||
.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL,
|
||||
});
|
||||
|
||||
self.header.?.ncmds = @intCast(u32, self.load_commands.items.len);
|
||||
var sizeofcmds: u32 = 0;
|
||||
for (self.load_commands.items) |cmd| {
|
||||
sizeofcmds += cmd.cmdsize();
|
||||
switch (self.base.options.target.cpu.arch) {
|
||||
.aarch64 => {
|
||||
header.cputype = macho.CPU_TYPE_ARM64;
|
||||
header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
|
||||
},
|
||||
.x86_64 => {
|
||||
header.cputype = macho.CPU_TYPE_X86_64;
|
||||
header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL;
|
||||
},
|
||||
else => return error.UnsupportedCpuArchitecture,
|
||||
}
|
||||
self.header.?.sizeofcmds = sizeofcmds;
|
||||
log.debug("writing Mach-O header {}", .{self.header.?});
|
||||
try self.base.file.?.pwriteAll(mem.asBytes(&self.header.?), 0);
|
||||
self.header_dirty = false;
|
||||
|
||||
switch (self.base.options.output_mode) {
|
||||
.Exe => {
|
||||
header.filetype = macho.MH_EXECUTE;
|
||||
},
|
||||
.Lib => {
|
||||
// By this point, it can only be a dylib.
|
||||
header.filetype = macho.MH_DYLIB;
|
||||
header.flags |= macho.MH_NO_REEXPORTED_DYLIBS;
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
if (self.hasTlvDescriptors()) {
|
||||
header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
|
||||
}
|
||||
|
||||
header.ncmds = @intCast(u32, self.load_commands.items.len);
|
||||
header.sizeofcmds = 0;
|
||||
|
||||
for (self.load_commands.items) |cmd| {
|
||||
header.sizeofcmds += cmd.cmdsize();
|
||||
}
|
||||
|
||||
log.debug("writing Mach-O header {}", .{header});
|
||||
|
||||
try self.base.file.?.pwriteAll(mem.asBytes(&header), 0);
|
||||
}
|
||||
|
||||
pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
|
||||
@ -3249,3 +3209,7 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
|
||||
return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch
|
||||
std.math.maxInt(@TypeOf(actual_size));
|
||||
}
|
||||
|
||||
fn hasTlvDescriptors(_: *MachO) bool {
|
||||
return false;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ const DebugSymbols = @This();
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const fs = std.fs;
|
||||
const log = std.log.scoped(.link);
|
||||
const log = std.log.scoped(.dsym);
|
||||
const macho = std.macho;
|
||||
const mem = std.mem;
|
||||
const DW = std.dwarf;
|
||||
@ -27,9 +27,6 @@ const page_size: u16 = 0x1000;
|
||||
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
|
||||
@ -78,7 +75,6 @@ dbg_info_decl_last: ?*TextBlock = null,
|
||||
/// Table of debug symbol names aka the debug string table.
|
||||
debug_string_table: std.ArrayListUnmanaged(u8) = .{},
|
||||
|
||||
header_dirty: bool = false,
|
||||
load_commands_dirty: bool = false,
|
||||
string_table_dirty: bool = false,
|
||||
debug_string_table_dirty: bool = false,
|
||||
@ -106,26 +102,10 @@ const min_nop_size = 2;
|
||||
/// 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;
|
||||
}
|
||||
if (self.uuid_cmd_index == null) {
|
||||
const base_cmd = self.base.load_commands.items[self.base.uuid_cmd_index.?];
|
||||
self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
try self.load_commands.append(allocator, base_cmd);
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.symtab_cmd_index == null) {
|
||||
@ -134,11 +114,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const symtab_size = base_cmd.nsyms * @sizeOf(macho.nlist_64);
|
||||
const symtab_off = self.findFreeSpaceLinkedit(symtab_size, @sizeOf(macho.nlist_64));
|
||||
|
||||
log.debug("found dSym symbol table free space 0x{x} to 0x{x}", .{ symtab_off, symtab_off + symtab_size });
|
||||
log.debug("found symbol table free space 0x{x} to 0x{x}", .{ symtab_off, symtab_off + symtab_size });
|
||||
|
||||
const strtab_off = self.findFreeSpaceLinkedit(base_cmd.strsize, 1);
|
||||
|
||||
log.debug("found dSym string table free space 0x{x} to 0x{x}", .{ strtab_off, strtab_off + base_cmd.strsize });
|
||||
log.debug("found string table free space 0x{x} to 0x{x}", .{ strtab_off, strtab_off + base_cmd.strsize });
|
||||
|
||||
try self.load_commands.append(allocator, .{
|
||||
.Symtab = .{
|
||||
@ -150,7 +130,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
.strsize = base_cmd.strsize,
|
||||
},
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
self.string_table_dirty = true;
|
||||
}
|
||||
@ -159,7 +138,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const base_cmd = self.base.load_commands.items[self.base.pagezero_segment_cmd_index.?].Segment;
|
||||
const cmd = try self.copySegmentCommand(allocator, base_cmd);
|
||||
try self.load_commands.append(allocator, .{ .Segment = cmd });
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.text_segment_cmd_index == null) {
|
||||
@ -167,7 +145,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const base_cmd = self.base.load_commands.items[self.base.text_segment_cmd_index.?].Segment;
|
||||
const cmd = try self.copySegmentCommand(allocator, base_cmd);
|
||||
try self.load_commands.append(allocator, .{ .Segment = cmd });
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.data_const_segment_cmd_index == null) outer: {
|
||||
@ -176,7 +153,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const base_cmd = self.base.load_commands.items[self.base.data_const_segment_cmd_index.?].Segment;
|
||||
const cmd = try self.copySegmentCommand(allocator, base_cmd);
|
||||
try self.load_commands.append(allocator, .{ .Segment = cmd });
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.data_segment_cmd_index == null) outer: {
|
||||
@ -185,7 +161,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const base_cmd = self.base.load_commands.items[self.base.data_segment_cmd_index.?].Segment;
|
||||
const cmd = try self.copySegmentCommand(allocator, base_cmd);
|
||||
try self.load_commands.append(allocator, .{ .Segment = cmd });
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.linkedit_segment_cmd_index == null) {
|
||||
@ -196,7 +171,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
cmd.inner.fileoff = self.linkedit_off;
|
||||
cmd.inner.filesize = self.linkedit_size;
|
||||
try self.load_commands.append(allocator, .{ .Segment = cmd });
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.dwarf_segment_cmd_index == null) {
|
||||
@ -208,7 +182,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const off = linkedit.inner.fileoff + linkedit.inner.filesize;
|
||||
const vmaddr = linkedit.inner.vmaddr + linkedit.inner.vmsize;
|
||||
|
||||
log.debug("found dSym __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size });
|
||||
log.debug("found __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size });
|
||||
|
||||
try self.load_commands.append(allocator, .{
|
||||
.Segment = SegmentCommand.empty("__DWARF", .{
|
||||
@ -218,7 +192,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
.filesize = needed_size,
|
||||
}),
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.debug_str_section_index == null) {
|
||||
@ -232,7 +205,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
.offset = @intCast(u32, dwarf_segment.inner.fileoff),
|
||||
.@"align" = 1,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
self.debug_string_table_dirty = true;
|
||||
}
|
||||
@ -244,7 +216,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const p_align = 1;
|
||||
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
|
||||
|
||||
log.debug("found dSym __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
|
||||
log.debug("found __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
|
||||
|
||||
try dwarf_segment.addSection(allocator, "__debug_info", .{
|
||||
.addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
|
||||
@ -252,7 +224,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
.offset = @intCast(u32, off),
|
||||
.@"align" = p_align,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
self.debug_info_header_dirty = true;
|
||||
}
|
||||
@ -264,7 +235,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const p_align = 1;
|
||||
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
|
||||
|
||||
log.debug("found dSym __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
|
||||
log.debug("found __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
|
||||
|
||||
try dwarf_segment.addSection(allocator, "__debug_abbrev", .{
|
||||
.addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
|
||||
@ -272,7 +243,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
.offset = @intCast(u32, off),
|
||||
.@"align" = p_align,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
self.debug_abbrev_section_dirty = true;
|
||||
}
|
||||
@ -284,7 +254,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const p_align = 16;
|
||||
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
|
||||
|
||||
log.debug("found dSym __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
|
||||
log.debug("found __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
|
||||
|
||||
try dwarf_segment.addSection(allocator, "__debug_aranges", .{
|
||||
.addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
|
||||
@ -292,7 +262,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
.offset = @intCast(u32, off),
|
||||
.@"align" = p_align,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
self.debug_aranges_section_dirty = true;
|
||||
}
|
||||
@ -304,7 +273,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
const p_align = 1;
|
||||
const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
|
||||
|
||||
log.debug("found dSym __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
|
||||
log.debug("found __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
|
||||
|
||||
try dwarf_segment.addSection(allocator, "__debug_line", .{
|
||||
.addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
|
||||
@ -312,7 +281,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
|
||||
.offset = @intCast(u32, off),
|
||||
.@"align" = p_align,
|
||||
});
|
||||
self.header_dirty = true;
|
||||
self.load_commands_dirty = true;
|
||||
self.debug_line_header_dirty = true;
|
||||
}
|
||||
@ -624,7 +592,6 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt
|
||||
try self.writeLoadCommands(allocator);
|
||||
try self.writeHeader();
|
||||
|
||||
assert(!self.header_dirty);
|
||||
assert(!self.load_commands_dirty);
|
||||
assert(!self.string_table_dirty);
|
||||
assert(!self.debug_abbrev_section_dirty);
|
||||
@ -716,23 +683,38 @@ fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void {
|
||||
}
|
||||
|
||||
const off = @sizeOf(macho.mach_header_64);
|
||||
log.debug("writing {} dSym load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
|
||||
log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
|
||||
try self.file.pwriteAll(buffer, off);
|
||||
self.load_commands_dirty = false;
|
||||
}
|
||||
|
||||
fn writeHeader(self: *DebugSymbols) !void {
|
||||
if (!self.header_dirty) return;
|
||||
var header = emptyHeader(.{
|
||||
.filetype = macho.MH_DSYM,
|
||||
});
|
||||
|
||||
self.header.?.ncmds = @intCast(u32, self.load_commands.items.len);
|
||||
var sizeofcmds: u32 = 0;
|
||||
for (self.load_commands.items) |cmd| {
|
||||
sizeofcmds += cmd.cmdsize();
|
||||
switch (self.base.base.options.target.cpu.arch) {
|
||||
.aarch64 => {
|
||||
header.cputype = macho.CPU_TYPE_ARM64;
|
||||
header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
|
||||
},
|
||||
.x86_64 => {
|
||||
header.cputype = macho.CPU_TYPE_X86_64;
|
||||
header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL;
|
||||
},
|
||||
else => return error.UnsupportedCpuArchitecture,
|
||||
}
|
||||
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;
|
||||
|
||||
header.ncmds = @intCast(u32, self.load_commands.items.len);
|
||||
header.sizeofcmds = 0;
|
||||
|
||||
for (self.load_commands.items) |cmd| {
|
||||
header.sizeofcmds += cmd.cmdsize();
|
||||
}
|
||||
|
||||
log.debug("writing Mach-O header {}", .{header});
|
||||
|
||||
try self.file.pwriteAll(mem.asBytes(&header), 0);
|
||||
}
|
||||
|
||||
fn allocatedSizeLinkedit(self: *DebugSymbols, start: u64) u64 {
|
||||
@ -798,7 +780,7 @@ fn relocateSymbolTable(self: *DebugSymbols) !void {
|
||||
const existing_size = symtab.nsyms * @sizeOf(macho.nlist_64);
|
||||
|
||||
assert(new_symoff + existing_size <= self.linkedit_off + self.linkedit_size); // TODO expand LINKEDIT segment.
|
||||
log.debug("relocating dSym symbol table from 0x{x}-0x{x} to 0x{x}-0x{x}", .{
|
||||
log.debug("relocating symbol table from 0x{x}-0x{x} to 0x{x}-0x{x}", .{
|
||||
symtab.symoff,
|
||||
symtab.symoff + existing_size,
|
||||
new_symoff,
|
||||
@ -820,7 +802,7 @@ pub fn writeLocalSymbol(self: *DebugSymbols, index: usize) !void {
|
||||
try self.relocateSymbolTable();
|
||||
const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
|
||||
const off = symtab.symoff + @sizeOf(macho.nlist_64) * index;
|
||||
log.debug("writing dSym local symbol {} at 0x{x}", .{ index, off });
|
||||
log.debug("writing local symbol {} at 0x{x}", .{ index, off });
|
||||
try self.file.pwriteAll(mem.asBytes(&self.base.locals.items[index]), off);
|
||||
}
|
||||
|
||||
@ -839,7 +821,7 @@ fn writeStringTable(self: *DebugSymbols) !void {
|
||||
symtab.stroff = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1));
|
||||
}
|
||||
symtab.strsize = @intCast(u32, needed_size);
|
||||
log.debug("writing dSym string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
|
||||
log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
|
||||
|
||||
try self.file.pwriteAll(self.base.string_table.items, symtab.stroff);
|
||||
self.load_commands_dirty = true;
|
||||
|
@ -3132,54 +3132,44 @@ fn writeLoadCommands(self: *Zld) !void {
|
||||
}
|
||||
|
||||
fn writeHeader(self: *Zld) !void {
|
||||
var header: macho.mach_header_64 = undefined;
|
||||
header.magic = macho.MH_MAGIC_64;
|
||||
var header = emptyHeader(.{
|
||||
.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL,
|
||||
});
|
||||
|
||||
const CpuInfo = struct {
|
||||
cpu_type: macho.cpu_type_t,
|
||||
cpu_subtype: macho.cpu_subtype_t,
|
||||
};
|
||||
|
||||
const cpu_info: CpuInfo = switch (self.target.?.cpu.arch) {
|
||||
.aarch64 => .{
|
||||
.cpu_type = macho.CPU_TYPE_ARM64,
|
||||
.cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL,
|
||||
switch (self.target.?.cpu.arch) {
|
||||
.aarch64 => {
|
||||
header.cputype = macho.CPU_TYPE_ARM64;
|
||||
header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
|
||||
},
|
||||
.x86_64 => .{
|
||||
.cpu_type = macho.CPU_TYPE_X86_64,
|
||||
.cpu_subtype = macho.CPU_SUBTYPE_X86_64_ALL,
|
||||
.x86_64 => {
|
||||
header.cputype = macho.CPU_TYPE_X86_64;
|
||||
header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL;
|
||||
},
|
||||
else => return error.UnsupportedCpuArchitecture,
|
||||
};
|
||||
header.cputype = cpu_info.cpu_type;
|
||||
header.cpusubtype = cpu_info.cpu_subtype;
|
||||
}
|
||||
|
||||
switch (self.output.?.tag) {
|
||||
.exe => {
|
||||
header.filetype = macho.MH_EXECUTE;
|
||||
header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL;
|
||||
},
|
||||
.dylib => {
|
||||
header.filetype = macho.MH_DYLIB;
|
||||
header.flags = macho.MH_NOUNDEFS |
|
||||
macho.MH_DYLDLINK |
|
||||
macho.MH_PIE |
|
||||
macho.MH_TWOLEVEL |
|
||||
macho.MH_NO_REEXPORTED_DYLIBS;
|
||||
header.flags |= macho.MH_NO_REEXPORTED_DYLIBS;
|
||||
},
|
||||
}
|
||||
|
||||
header.reserved = 0;
|
||||
|
||||
if (self.tlv_section_index) |_|
|
||||
header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
|
||||
|
||||
header.ncmds = @intCast(u32, self.load_commands.items.len);
|
||||
header.sizeofcmds = 0;
|
||||
|
||||
for (self.load_commands.items) |cmd| {
|
||||
header.sizeofcmds += cmd.cmdsize();
|
||||
}
|
||||
|
||||
log.debug("writing Mach-O header {}", .{header});
|
||||
|
||||
try self.file.?.pwriteAll(mem.asBytes(&header), 0);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,28 @@ const Allocator = std.mem.Allocator;
|
||||
const MachO = @import("../MachO.zig");
|
||||
const padToIdeal = MachO.padToIdeal;
|
||||
|
||||
pub const HeaderArgs = struct {
|
||||
magic: u32 = macho.MH_MAGIC_64,
|
||||
cputype: macho.cpu_type_t = 0,
|
||||
cpusubtype: macho.cpu_subtype_t = 0,
|
||||
filetype: u32 = 0,
|
||||
flags: u32 = 0,
|
||||
reserved: u32 = 0,
|
||||
};
|
||||
|
||||
pub fn emptyHeader(args: HeaderArgs) macho.mach_header_64 {
|
||||
return .{
|
||||
.magic = args.magic,
|
||||
.cputype = args.cputype,
|
||||
.cpusubtype = args.cpusubtype,
|
||||
.filetype = args.filetype,
|
||||
.ncmds = 0,
|
||||
.sizeofcmds = 0,
|
||||
.flags = args.flags,
|
||||
.reserved = args.reserved,
|
||||
};
|
||||
}
|
||||
|
||||
pub const LoadCommand = union(enum) {
|
||||
Segment: SegmentCommand,
|
||||
DyldInfoOnly: macho.dyld_info_command,
|
||||
|
Loading…
Reference in New Issue
Block a user