macho: cleanup output section selection logic

Cache only section indexes used by the linker for synthetic sections
and/or incremental codepath.
This commit is contained in:
Jakub Konka
2022-08-01 18:42:18 +02:00
parent bb532584bc
commit 7bba3d330a
2 changed files with 157 additions and 480 deletions

View File

@@ -121,48 +121,12 @@ data_const_segment_cmd_index: ?u8 = null,
data_segment_cmd_index: ?u8 = null,
linkedit_segment_cmd_index: ?u8 = null,
// __TEXT segment sections
text_section_index: ?u8 = null,
stubs_section_index: ?u8 = null,
stub_helper_section_index: ?u8 = null,
text_const_section_index: ?u8 = null,
cstring_section_index: ?u8 = null,
ustring_section_index: ?u8 = null,
gcc_except_tab_section_index: ?u8 = null,
unwind_info_section_index: ?u8 = null,
eh_frame_section_index: ?u8 = null,
objc_methlist_section_index: ?u8 = null,
objc_methname_section_index: ?u8 = null,
objc_methtype_section_index: ?u8 = null,
objc_classname_section_index: ?u8 = null,
// __DATA_CONST segment sections
got_section_index: ?u8 = null,
mod_init_func_section_index: ?u8 = null,
mod_term_func_section_index: ?u8 = null,
data_const_section_index: ?u8 = null,
objc_cfstring_section_index: ?u8 = null,
objc_classlist_section_index: ?u8 = null,
objc_imageinfo_section_index: ?u8 = null,
// __DATA segment sections
tlv_section_index: ?u8 = null,
tlv_data_section_index: ?u8 = null,
tlv_bss_section_index: ?u8 = null,
tlv_ptrs_section_index: ?u8 = null,
la_symbol_ptr_section_index: ?u8 = null,
data_section_index: ?u8 = null,
bss_section_index: ?u8 = null,
objc_const_section_index: ?u8 = null,
objc_selrefs_section_index: ?u8 = null,
objc_classrefs_section_index: ?u8 = null,
objc_data_section_index: ?u8 = null,
rustc_section_index: ?u8 = null,
rustc_section_size: u64 = 0,
locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},
@@ -547,14 +511,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
try self.createMhExecuteHeaderSymbol();
try self.resolveDyldStubBinder();
try self.createDyldPrivateAtom();
try self.createStubHelperPreambleAtom();
try self.resolveSymbolsInDylibs();
if (self.unresolved.count() > 0) {
return error.UndefinedSymbolReference;
}
try self.createDyldPrivateAtom();
try self.createStubHelperPreambleAtom();
try self.allocateSpecialSymbols();
if (build_options.enable_logging) {
@@ -1140,7 +1105,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
try self.resolveSymbolsInArchives();
try self.resolveDyldStubBinder();
try self.createDyldPrivateAtom();
try self.resolveSymbolsInDylibs();
try self.createMhExecuteHeaderSymbol();
try self.createDsoHandleSymbol();
@@ -1160,8 +1124,9 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
try object.scanInputSections(self);
}
try self.createStubHelperPreambleAtom();
try self.createDyldPrivateAtom();
try self.createTentativeDefAtoms();
try self.createStubHelperPreambleAtom();
for (self.objects.items) |*object, object_id| {
try object.splitIntoAtomsOneShot(self, @intCast(u32, object_id));
@@ -1184,11 +1149,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
try self.writeAtomsOneShot();
if (self.rustc_section_index) |id| {
const header = &self.sections.items(.header)[id];
header.size = self.rustc_section_size;
}
var lc_buffer = std.ArrayList(u8).init(arena);
const lc_writer = lc_buffer.writer();
var ncmds: u32 = 0;
@@ -1696,417 +1656,142 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
const segname = sect.segName();
const sectname = sect.sectName();
const res: ?u8 = blk: {
if (mem.eql(u8, "__LLVM", segname)) {
log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{
sect.flags, segname, sectname,
});
break :blk null;
}
if (sect.isCode()) {
if (self.text_section_index == null) {
self.text_section_index = try self.initSection(
"__TEXT",
"__text",
sect.size,
sect.@"align",
.{
.flags = macho.S_REGULAR |
macho.S_ATTR_PURE_INSTRUCTIONS |
macho.S_ATTR_SOME_INSTRUCTIONS,
},
);
}
break :blk self.text_section_index.?;
}
if (sect.isDebug()) {
// TODO debug attributes
if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
sect.flags, segname, sectname,
});
}
break :blk null;
}
switch (sect.@"type"()) {
macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
if (self.text_const_section_index == null) {
self.text_const_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__const",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.text_const_section_index.?;
macho.S_4BYTE_LITERALS,
macho.S_8BYTE_LITERALS,
macho.S_16BYTE_LITERALS,
=> {
break :blk self.getSectionByName("__TEXT", "__const") orelse try self.initSection(
"__TEXT",
"__const",
sect.size,
sect.@"align",
.{},
);
},
macho.S_CSTRING_LITERALS => {
if (mem.eql(u8, sectname, "__objc_methname")) {
// 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 = try self.initSection(
self.text_segment_cmd_index.?,
"__objc_methname",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_methname_section_index.?;
} else if (mem.eql(u8, sectname, "__objc_methtype")) {
if (self.objc_methtype_section_index == null) {
self.objc_methtype_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__objc_methtype",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_methtype_section_index.?;
} else if (mem.eql(u8, sectname, "__objc_classname")) {
if (self.objc_classname_section_index == null) {
self.objc_classname_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__objc_classname",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_classname_section_index.?;
}
if (self.cstring_section_index == null) {
self.cstring_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__cstring",
sect.size,
sect.@"align",
.{
.flags = macho.S_CSTRING_LITERALS,
},
);
}
break :blk self.cstring_section_index.?;
},
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 = try self.initSection(
self.data_segment_cmd_index.?,
"__objc_selrefs",
sect.size,
sect.@"align",
.{
.flags = macho.S_LITERAL_POINTERS,
},
);
}
break :blk self.objc_selrefs_section_index.?;
} else {
// 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 = try self.initSection(
self.data_const_segment_cmd_index.?,
"__mod_init_func",
sect.size,
sect.@"align",
.{
.flags = macho.S_MOD_INIT_FUNC_POINTERS,
},
);
}
break :blk self.mod_init_func_section_index.?;
},
macho.S_MOD_TERM_FUNC_POINTERS => {
if (self.mod_term_func_section_index == null) {
self.mod_term_func_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
"__mod_term_func",
sect.size,
sect.@"align",
.{
.flags = macho.S_MOD_TERM_FUNC_POINTERS,
},
);
}
break :blk self.mod_term_func_section_index.?;
},
macho.S_ZEROFILL => {
if (self.bss_section_index == null) {
self.bss_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__bss",
sect.size,
sect.@"align",
.{
.flags = macho.S_ZEROFILL,
},
);
}
break :blk self.bss_section_index.?;
},
macho.S_THREAD_LOCAL_VARIABLES => {
if (self.tlv_section_index == null) {
self.tlv_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__thread_vars",
sect.size,
sect.@"align",
.{
.flags = macho.S_THREAD_LOCAL_VARIABLES,
},
);
}
break :blk self.tlv_section_index.?;
},
macho.S_THREAD_LOCAL_VARIABLE_POINTERS => {
if (self.tlv_ptrs_section_index == null) {
self.tlv_ptrs_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__thread_ptrs",
sect.size,
sect.@"align",
.{
.flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
},
);
}
break :blk self.tlv_ptrs_section_index.?;
},
macho.S_THREAD_LOCAL_REGULAR => {
if (self.tlv_data_section_index == null) {
self.tlv_data_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__thread_data",
sect.size,
sect.@"align",
.{
.flags = macho.S_THREAD_LOCAL_REGULAR,
},
);
}
break :blk self.tlv_data_section_index.?;
},
macho.S_THREAD_LOCAL_ZEROFILL => {
if (self.tlv_bss_section_index == null) {
self.tlv_bss_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__thread_bss",
sect.size,
sect.@"align",
.{
.flags = macho.S_THREAD_LOCAL_ZEROFILL,
},
);
}
break :blk self.tlv_bss_section_index.?;
},
macho.S_COALESCED => {
if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
// 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 = try self.initSection(
self.text_segment_cmd_index.?,
"__eh_frame",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.eh_frame_section_index.?;
}
// TODO audit this: is this the right mapping?
if (self.data_const_section_index == null) {
self.data_const_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
"__const",
if (mem.startsWith(u8, sectname, "__objc")) {
break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
segname,
sectname,
sect.size,
sect.@"align",
.{},
);
}
break :blk self.data_const_section_index.?;
break :blk self.getSectionByName("__TEXT", "__cstring") orelse try self.initSection(
"__TEXT",
"__cstring",
sect.size,
sect.@"align",
.{ .flags = macho.S_CSTRING_LITERALS },
);
},
macho.S_MOD_INIT_FUNC_POINTERS,
macho.S_MOD_TERM_FUNC_POINTERS,
=> {
break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection(
"__DATA_CONST",
sectname,
sect.size,
sect.@"align",
.{ .flags = sect.flags },
);
},
macho.S_LITERAL_POINTERS,
macho.S_ZEROFILL,
macho.S_THREAD_LOCAL_VARIABLES,
macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
macho.S_THREAD_LOCAL_REGULAR,
macho.S_THREAD_LOCAL_ZEROFILL,
=> {
break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
segname,
sectname,
sect.size,
sect.@"align",
.{ .flags = sect.flags },
);
},
macho.S_COALESCED => {
break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
segname,
sectname,
sect.size,
sect.@"align",
.{},
);
},
macho.S_REGULAR => {
if (sect.isCode()) {
if (self.text_section_index == null) {
self.text_section_index = try self.initSection(
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 self.text_section_index.?;
}
if (sect.isDebug()) {
// TODO debug attributes
if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
sect.flags, segname, sectname,
});
}
break :blk null;
}
if (mem.eql(u8, segname, "__TEXT")) {
if (mem.eql(u8, sectname, "__ustring")) {
if (self.ustring_section_index == null) {
self.ustring_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__ustring",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.ustring_section_index.?;
} else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
if (self.gcc_except_tab_section_index == null) {
self.gcc_except_tab_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__gcc_except_tab",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.gcc_except_tab_section_index.?;
} else if (mem.eql(u8, sectname, "__objc_methlist")) {
if (self.objc_methlist_section_index == null) {
self.objc_methlist_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__objc_methlist",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_methlist_section_index.?;
} else if (mem.eql(u8, sectname, "__rodata") or
if (mem.eql(u8, sectname, "__rodata") or
mem.eql(u8, sectname, "__typelink") or
mem.eql(u8, sectname, "__itablink") or
mem.eql(u8, sectname, "__gosymtab") or
mem.eql(u8, sectname, "__gopclntab"))
{
if (self.data_const_section_index == null) {
self.data_const_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
"__const",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.data_const_section_index.?;
} else {
if (self.text_const_section_index == null) {
self.text_const_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__const",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.text_const_section_index.?;
}
}
if (mem.eql(u8, segname, "__DATA_CONST")) {
if (self.data_const_section_index == null) {
self.data_const_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
break :blk self.getSectionByName("__DATA_CONST", "__const") orelse try self.initSection(
"__DATA_CONST",
"__const",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.data_const_section_index.?;
}
if (mem.eql(u8, segname, "__DATA")) {
if (mem.eql(u8, sectname, "__const")) {
if (self.data_const_section_index == null) {
self.data_const_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
"__const",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.data_const_section_index.?;
} else if (mem.eql(u8, sectname, "__cfstring")) {
if (self.objc_cfstring_section_index == null) {
self.objc_cfstring_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
"__cfstring",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_cfstring_section_index.?;
} else if (mem.eql(u8, sectname, "__objc_classlist")) {
if (self.objc_classlist_section_index == null) {
self.objc_classlist_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
"__objc_classlist",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_classlist_section_index.?;
} else if (mem.eql(u8, sectname, "__objc_imageinfo")) {
if (self.objc_imageinfo_section_index == null) {
self.objc_imageinfo_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
"__objc_imageinfo",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_imageinfo_section_index.?;
} else if (mem.eql(u8, sectname, "__objc_const")) {
if (self.objc_const_section_index == null) {
self.objc_const_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__objc_const",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_const_section_index.?;
} else if (mem.eql(u8, sectname, "__objc_classrefs")) {
if (self.objc_classrefs_section_index == null) {
self.objc_classrefs_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__objc_classrefs",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_classrefs_section_index.?;
} else if (mem.eql(u8, sectname, "__objc_data")) {
if (self.objc_data_section_index == null) {
self.objc_data_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__objc_data",
sect.size,
sect.@"align",
.{},
);
}
break :blk self.objc_data_section_index.?;
} else if (mem.eql(u8, sectname, ".rustc")) {
if (self.rustc_section_index == null) {
self.rustc_section_index = try self.initSection(
self.data_segment_cmd_index.?,
".rustc",
sect.size,
sect.@"align",
.{},
);
// We need to preserve the section size for rustc to properly
// decompress the metadata.
self.rustc_section_size = sect.size;
}
break :blk self.rustc_section_index.?;
} else {
if (mem.eql(u8, sectname, "__const") or
mem.eql(u8, sectname, "__cfstring") or
mem.eql(u8, sectname, "__objc_classlist") or
mem.eql(u8, sectname, "__objc_imageinfo"))
{
break :blk self.getSectionByName("__DATA_CONST", sectname) orelse
try self.initSection(
"__DATA_CONST",
sectname,
sect.size,
sect.@"align",
.{},
);
} else if (mem.eql(u8, sectname, "__data")) {
if (self.data_section_index == null) {
self.data_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__data",
segname,
sectname,
sect.size,
sect.@"align",
.{},
@@ -2115,14 +1800,13 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
break :blk self.data_section_index.?;
}
}
if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {
log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{
sect.flags, segname, sectname,
});
}
break :blk null;
break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
segname,
sectname,
sect.size,
sect.@"align",
.{},
);
},
else => break :blk null,
}
@@ -2774,11 +2458,16 @@ fn createTentativeDefAtoms(self: *MachO) !void {
// text blocks for each tentative definition.
const size = sym.n_value;
const alignment = (sym.n_desc >> 8) & 0x0f;
const n_sect = (try self.getOutputSection(.{
.segname = makeStaticString("__DATA"),
.sectname = makeStaticString("__bss"),
.flags = macho.S_ZEROFILL,
})).?;
sym.* = .{
.n_strx = sym.n_strx,
.n_type = macho.N_SECT | macho.N_EXT,
.n_sect = 0,
.n_sect = n_sect,
.n_desc = 0,
.n_value = 0,
};
@@ -2786,7 +2475,7 @@ fn createTentativeDefAtoms(self: *MachO) !void {
const atom = try MachO.createEmptyAtom(gpa, global.sym_index, size, alignment);
atom.file = global.file;
try self.allocateAtomCommon(atom, self.bss_section_index.?);
try self.allocateAtomCommon(atom, n_sect);
if (global.file) |file| {
const object = &self.objects.items[file];
@@ -4174,7 +3863,8 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {
const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
for (unnamed_consts.items) |atom| {
self.freeAtom(atom, self.text_const_section_index.?, true);
const sect_id = atom.getSymbol(self).n_sect;
self.freeAtom(atom, sect_id, true);
self.locals_free_list.append(self.base.allocator, atom.sym_index) catch {};
self.locals.items[atom.sym_index].n_type = 0;
_ = self.atom_by_index_table.remove(atom.sym_index);
@@ -4307,7 +3997,7 @@ fn populateMissingMetadata(self: *MachO) !void {
};
const needed_size = if (self.mode == .incremental) self.base.options.program_code_size_hint else 0;
self.text_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__TEXT",
"__text",
needed_size,
alignment,
@@ -4330,7 +4020,7 @@ fn populateMissingMetadata(self: *MachO) !void {
};
const needed_size = if (self.mode == .incremental) stub_size * self.base.options.symbol_count_hint else 0;
self.stubs_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__TEXT",
"__stubs",
needed_size,
alignment,
@@ -4362,7 +4052,7 @@ fn populateMissingMetadata(self: *MachO) !void {
else
0;
self.stub_helper_section_index = try self.initSection(
self.text_segment_cmd_index.?,
"__TEXT",
"__stub_helper",
needed_size,
alignment,
@@ -4407,7 +4097,7 @@ fn populateMissingMetadata(self: *MachO) !void {
0;
const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
self.got_section_index = try self.initSection(
self.data_const_segment_cmd_index.?,
"__DATA_CONST",
"__got",
needed_size,
alignment,
@@ -4452,7 +4142,7 @@ fn populateMissingMetadata(self: *MachO) !void {
0;
const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
self.la_symbol_ptr_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__DATA",
"__la_symbol_ptr",
needed_size,
alignment,
@@ -4469,7 +4159,7 @@ fn populateMissingMetadata(self: *MachO) !void {
0;
const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
self.data_section_index = try self.initSection(
self.data_segment_cmd_index.?,
"__DATA",
"__data",
needed_size,
alignment,
@@ -4701,12 +4391,13 @@ const InitSectionOpts = struct {
fn initSection(
self: *MachO,
segment_id: u8,
segname: []const u8,
sectname: []const u8,
size: u64,
alignment: u32,
opts: InitSectionOpts,
) !u8 {
const segment_id = self.getSegmentByName(segname).?;
const seg = &self.segments.items[segment_id];
const index = try self.insertSection(segment_id, .{
.sectname = makeStaticString(sectname),
@@ -4779,42 +4470,13 @@ fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8
header.sectName(),
insertion_index,
});
// TODO slim it down
for (&[_]*?u8{
// __TEXT
&self.text_section_index,
&self.stubs_section_index,
&self.stub_helper_section_index,
&self.gcc_except_tab_section_index,
&self.cstring_section_index,
&self.ustring_section_index,
&self.text_const_section_index,
&self.objc_methlist_section_index,
&self.objc_methname_section_index,
&self.objc_methtype_section_index,
&self.objc_classname_section_index,
&self.eh_frame_section_index,
// __DATA_CONST
&self.got_section_index,
&self.mod_init_func_section_index,
&self.mod_term_func_section_index,
&self.data_const_section_index,
&self.objc_cfstring_section_index,
&self.objc_classlist_section_index,
&self.objc_imageinfo_section_index,
// __DATA
&self.rustc_section_index,
&self.la_symbol_ptr_section_index,
&self.objc_const_section_index,
&self.objc_selrefs_section_index,
&self.objc_classrefs_section_index,
&self.objc_data_section_index,
&self.data_section_index,
&self.tlv_section_index,
&self.tlv_ptrs_section_index,
&self.tlv_data_section_index,
&self.tlv_bss_section_index,
&self.bss_section_index,
}) |maybe_index| {
const index = maybe_index.* orelse continue;
if (insertion_index <= index) maybe_index.* = index + 1;
@@ -6017,7 +5679,7 @@ fn writeHeader(self: *MachO, ncmds: u32, sizeofcmds: u32) !void {
else => unreachable,
}
if (self.tlv_section_index) |_| {
if (self.getSectionByName("__DATA", "__thread_vars")) |_| {
header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
}
@@ -6042,6 +5704,20 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
return buf;
}
fn getSegmentByName(self: MachO, segname: []const u8) ?u8 {
for (self.segments.items) |seg, i| {
if (mem.eql(u8, segname, seg.segName())) return @intCast(u8, i);
} else return null;
}
pub fn getSectionByName(self: MachO, segname: []const u8, sectname: []const u8) ?u8 {
// TODO investigate caching with a hashmap
for (self.sections.items(.header)) |header, i| {
if (mem.eql(u8, header.segName(), segname) and mem.eql(u8, header.sectName(), sectname))
return @intCast(u8, i);
} else return null;
}
fn getSectionIndexes(self: MachO, segment_index: u8) struct { start: u8, end: u8 } {
var start: u8 = 0;
const nsects = for (self.segments.items) |seg, i| {

View File

@@ -529,6 +529,7 @@ fn addStub(target: MachO.SymbolWithLoc, context: RelocContext) !void {
if (context.macho_file.stubs_table.contains(target)) return;
const stub_index = try context.macho_file.allocateStubEntry(target);
const stub_helper_atom = try context.macho_file.createStubHelperAtom();
const laptr_atom = try context.macho_file.createLazyPointerAtom(stub_helper_atom.sym_index, target);
const stub_atom = try context.macho_file.createStubAtom(laptr_atom.sym_index);
@@ -601,9 +602,9 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
// * wrt to __thread_data if defined, then
// * wrt to __thread_bss
const sect_id: u16 = sect_id: {
if (macho_file.tlv_data_section_index) |i| {
if (macho_file.getSectionByName("__DATA", "__thread_data")) |i| {
break :sect_id i;
} else if (macho_file.tlv_bss_section_index) |i| {
} else if (macho_file.getSectionByName("__DATA", "__thread_bss")) |i| {
break :sect_id i;
} else {
log.err("threadlocal variables present but no initializer sections found", .{});