Commit 50db993119
Changed files (4)
lib
std
src
link
lib/std/macho.zig
@@ -601,35 +601,35 @@ pub const segment_command = extern struct {
/// command and their size is reflected in cmdsize.
pub const segment_command_64 = extern struct {
/// LC_SEGMENT_64
- cmd: u32,
+ cmd: u32 = LC_SEGMENT_64,
/// includes sizeof section_64 structs
- cmdsize: u32,
+ cmdsize: u32 = @sizeOf(segment_command_64),
/// segment name
segname: [16]u8,
/// memory address of this segment
- vmaddr: u64,
+ vmaddr: u64 = 0,
/// memory size of this segment
- vmsize: u64,
+ vmsize: u64 = 0,
/// file offset of this segment
- fileoff: u64,
+ fileoff: u64 = 0,
/// amount to map from the file
- filesize: u64,
+ filesize: u64 = 0,
/// maximum VM protection
- maxprot: vm_prot_t,
+ maxprot: vm_prot_t = VM_PROT_NONE,
/// initial VM protection
- initprot: vm_prot_t,
+ initprot: vm_prot_t = VM_PROT_NONE,
/// number of sections in segment
- nsects: u32,
- flags: u32,
+ nsects: u32 = 0,
+ flags: u32 = 0,
};
/// A segment is made up of zero or more sections. Non-MH_OBJECT files have
@@ -700,34 +700,34 @@ pub const section_64 = extern struct {
segname: [16]u8,
/// memory address of this section
- addr: u64,
+ addr: u64 = 0,
/// size in bytes of this section
- size: u64,
+ size: u64 = 0,
/// file offset of this section
- offset: u32,
+ offset: u32 = 0,
/// section alignment (power of 2)
- @"align": u32,
+ @"align": u32 = 0,
/// file offset of relocation entries
- reloff: u32,
+ reloff: u32 = 0,
/// number of relocation entries
- nreloc: u32,
+ nreloc: u32 = 0,
/// flags (section type and attributes
- flags: u32,
+ flags: u32 = S_REGULAR,
/// reserved (for offset or index)
- reserved1: u32,
+ reserved1: u32 = 0,
/// reserved (for count or sizeof)
- reserved2: u32,
+ reserved2: u32 = 0,
/// reserved
- reserved3: u32,
+ reserved3: u32 = 0,
};
pub const nlist = extern struct {
src/link/MachO/commands.zig
@@ -9,6 +9,7 @@ const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const MachO = @import("../MachO.zig");
+const makeStaticString = MachO.makeStaticString;
const padToIdeal = MachO.padToIdeal;
pub const HeaderArgs = struct {
@@ -217,75 +218,6 @@ pub const SegmentCommand = struct {
inner: macho.segment_command_64,
sections: std.ArrayListUnmanaged(macho.section_64) = .{},
- const SegmentOptions = struct {
- cmdsize: u32 = @sizeOf(macho.segment_command_64),
- vmaddr: u64 = 0,
- vmsize: u64 = 0,
- fileoff: u64 = 0,
- filesize: u64 = 0,
- maxprot: macho.vm_prot_t = macho.VM_PROT_NONE,
- initprot: macho.vm_prot_t = macho.VM_PROT_NONE,
- nsects: u32 = 0,
- flags: u32 = 0,
- };
-
- pub fn empty(comptime segname: []const u8, opts: SegmentOptions) SegmentCommand {
- return .{
- .inner = .{
- .cmd = macho.LC_SEGMENT_64,
- .cmdsize = opts.cmdsize,
- .segname = makeStaticString(segname),
- .vmaddr = opts.vmaddr,
- .vmsize = opts.vmsize,
- .fileoff = opts.fileoff,
- .filesize = opts.filesize,
- .maxprot = opts.maxprot,
- .initprot = opts.initprot,
- .nsects = opts.nsects,
- .flags = opts.flags,
- },
- };
- }
-
- const SectionOptions = struct {
- addr: u64 = 0,
- size: u64 = 0,
- offset: u32 = 0,
- @"align": u32 = 0,
- reloff: u32 = 0,
- nreloc: u32 = 0,
- flags: u32 = macho.S_REGULAR,
- reserved1: u32 = 0,
- reserved2: u32 = 0,
- reserved3: u32 = 0,
- };
-
- pub fn addSection(
- self: *SegmentCommand,
- alloc: *Allocator,
- comptime sectname: []const u8,
- opts: SectionOptions,
- ) !void {
- var section = macho.section_64{
- .sectname = makeStaticString(sectname),
- .segname = undefined,
- .addr = opts.addr,
- .size = opts.size,
- .offset = opts.offset,
- .@"align" = opts.@"align",
- .reloff = opts.reloff,
- .nreloc = opts.nreloc,
- .flags = opts.flags,
- .reserved1 = opts.reserved1,
- .reserved2 = opts.reserved2,
- .reserved3 = opts.reserved3,
- };
- mem.copy(u8, §ion.segname, &self.inner.segname);
- try self.sections.append(alloc, section);
- self.inner.cmdsize += @sizeOf(macho.section_64);
- self.inner.nsects += 1;
- }
-
pub fn read(alloc: *Allocator, reader: anytype) !SegmentCommand {
const inner = try reader.readStruct(macho.segment_command_64);
var segment = SegmentCommand{
@@ -427,13 +359,6 @@ pub fn createLoadDylibCommand(
return dylib_cmd;
}
-fn makeStaticString(bytes: []const u8) [16]u8 {
- var buf = [_]u8{0} ** 16;
- assert(bytes.len <= buf.len);
- mem.copy(u8, &buf, bytes);
- return buf;
-}
-
fn parseName(name: *const [16]u8) []const u8 {
const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len;
return name[0..len];
@@ -513,34 +438,26 @@ test "read-write segment command" {
0x00, 0x00, 0x00, 0x00, // reserved3
};
var cmd = SegmentCommand{
- .inner = .{
- .cmd = macho.LC_SEGMENT_64,
+ .inner = macho.segment_command_64.new(.{
.cmdsize = 152,
.segname = makeStaticString("__TEXT"),
.vmaddr = 4294967296,
.vmsize = 294912,
- .fileoff = 0,
.filesize = 294912,
.maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE,
.initprot = macho.VM_PROT_EXECUTE | macho.VM_PROT_READ,
.nsects = 1,
- .flags = 0,
- },
+ }),
};
- try cmd.sections.append(gpa, .{
+ try cmd.sections.append(gpa, macho.section_64.new(.{
.sectname = makeStaticString("__text"),
.segname = makeStaticString("__TEXT"),
.addr = 4294983680,
.size = 448,
.offset = 16384,
.@"align" = 2,
- .reloff = 0,
- .nreloc = 0,
.flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
- .reserved1 = 0,
- .reserved2 = 0,
- .reserved3 = 0,
- });
+ }));
defer cmd.deinit(gpa);
try testRead(gpa, in_buffer, LoadCommand{ .Segment = cmd });
src/link/MachO/DebugSymbols.zig
@@ -5,23 +5,26 @@ const assert = std.debug.assert;
const fs = std.fs;
const log = std.log.scoped(.dsym);
const macho = std.macho;
+const math = std.math;
const mem = std.mem;
const DW = std.dwarf;
const leb = std.leb;
const Allocator = mem.Allocator;
const build_options = @import("build_options");
+const commands = @import("commands.zig");
const trace = @import("../../tracy.zig").trace;
+const LoadCommand = commands.LoadCommand;
const Module = @import("../../Module.zig");
const Type = @import("../../type.zig").Type;
const link = @import("../../link.zig");
const MachO = @import("../MachO.zig");
-const SrcFn = MachO.SrcFn;
const TextBlock = MachO.TextBlock;
+const SegmentCommand = commands.SegmentCommand;
+const SrcFn = MachO.SrcFn;
+const makeStaticString = MachO.makeStaticString;
const padToIdeal = MachO.padToIdeal;
-usingnamespace @import("commands.zig");
-
const page_size: u16 = 0x1000;
base: *MachO,
@@ -185,105 +188,84 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
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", .{
- .vmaddr = vmaddr,
- .vmsize = needed_size,
- .fileoff = off,
- .filesize = needed_size,
- }),
+ .Segment = .{
+ .inner = .{
+ .segname = makeStaticString("__DWARF"),
+ .vmaddr = vmaddr,
+ .vmsize = needed_size,
+ .fileoff = off,
+ .filesize = needed_size,
+ },
+ },
});
self.load_commands_dirty = true;
}
if (self.debug_str_section_index == null) {
- const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
- self.debug_str_section_index = @intCast(u16, dwarf_segment.sections.items.len);
assert(self.debug_string_table.items.len == 0);
-
- try dwarf_segment.addSection(allocator, "__debug_str", .{
- .addr = dwarf_segment.inner.vmaddr,
- .size = @intCast(u32, self.debug_string_table.items.len),
- .offset = @intCast(u32, dwarf_segment.inner.fileoff),
- .@"align" = 1,
- });
- self.load_commands_dirty = true;
+ self.debug_str_section_index = try self.allocateSection(
+ "__debug_str",
+ @intCast(u32, self.debug_string_table.items.len),
+ 0,
+ );
self.debug_string_table_dirty = true;
}
if (self.debug_info_section_index == null) {
- const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
- self.debug_info_section_index = @intCast(u16, dwarf_segment.sections.items.len);
-
- const file_size_hint = 200;
- const p_align = 1;
- const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
-
- 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,
- .size = file_size_hint,
- .offset = @intCast(u32, off),
- .@"align" = p_align,
- });
- self.load_commands_dirty = true;
+ self.debug_info_section_index = try self.allocateSection("__debug_info", 200, 0);
self.debug_info_header_dirty = true;
}
if (self.debug_abbrev_section_index == null) {
- const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
- self.debug_abbrev_section_index = @intCast(u16, dwarf_segment.sections.items.len);
-
- const file_size_hint = 128;
- const p_align = 1;
- const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
-
- 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,
- .size = file_size_hint,
- .offset = @intCast(u32, off),
- .@"align" = p_align,
- });
- self.load_commands_dirty = true;
+ self.debug_abbrev_section_index = try self.allocateSection("__debug_abbrev", 128, 0);
self.debug_abbrev_section_dirty = true;
}
if (self.debug_aranges_section_index == null) {
- const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
- self.debug_aranges_section_index = @intCast(u16, dwarf_segment.sections.items.len);
-
- const file_size_hint = 160;
- const p_align = 16;
- const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
-
- 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,
- .size = file_size_hint,
- .offset = @intCast(u32, off),
- .@"align" = p_align,
- });
- self.load_commands_dirty = true;
+ self.debug_aranges_section_index = try self.allocateSection("__debug_aranges", 160, 4);
self.debug_aranges_section_dirty = true;
}
if (self.debug_line_section_index == null) {
- const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
- self.debug_line_section_index = @intCast(u16, dwarf_segment.sections.items.len);
+ self.debug_line_section_index = try self.allocateSection("__debug_line", 250, 0);
+ self.debug_line_header_dirty = true;
+ }
+}
- const file_size_hint = 250;
- const p_align = 1;
- const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
+fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignment: u16) !u16 {
+ const seg = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
+ var sect = macho.section_64{
+ .sectname = makeStaticString(sectname),
+ .segname = seg.inner.segname,
+ .size = @intCast(u32, size),
+ .@"align" = alignment,
+ };
+ const alignment_pow_2 = try math.powi(u32, 2, alignment);
+ const off = seg.findFreeSpace(size, alignment_pow_2, null);
- log.debug("found __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
+ assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand
- try dwarf_segment.addSection(allocator, "__debug_line", .{
- .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
- .size = file_size_hint,
- .offset = @intCast(u32, off),
- .@"align" = p_align,
- });
- self.load_commands_dirty = true;
- self.debug_line_header_dirty = true;
- }
+ log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{
+ commands.segmentName(sect),
+ commands.sectionName(sect),
+ off,
+ off + size,
+ });
+
+ sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff;
+ sect.offset = @intCast(u32, off);
+
+ const index = @intCast(u16, seg.sections.items.len);
+ try seg.sections.append(self.base.base.allocator, sect);
+ seg.inner.cmdsize += @sizeOf(macho.section_64);
+ seg.inner.nsects += 1;
+
+ // TODO
+ // const match = MatchingSection{
+ // .seg = segment_id,
+ // .sect = index,
+ // };
+ // _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
+ // try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
+
+ self.load_commands_dirty = true;
+
+ return index;
}
pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Options) !void {
@@ -611,15 +593,18 @@ pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {
}
fn copySegmentCommand(self: *DebugSymbols, allocator: *Allocator, base_cmd: SegmentCommand) !SegmentCommand {
- var cmd = SegmentCommand.empty("", .{
- .cmdsize = base_cmd.inner.cmdsize,
- .vmaddr = base_cmd.inner.vmaddr,
- .vmsize = base_cmd.inner.vmsize,
- .maxprot = base_cmd.inner.maxprot,
- .initprot = base_cmd.inner.initprot,
- .nsects = base_cmd.inner.nsects,
- .flags = base_cmd.inner.flags,
- });
+ var cmd = SegmentCommand{
+ .inner = .{
+ .segname = undefined,
+ .cmdsize = base_cmd.inner.cmdsize,
+ .vmaddr = base_cmd.inner.vmaddr,
+ .vmsize = base_cmd.inner.vmsize,
+ .maxprot = base_cmd.inner.maxprot,
+ .initprot = base_cmd.inner.initprot,
+ .nsects = base_cmd.inner.nsects,
+ .flags = base_cmd.inner.flags,
+ },
+ };
mem.copy(u8, &cmd.inner.segname, &base_cmd.inner.segname);
try cmd.sections.ensureCapacity(allocator, cmd.inner.nsects);
@@ -689,7 +674,7 @@ fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void {
}
fn writeHeader(self: *DebugSymbols) !void {
- var header = emptyHeader(.{
+ var header = commands.emptyHeader(.{
.filetype = macho.MH_DSYM,
});
src/link/MachO.zig
@@ -1133,20 +1133,19 @@ pub const MatchingSection = struct {
};
pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSection {
- const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
- const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
- const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
const segname = commands.segmentName(sect);
const sectname = commands.sectionName(sect);
-
- var needs_allocation = false;
const res: ?MatchingSection = blk: {
switch (commands.sectionType(sect)) {
macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
if (self.text_const_section_index == null) {
- self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__const", .{});
- needs_allocation = true;
+ self.text_const_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__const",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1159,11 +1158,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
// TODO it seems the common values within the sections in objects are deduplicated/merged
// on merging the sections' contents.
if (self.objc_methname_section_index == null) {
- self.objc_methname_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__objc_methname", .{
- .flags = macho.S_CSTRING_LITERALS,
- });
- needs_allocation = true;
+ self.objc_methname_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__objc_methname",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1172,11 +1173,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__objc_methtype")) {
if (self.objc_methtype_section_index == null) {
- self.objc_methtype_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__objc_methtype", .{
- .flags = macho.S_CSTRING_LITERALS,
- });
- needs_allocation = true;
+ self.objc_methtype_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__objc_methtype",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1185,9 +1188,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__objc_classname")) {
if (self.objc_classname_section_index == null) {
- self.objc_classname_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__objc_classname", .{});
- needs_allocation = true;
+ self.objc_classname_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__objc_classname",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1197,11 +1204,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
}
if (self.cstring_section_index == null) {
- self.cstring_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__cstring", .{
- .flags = macho.S_CSTRING_LITERALS,
- });
- needs_allocation = true;
+ self.cstring_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__cstring",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_CSTRING_LITERALS,
+ },
+ );
}
break :blk .{
@@ -1212,29 +1223,37 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
macho.S_LITERAL_POINTERS => {
if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) {
if (self.objc_selrefs_section_index == null) {
- self.objc_selrefs_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__objc_selrefs", .{
- .flags = macho.S_LITERAL_POINTERS,
- });
- needs_allocation = true;
+ self.objc_selrefs_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__objc_selrefs",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_LITERAL_POINTERS,
+ },
+ );
}
break :blk .{
.seg = self.data_segment_cmd_index.?,
.sect = self.objc_selrefs_section_index.?,
};
+ } else {
+ // TODO investigate
+ break :blk null;
}
-
- // TODO investigate
- break :blk null;
},
macho.S_MOD_INIT_FUNC_POINTERS => {
if (self.mod_init_func_section_index == null) {
- self.mod_init_func_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__mod_init_func", .{
- .flags = macho.S_MOD_INIT_FUNC_POINTERS,
- });
- needs_allocation = true;
+ self.mod_init_func_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__mod_init_func",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_MOD_INIT_FUNC_POINTERS,
+ },
+ );
}
break :blk .{
@@ -1244,11 +1263,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
},
macho.S_MOD_TERM_FUNC_POINTERS => {
if (self.mod_term_func_section_index == null) {
- self.mod_term_func_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__mod_term_func", .{
- .flags = macho.S_MOD_TERM_FUNC_POINTERS,
- });
- needs_allocation = true;
+ self.mod_term_func_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__mod_term_func",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_MOD_TERM_FUNC_POINTERS,
+ },
+ );
}
break :blk .{
@@ -1258,11 +1281,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
},
macho.S_ZEROFILL => {
if (self.bss_section_index == null) {
- self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__bss", .{
- .flags = macho.S_ZEROFILL,
- });
- needs_allocation = true;
+ self.bss_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__bss",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_ZEROFILL,
+ },
+ );
}
break :blk .{
@@ -1272,11 +1299,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
},
macho.S_THREAD_LOCAL_VARIABLES => {
if (self.tlv_section_index == null) {
- self.tlv_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__thread_vars", .{
- .flags = macho.S_THREAD_LOCAL_VARIABLES,
- });
- needs_allocation = true;
+ self.tlv_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__thread_vars",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_THREAD_LOCAL_VARIABLES,
+ },
+ );
}
break :blk .{
@@ -1286,11 +1317,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
},
macho.S_THREAD_LOCAL_REGULAR => {
if (self.tlv_data_section_index == null) {
- self.tlv_data_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__thread_data", .{
- .flags = macho.S_THREAD_LOCAL_REGULAR,
- });
- needs_allocation = true;
+ self.tlv_data_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__thread_data",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_THREAD_LOCAL_REGULAR,
+ },
+ );
}
break :blk .{
@@ -1300,11 +1335,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
},
macho.S_THREAD_LOCAL_ZEROFILL => {
if (self.tlv_bss_section_index == null) {
- self.tlv_bss_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__thread_bss", .{
- .flags = macho.S_THREAD_LOCAL_ZEROFILL,
- });
- needs_allocation = true;
+ self.tlv_bss_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__thread_bss",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_THREAD_LOCAL_ZEROFILL,
+ },
+ );
}
break :blk .{
@@ -1317,9 +1356,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
// TODO I believe __eh_frame is currently part of __unwind_info section
// in the latest ld64 output.
if (self.eh_frame_section_index == null) {
- self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__eh_frame", .{});
- needs_allocation = true;
+ self.eh_frame_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__eh_frame",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1330,9 +1373,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
// TODO audit this: is this the right mapping?
if (self.data_const_section_index == null) {
- self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__const", .{});
- needs_allocation = true;
+ self.data_const_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__const",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1343,11 +1390,17 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
macho.S_REGULAR => {
if (commands.sectionIsCode(sect)) {
if (self.text_section_index == null) {
- self.text_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__text", .{
- .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
- });
- needs_allocation = true;
+ self.text_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__text",
+ sect.size,
+ sect.@"align",
+ .{
+ .flags = macho.S_REGULAR |
+ macho.S_ATTR_PURE_INSTRUCTIONS |
+ macho.S_ATTR_SOME_INSTRUCTIONS,
+ },
+ );
}
break :blk .{
@@ -1368,9 +1421,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
if (mem.eql(u8, segname, "__TEXT")) {
if (mem.eql(u8, sectname, "__ustring")) {
if (self.ustring_section_index == null) {
- self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__ustring", .{});
- needs_allocation = true;
+ self.ustring_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__ustring",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1379,9 +1436,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
if (self.gcc_except_tab_section_index == null) {
- self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__gcc_except_tab", .{});
- needs_allocation = true;
+ self.gcc_except_tab_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__gcc_except_tab",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1390,9 +1451,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__objc_methlist")) {
if (self.objc_methlist_section_index == null) {
- self.objc_methlist_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__objc_methlist", .{});
- needs_allocation = true;
+ self.objc_methlist_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__objc_methlist",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1406,9 +1471,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
mem.eql(u8, sectname, "__gopclntab"))
{
if (self.data_const_section_index == null) {
- self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__const", .{});
- needs_allocation = true;
+ self.data_const_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__const",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1417,9 +1486,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else {
if (self.text_const_section_index == null) {
- self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.base.allocator, "__const", .{});
- needs_allocation = true;
+ self.text_const_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__const",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1431,9 +1504,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
if (mem.eql(u8, segname, "__DATA_CONST")) {
if (self.data_const_section_index == null) {
- self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__const", .{});
- needs_allocation = true;
+ self.data_const_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__const",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1445,9 +1522,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
if (mem.eql(u8, segname, "__DATA")) {
if (mem.eql(u8, sectname, "__const")) {
if (self.data_const_section_index == null) {
- self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__const", .{});
- needs_allocation = true;
+ self.data_const_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__const",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1456,9 +1537,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__cfstring")) {
if (self.objc_cfstring_section_index == null) {
- self.objc_cfstring_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__cfstring", .{});
- needs_allocation = true;
+ self.objc_cfstring_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__cfstring",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1467,9 +1552,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__objc_classlist")) {
if (self.objc_classlist_section_index == null) {
- self.objc_classlist_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__objc_classlist", .{});
- needs_allocation = true;
+ self.objc_classlist_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__objc_classlist",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1478,9 +1567,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__objc_imageinfo")) {
if (self.objc_imageinfo_section_index == null) {
- self.objc_imageinfo_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.base.allocator, "__objc_imageinfo", .{});
- needs_allocation = true;
+ self.objc_imageinfo_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__objc_imageinfo",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1489,9 +1582,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__objc_const")) {
if (self.objc_const_section_index == null) {
- self.objc_const_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__objc_const", .{});
- needs_allocation = true;
+ self.objc_const_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__objc_const",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1500,9 +1597,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__objc_classrefs")) {
if (self.objc_classrefs_section_index == null) {
- self.objc_classrefs_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__objc_classrefs", .{});
- needs_allocation = true;
+ self.objc_classrefs_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__objc_classrefs",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1511,9 +1612,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else if (mem.eql(u8, sectname, "__objc_data")) {
if (self.objc_data_section_index == null) {
- self.objc_data_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__objc_data", .{});
- needs_allocation = true;
+ self.objc_data_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__objc_data",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1522,9 +1627,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
};
} else {
if (self.data_section_index == null) {
- self.data_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.base.allocator, "__data", .{});
- needs_allocation = true;
+ self.data_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__data",
+ sect.size,
+ sect.@"align",
+ .{},
+ );
}
break :blk .{
@@ -1545,42 +1654,6 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
else => break :blk null,
}
};
-
- if (res) |match| {
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- _ = try self.block_free_lists.getOrPutValue(self.base.allocator, match, .{});
-
- const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1;
- if (!use_stage1) {
- const target_seg = &self.load_commands.items[match.seg].Segment;
- const target_sect = &target_seg.sections.items[match.sect];
-
- // Update section's alignment
- // TODO if sect.@"align" > target_sect.@"align", should we move the entire
- // section to match the required alignment?
- target_sect.@"align" = math.max(target_sect.@"align", sect.@"align");
-
- if (needs_allocation) {
- const alignment = try math.powi(u32, 2, target_sect.@"align");
- const needed_size = sect.size;
- const off = target_seg.findFreeSpace(needed_size, alignment, self.header_pad);
- assert(off + needed_size <= target_seg.inner.fileoff + target_seg.inner.filesize); // TODO expand
-
- log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{
- segname,
- sectname,
- off,
- off + needed_size,
- });
-
- target_sect.addr = target_seg.inner.vmaddr + off;
- target_sect.size = needed_size;
- target_sect.offset = @intCast(u32, off);
- self.load_commands_dirty = true;
- }
- }
- }
-
return res;
}
@@ -3878,9 +3951,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
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, .{
- .Segment = SegmentCommand.empty("__PAGEZERO", .{
- .vmsize = 0x100000000, // size always set to 4GB
- }),
+ .Segment = .{
+ .inner = .{
+ .segname = makeStaticString("__PAGEZERO"),
+ .vmsize = 0x100000000, // size always set to 4GB
+ },
+ },
});
self.load_commands_dirty = true;
}
@@ -3895,51 +3971,39 @@ pub fn populateMissingMetadata(self: *MachO) !void {
log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });
try self.load_commands.append(self.base.allocator, .{
- .Segment = SegmentCommand.empty("__TEXT", .{
- .vmaddr = 0x100000000, // always starts at 4GB
- .vmsize = needed_size,
- .filesize = needed_size,
- .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
- .initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
- }),
+ .Segment = .{
+ .inner = .{
+ .segname = makeStaticString("__TEXT"),
+ .vmaddr = 0x100000000, // always starts at 4GB
+ .vmsize = needed_size,
+ .filesize = needed_size,
+ .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
+ .initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
+ },
+ },
});
self.load_commands_dirty = true;
}
if (self.text_section_index == null) {
- const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
- self.text_section_index = @intCast(u16, text_segment.sections.items.len);
-
const alignment: u2 = switch (self.base.options.target.cpu.arch) {
.x86_64 => 0,
.aarch64 => 2,
else => unreachable, // unhandled architecture type
};
const needed_size = self.base.options.program_code_size_hint;
- const off = text_segment.findFreeSpace(needed_size, @as(u16, 1) << alignment, self.header_pad);
-
- log.debug("found __text section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
-
- try text_segment.addSection(self.base.allocator, "__text", .{
- .addr = text_segment.inner.vmaddr + off,
- .size = @intCast(u32, needed_size),
- .offset = @intCast(u32, off),
- .@"align" = alignment,
- .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
- });
- const match = MatchingSection{
- .seg = self.text_segment_cmd_index.?,
- .sect = self.text_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ self.text_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__text",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
+ },
+ );
}
if (self.stubs_section_index == null) {
- const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
- self.stubs_section_index = @intCast(u16, text_segment.sections.items.len);
-
const alignment: u2 = switch (self.base.options.target.cpu.arch) {
.x86_64 => 0,
.aarch64 => 2,
@@ -3951,32 +4015,19 @@ pub fn populateMissingMetadata(self: *MachO) !void {
else => unreachable, // unhandled architecture type
};
const needed_size = stub_size * self.base.options.symbol_count_hint;
- const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad);
- assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment.
-
- log.debug("found __stubs section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
-
- try text_segment.addSection(self.base.allocator, "__stubs", .{
- .addr = text_segment.inner.vmaddr + off,
- .size = needed_size,
- .offset = @intCast(u32, off),
- .@"align" = alignment,
- .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
- .reserved2 = stub_size,
- });
- const match = MatchingSection{
- .seg = self.text_segment_cmd_index.?,
- .sect = self.stubs_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ self.stubs_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__stubs",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
+ .reserved2 = stub_size,
+ },
+ );
}
if (self.stub_helper_section_index == null) {
- const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
- self.stub_helper_section_index = @intCast(u16, text_segment.sections.items.len);
-
const alignment: u2 = switch (self.base.options.target.cpu.arch) {
.x86_64 => 0,
.aarch64 => 2,
@@ -3993,25 +4044,15 @@ pub fn populateMissingMetadata(self: *MachO) !void {
else => unreachable,
};
const needed_size = stub_size * self.base.options.symbol_count_hint + preamble_size;
- const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad);
- assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment.
-
- log.debug("found __stub_helper section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
-
- try text_segment.addSection(self.base.allocator, "__stub_helper", .{
- .addr = text_segment.inner.vmaddr + off,
- .size = needed_size,
- .offset = @intCast(u32, off),
- .@"align" = alignment,
- .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
- });
- const match = MatchingSection{
- .seg = self.text_segment_cmd_index.?,
- .sect = self.stub_helper_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ self.stub_helper_section_index = try self.allocateSection(
+ self.text_segment_cmd_index.?,
+ "__stub_helper",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
+ },
+ );
}
if (self.data_const_segment_cmd_index == null) {
@@ -4020,45 +4061,39 @@ pub fn populateMissingMetadata(self: *MachO) !void {
const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
- log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size });
+ log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{
+ address_and_offset.offset,
+ address_and_offset.offset + needed_size,
+ });
try self.load_commands.append(self.base.allocator, .{
- .Segment = SegmentCommand.empty("__DATA_CONST", .{
- .vmaddr = address_and_offset.address,
- .vmsize = needed_size,
- .fileoff = address_and_offset.offset,
- .filesize = needed_size,
- .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
- .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
- }),
+ .Segment = .{
+ .inner = .{
+ .segname = makeStaticString("__DATA_CONST"),
+ .vmaddr = address_and_offset.address,
+ .vmsize = needed_size,
+ .fileoff = address_and_offset.offset,
+ .filesize = needed_size,
+ .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
+ .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
+ },
+ },
});
self.load_commands_dirty = true;
}
if (self.got_section_index == null) {
- const dc_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
- self.got_section_index = @intCast(u16, dc_segment.sections.items.len);
-
const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
- const off = dc_segment.findFreeSpace(needed_size, @alignOf(u64), null);
- assert(off + needed_size <= dc_segment.inner.fileoff + dc_segment.inner.filesize); // TODO Must expand __DATA_CONST segment.
-
- log.debug("found __got section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
-
- try dc_segment.addSection(self.base.allocator, "__got", .{
- .addr = dc_segment.inner.vmaddr + off - dc_segment.inner.fileoff,
- .size = needed_size,
- .offset = @intCast(u32, off),
- .@"align" = 3, // 2^3 = @sizeOf(u64)
- .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
- });
- const match = MatchingSection{
- .seg = self.data_const_segment_cmd_index.?,
- .sect = self.got_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
+ self.got_section_index = try self.allocateSection(
+ self.data_const_segment_cmd_index.?,
+ "__got",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
+ },
+ );
}
if (self.data_segment_cmd_index == null) {
@@ -4070,175 +4105,115 @@ pub fn populateMissingMetadata(self: *MachO) !void {
log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size });
try self.load_commands.append(self.base.allocator, .{
- .Segment = SegmentCommand.empty("__DATA", .{
- .vmaddr = address_and_offset.address,
- .vmsize = needed_size,
- .fileoff = address_and_offset.offset,
- .filesize = needed_size,
- .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
- .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
- }),
+ .Segment = .{
+ .inner = .{
+ .segname = makeStaticString("__DATA"),
+ .vmaddr = address_and_offset.address,
+ .vmsize = needed_size,
+ .fileoff = address_and_offset.offset,
+ .filesize = needed_size,
+ .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
+ .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
+ },
+ },
});
self.load_commands_dirty = true;
}
if (self.la_symbol_ptr_section_index == null) {
- const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- self.la_symbol_ptr_section_index = @intCast(u16, data_segment.sections.items.len);
-
const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
- const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null);
- assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment.
-
- log.debug("found __la_symbol_ptr section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
-
- try data_segment.addSection(self.base.allocator, "__la_symbol_ptr", .{
- .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
- .size = needed_size,
- .offset = @intCast(u32, off),
- .@"align" = 3, // 2^3 = @sizeOf(u64)
- .flags = macho.S_LAZY_SYMBOL_POINTERS,
- });
- const match = MatchingSection{
- .seg = self.data_segment_cmd_index.?,
- .sect = self.la_symbol_ptr_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
+ self.la_symbol_ptr_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__la_symbol_ptr",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_LAZY_SYMBOL_POINTERS,
+ },
+ );
}
if (self.data_section_index == null) {
- const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- self.data_section_index = @intCast(u16, data_segment.sections.items.len);
-
const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
- const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null);
- assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment.
-
- log.debug("found __data section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
-
- try data_segment.addSection(self.base.allocator, "__data", .{
- .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
- .size = needed_size,
- .offset = @intCast(u32, off),
- .@"align" = 3, // 2^3 = @sizeOf(u64)
- });
- const match = MatchingSection{
- .seg = self.data_segment_cmd_index.?,
- .sect = self.data_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
+ self.data_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__data",
+ needed_size,
+ alignment,
+ .{},
+ );
}
if (self.tlv_section_index == null) {
- const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- self.tlv_section_index = @intCast(u16, data_segment.sections.items.len);
-
const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
- const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null);
- assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment.
-
- log.debug("found __thread_vars section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
-
- try data_segment.addSection(self.base.allocator, "__thread_vars", .{
- .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
- .size = needed_size,
- .offset = @intCast(u32, off),
- .@"align" = 3, // 2^3 = @sizeOf(u64)
- .flags = macho.S_THREAD_LOCAL_VARIABLES,
- });
- const match = MatchingSection{
- .seg = self.data_segment_cmd_index.?,
- .sect = self.tlv_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
+ self.tlv_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__thread_vars",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_THREAD_LOCAL_VARIABLES,
+ },
+ );
}
if (self.tlv_data_section_index == null) {
- const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- self.tlv_data_section_index = @intCast(u16, data_segment.sections.items.len);
-
const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
- const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null);
- assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment.
-
- log.debug("found __thread_data section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
-
- try data_segment.addSection(self.base.allocator, "__thread_data", .{
- .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
- .size = needed_size,
- .offset = @intCast(u32, off),
- .@"align" = 3, // 2^3 = @sizeOf(u64)
- .flags = macho.S_THREAD_LOCAL_REGULAR,
- });
- const match = MatchingSection{
- .seg = self.data_segment_cmd_index.?,
- .sect = self.tlv_data_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
+ self.tlv_data_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__thread_data",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_THREAD_LOCAL_REGULAR,
+ },
+ );
}
if (self.tlv_bss_section_index == null) {
- const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- self.tlv_bss_section_index = @intCast(u16, data_segment.sections.items.len);
-
const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
- const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null);
- assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment.
-
- log.debug("found __thread_bss section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
+ const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
+ self.tlv_bss_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__thread_bss",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_THREAD_LOCAL_ZEROFILL,
+ },
+ );
// We keep offset to the section in a separate variable as the actual section is usually pointing at the
// beginning of the file.
- self.tlv_bss_file_offset = off;
- try data_segment.addSection(self.base.allocator, "__thread_bss", .{
- .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
- .size = needed_size,
- .@"align" = 3, // 2^3 = @sizeOf(u64)
- .flags = macho.S_THREAD_LOCAL_ZEROFILL,
- });
- const match = MatchingSection{
- .seg = self.data_segment_cmd_index.?,
- .sect = self.tlv_bss_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
+ const out_sect = &seg.sections.items[self.tlv_bss_section_index.?];
+ self.tlv_bss_file_offset = out_sect.offset;
+ out_sect.offset = 0;
}
if (self.bss_section_index == null) {
- const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
- self.bss_section_index = @intCast(u16, data_segment.sections.items.len);
-
const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
- const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null);
- assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment.
-
- log.debug("found __bss section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
+ const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
+ self.bss_section_index = try self.allocateSection(
+ self.data_segment_cmd_index.?,
+ "__bss",
+ needed_size,
+ alignment,
+ .{
+ .flags = macho.S_ZEROFILL,
+ },
+ );
// We keep offset to the section in a separate variable as the actual section is usually pointing at the
// beginning of the file.
- self.bss_file_offset = off;
- try data_segment.addSection(self.base.allocator, "__bss", .{
- .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
- .size = 0,
- .@"align" = 3, // 2^3 = @sizeOf(u64)
- .flags = macho.S_ZEROFILL,
- });
- const match = MatchingSection{
- .seg = self.data_segment_cmd_index.?,
- .sect = self.bss_section_index.?,
- };
- _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
- try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
- self.load_commands_dirty = true;
+ const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
+ const out_sect = &seg.sections.items[self.bss_section_index.?];
+ self.bss_file_offset = out_sect.offset;
+ out_sect.offset = 0;
}
if (self.linkedit_segment_cmd_index == null) {
@@ -4248,12 +4223,15 @@ pub fn populateMissingMetadata(self: *MachO) !void {
log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset});
try self.load_commands.append(self.base.allocator, .{
- .Segment = SegmentCommand.empty("__LINKEDIT", .{
- .vmaddr = address_and_offset.address,
- .fileoff = address_and_offset.offset,
- .maxprot = macho.VM_PROT_READ,
- .initprot = macho.VM_PROT_READ,
- }),
+ .Segment = .{
+ .inner = .{
+ .segname = makeStaticString("__LINKEDIT"),
+ .vmaddr = address_and_offset.address,
+ .fileoff = address_and_offset.offset,
+ .maxprot = macho.VM_PROT_READ,
+ .initprot = macho.VM_PROT_READ,
+ },
+ },
});
self.load_commands_dirty = true;
}
@@ -4485,6 +4463,67 @@ pub fn populateMissingMetadata(self: *MachO) !void {
}
}
+const AllocateSectionOpts = struct {
+ flags: u32 = macho.S_REGULAR,
+ reserved1: u32 = 0,
+ reserved2: u32 = 0,
+};
+
+fn allocateSection(
+ self: *MachO,
+ segment_id: u16,
+ sectname: []const u8,
+ size: u64,
+ alignment: u32,
+ opts: AllocateSectionOpts,
+) !u16 {
+ const seg = &self.load_commands.items[segment_id].Segment;
+ var sect = macho.section_64{
+ .sectname = makeStaticString(sectname),
+ .segname = seg.inner.segname,
+ .size = @intCast(u32, size),
+ .@"align" = alignment,
+ .flags = opts.flags,
+ .reserved1 = opts.reserved1,
+ .reserved2 = opts.reserved2,
+ };
+
+ const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1;
+ if (!use_stage1) {
+ const alignment_pow_2 = try math.powi(u32, 2, alignment);
+ const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null;
+ const off = seg.findFreeSpace(size, alignment_pow_2, padding);
+
+ assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand
+
+ log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{
+ commands.segmentName(sect),
+ commands.sectionName(sect),
+ off,
+ off + size,
+ });
+
+ sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff;
+ sect.offset = @intCast(u32, off);
+ }
+
+ const index = @intCast(u16, seg.sections.items.len);
+ try seg.sections.append(self.base.allocator, sect);
+ seg.inner.cmdsize += @sizeOf(macho.section_64);
+ seg.inner.nsects += 1;
+
+ const match = MatchingSection{
+ .seg = segment_id,
+ .sect = index,
+ };
+ _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
+ try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
+
+ self.load_commands_dirty = true;
+
+ return index;
+}
+
fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
const text_section = &text_segment.sections.items[self.text_section_index.?];
@@ -5513,6 +5552,13 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
std.math.maxInt(@TypeOf(actual_size));
}
+pub fn makeStaticString(bytes: []const u8) [16]u8 {
+ var buf = [_]u8{0} ** 16;
+ assert(bytes.len <= buf.len);
+ mem.copy(u8, &buf, bytes);
+ return buf;
+}
+
pub fn makeString(self: *MachO, string: []const u8) !u32 {
if (self.strtab_dir.getAdapted(@as([]const u8, string), StringSliceAdapter{ .strtab = &self.strtab })) |off| {
log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off });