authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-24 13:49:03+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
log5750620715bde214778546d2adc6db5fdfad5588
tree02aaa9cde4c8abcb1be09ca363079ca9cb42d0d4
parent04e93dd26572e8d1d69c0f714a6eb06b9435f771

macho: use TableSection for TLV pointer entries in zld driver


2 files changed, 75 insertions(+), 123 deletions(-)

src/link/MachO/Atom.zig+34-29
...@@ -360,7 +360,6 @@ pub fn parseRelocTarget(zld: *Zld, ctx: struct {...@@ -360,7 +360,6 @@ pub fn parseRelocTarget(zld: *Zld, ctx: struct {
360360
361pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc) ?Index {361pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc) ?Index {
362 if (zld.getStubsAtomIndexForSymbol(target)) |stubs_atom| return stubs_atom;362 if (zld.getStubsAtomIndexForSymbol(target)) |stubs_atom| return stubs_atom;
363 if (zld.getTlvPtrAtomIndexForSymbol(target)) |tlv_ptr_atom| return tlv_ptr_atom;
364363
365 if (target.getFile() == null) {364 if (target.getFile() == null) {
366 const target_sym_name = zld.getSymbolName(target);365 const target_sym_name = zld.getSymbolName(target);
...@@ -413,7 +412,8 @@ fn scanAtomRelocsArm64(zld: *Zld, atom_index: Index, relocs: []align(1) const ma...@@ -413,7 +412,8 @@ fn scanAtomRelocsArm64(zld: *Zld, atom_index: Index, relocs: []align(1) const ma
413 .ARM64_RELOC_TLVP_LOAD_PAGE21,412 .ARM64_RELOC_TLVP_LOAD_PAGE21,
414 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12,413 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
415 => {414 => {
416 try addTlvPtrEntry(zld, target);415 const sym = zld.getSymbol(target);
416 if (sym.undf()) try zld.addTlvPtrEntry(target);
417 },417 },
418 else => {},418 else => {},
419 }419 }
...@@ -454,28 +454,14 @@ fn scanAtomRelocsX86(zld: *Zld, atom_index: Index, relocs: []align(1) const mach...@@ -454,28 +454,14 @@ fn scanAtomRelocsX86(zld: *Zld, atom_index: Index, relocs: []align(1) const mach
454 try zld.addGotEntry(target);454 try zld.addGotEntry(target);
455 },455 },
456 .X86_64_RELOC_TLV => {456 .X86_64_RELOC_TLV => {
457 try addTlvPtrEntry(zld, target);457 const sym = zld.getSymbol(target);
458 if (sym.undf()) try zld.addTlvPtrEntry(target);
458 },459 },
459 else => {},460 else => {},
460 }461 }
461 }462 }
462}463}
463464
464fn addTlvPtrEntry(zld: *Zld, target: SymbolWithLoc) !void {
465 const target_sym = zld.getSymbol(target);
466 if (!target_sym.undf()) return;
467 if (zld.tlv_ptr_table.contains(target)) return;
468
469 const gpa = zld.gpa;
470 const atom_index = try zld.createTlvPtrAtom();
471 const tlv_ptr_index = @as(u32, @intCast(zld.tlv_ptr_entries.items.len));
472 try zld.tlv_ptr_entries.append(gpa, .{
473 .target = target,
474 .atom_index = atom_index,
475 });
476 try zld.tlv_ptr_table.putNoClobber(gpa, target, tlv_ptr_index);
477}
478
479pub fn addStub(zld: *Zld, target: SymbolWithLoc) !void {465pub fn addStub(zld: *Zld, target: SymbolWithLoc) !void {
480 const target_sym = zld.getSymbol(target);466 const target_sym = zld.getSymbol(target);
481 if (!target_sym.undf()) return;467 if (!target_sym.undf()) return;
...@@ -641,10 +627,12 @@ fn resolveRelocsArm64(...@@ -641,10 +627,12 @@ fn resolveRelocsArm64(
641 const header = zld.sections.items(.header)[source_sym.n_sect - 1];627 const header = zld.sections.items(.header)[source_sym.n_sect - 1];
642 break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;628 break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;
643 };629 };
644 const target_addr = if (is_via_got)630 const target_addr = blk: {
645 zld.getGotEntryAddress(target).?631 if (is_via_got) break :blk zld.getGotEntryAddress(target).?;
646 else632 if (relocIsTlv(zld, rel) and zld.getSymbol(target).undf())
647 try getRelocTargetAddress(zld, target, is_tlv);633 break :blk zld.getTlvPtrEntryAddress(target).?;
634 break :blk try getRelocTargetAddress(zld, target, is_tlv);
635 };
648636
649 log.debug(" | source_addr = 0x{x}", .{source_addr});637 log.debug(" | source_addr = 0x{x}", .{source_addr});
650638
...@@ -802,7 +790,7 @@ fn resolveRelocsArm64(...@@ -802,7 +790,7 @@ fn resolveRelocsArm64(
802 }790 }
803 };791 };
804792
805 var inst = if (zld.tlv_ptr_table.contains(target)) aarch64.Instruction{793 var inst = if (zld.tlv_ptr_table.lookup.contains(target)) aarch64.Instruction{
806 .load_store_register = .{794 .load_store_register = .{
807 .rt = reg_info.rd,795 .rt = reg_info.rd,
808 .rn = reg_info.rn,796 .rn = reg_info.rn,
...@@ -938,14 +926,15 @@ fn resolveRelocsX86(...@@ -938,14 +926,15 @@ fn resolveRelocsX86(
938 const header = zld.sections.items(.header)[source_sym.n_sect - 1];926 const header = zld.sections.items(.header)[source_sym.n_sect - 1];
939 break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;927 break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;
940 };928 };
929 const target_addr = blk: {
930 if (is_via_got) break :blk zld.getGotEntryAddress(target).?;
931 if (relocIsTlv(zld, rel) and zld.getSymbol(target).undf())
932 break :blk zld.getTlvPtrEntryAddress(target).?;
933 break :blk try getRelocTargetAddress(zld, target, is_tlv);
934 };
941935
942 log.debug(" | source_addr = 0x{x}", .{source_addr});936 log.debug(" | source_addr = 0x{x}", .{source_addr});
943937
944 const target_addr = if (is_via_got)
945 zld.getGotEntryAddress(target).?
946 else
947 try getRelocTargetAddress(zld, target, is_tlv);
948
949 switch (rel_type) {938 switch (rel_type) {
950 .X86_64_RELOC_BRANCH => {939 .X86_64_RELOC_BRANCH => {
951 const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]);940 const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]);
...@@ -971,7 +960,7 @@ fn resolveRelocsX86(...@@ -971,7 +960,7 @@ fn resolveRelocsX86(
971 log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr});960 log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr});
972 const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0);961 const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0);
973962
974 if (zld.tlv_ptr_table.get(target) == null) {963 if (zld.tlv_ptr_table.lookup.get(target) == null) {
975 // We need to rewrite the opcode from movq to leaq.964 // We need to rewrite the opcode from movq to leaq.
976 atom_code[rel_offset - 2] = 0x8d;965 atom_code[rel_offset - 2] = 0x8d;
977 }966 }
...@@ -1112,3 +1101,19 @@ pub fn relocRequiresGot(zld: *Zld, rel: macho.relocation_info) bool {...@@ -1112,3 +1101,19 @@ pub fn relocRequiresGot(zld: *Zld, rel: macho.relocation_info) bool {
1112 else => unreachable,1101 else => unreachable,
1113 }1102 }
1114}1103}
1104
1105pub fn relocIsTlv(zld: *Zld, rel: macho.relocation_info) bool {
1106 switch (zld.options.target.cpu.arch) {
1107 .aarch64 => switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) {
1108 .ARM64_RELOC_TLVP_LOAD_PAGE21,
1109 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
1110 => return true,
1111 else => return false,
1112 },
1113 .x86_64 => switch (@as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type))) {
1114 .X86_64_RELOC_TLV => return true,
1115 else => return false,
1116 },
1117 else => unreachable,
1118 }
1119}
src/link/MachO/zld.zig+41-94
...@@ -68,6 +68,7 @@ pub const Zld = struct {...@@ -68,6 +68,7 @@ pub const Zld = struct {
68 sections: std.MultiArrayList(Section) = .{},68 sections: std.MultiArrayList(Section) = .{},
6969
70 got_section_index: ?u8 = null,70 got_section_index: ?u8 = null,
71 tlv_ptr_section_index: ?u8 = null,
7172
72 locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},73 locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
73 globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},74 globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
...@@ -81,9 +82,7 @@ pub const Zld = struct {...@@ -81,9 +82,7 @@ pub const Zld = struct {
8182
82 strtab: StringTable(.strtab) = .{},83 strtab: StringTable(.strtab) = .{},
8384
84 tlv_ptr_entries: std.ArrayListUnmanaged(IndirectPointer) = .{},85 tlv_ptr_table: TableSection(SymbolWithLoc) = .{},
85 tlv_ptr_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
86
87 got_table: TableSection(SymbolWithLoc) = .{},86 got_table: TableSection(SymbolWithLoc) = .{},
8887
89 stubs: std.ArrayListUnmanaged(IndirectPointer) = .{},88 stubs: std.ArrayListUnmanaged(IndirectPointer) = .{},
...@@ -268,24 +267,6 @@ pub const Zld = struct {...@@ -268,24 +267,6 @@ pub const Zld = struct {
268 return index;267 return index;
269 }268 }
270269
271 pub fn createTlvPtrAtom(self: *Zld) !AtomIndex {
272 const sym_index = try self.allocateSymbol();
273 const atom_index = try self.createEmptyAtom(sym_index, @sizeOf(u64), 3);
274 const sym = self.getSymbolPtr(.{ .sym_index = sym_index });
275 sym.n_type = macho.N_SECT;
276
277 const sect_id = (try self.getOutputSection(.{
278 .segname = makeStaticString("__DATA"),
279 .sectname = makeStaticString("__thread_ptrs"),
280 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
281 })).?;
282 sym.n_sect = sect_id + 1;
283
284 self.addAtomToSection(atom_index);
285
286 return atom_index;
287 }
288
289 fn createDyldStubBinderGotAtom(self: *Zld) !void {270 fn createDyldStubBinderGotAtom(self: *Zld) !void {
290 const global_index = self.dyld_stub_binder_index orelse return;271 const global_index = self.dyld_stub_binder_index orelse return;
291 const target = self.globals.items[global_index];272 const target = self.globals.items[global_index];
...@@ -841,7 +822,6 @@ pub const Zld = struct {...@@ -841,7 +822,6 @@ pub const Zld = struct {
841 pub fn deinit(self: *Zld) void {822 pub fn deinit(self: *Zld) void {
842 const gpa = self.gpa;823 const gpa = self.gpa;
843824
844 self.tlv_ptr_entries.deinit(gpa);
845 self.tlv_ptr_table.deinit(gpa);825 self.tlv_ptr_table.deinit(gpa);
846 self.got_table.deinit(gpa);826 self.got_table.deinit(gpa);
847 self.stubs.deinit(gpa);827 self.stubs.deinit(gpa);
...@@ -959,16 +939,26 @@ pub const Zld = struct {...@@ -959,16 +939,26 @@ pub const Zld = struct {
959 return global_index;939 return global_index;
960 }940 }
961941
962 pub fn addGotEntry(zld: *Zld, target: SymbolWithLoc) !void {942 pub fn addGotEntry(self: *Zld, target: SymbolWithLoc) !void {
963 if (zld.got_table.lookup.contains(target)) return;943 if (self.got_table.lookup.contains(target)) return;
964 _ = try zld.got_table.allocateEntry(zld.gpa, target);944 _ = try self.got_table.allocateEntry(self.gpa, target);
965 if (zld.got_section_index == null) {945 if (self.got_section_index == null) {
966 zld.got_section_index = try zld.initSection("__DATA_CONST", "__got", .{946 self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{
967 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,947 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
968 });948 });
969 }949 }
970 }950 }
971951
952 pub fn addTlvPtrEntry(self: *Zld, target: SymbolWithLoc) !void {
953 if (self.tlv_ptr_table.lookup.contains(target)) return;
954 _ = try self.tlv_ptr_table.allocateEntry(self.gpa, target);
955 if (self.tlv_ptr_section_index == null) {
956 self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{
957 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
958 });
959 }
960 }
961
972 fn allocateSpecialSymbols(self: *Zld) !void {962 fn allocateSpecialSymbols(self: *Zld) !void {
973 for (&[_]?u32{963 for (&[_]?u32{
974 self.dso_handle_index,964 self.dso_handle_index,
...@@ -1033,12 +1023,10 @@ pub const Zld = struct {...@@ -1033,12 +1023,10 @@ pub const Zld = struct {
1033 } else if (atom.getFile() == null) outer: {1023 } else if (atom.getFile() == null) outer: {
1034 switch (header.type()) {1024 switch (header.type()) {
1035 macho.S_NON_LAZY_SYMBOL_POINTERS => unreachable,1025 macho.S_NON_LAZY_SYMBOL_POINTERS => unreachable,
1026 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => unreachable,
1036 macho.S_LAZY_SYMBOL_POINTERS => {1027 macho.S_LAZY_SYMBOL_POINTERS => {
1037 try self.writeLazyPointer(count, buffer.writer());1028 try self.writeLazyPointer(count, buffer.writer());
1038 },1029 },
1039 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => {
1040 buffer.appendSliceAssumeCapacity(&[_]u8{0} ** @sizeOf(u64));
1041 },
1042 else => {1030 else => {
1043 if (self.stub_helper_preamble_sym_index) |sym_index| {1031 if (self.stub_helper_preamble_sym_index) |sym_index| {
1044 if (sym_index == atom.sym_index) {1032 if (sym_index == atom.sym_index) {
...@@ -1087,12 +1075,11 @@ pub const Zld = struct {...@@ -1087,12 +1075,11 @@ pub const Zld = struct {
1087 }1075 }
1088 }1076 }
10891077
1090 fn writeGotEntries(self: *Zld) !void {1078 fn writePointerEntries(self: *Zld, sect_id: u8, table: anytype) !void {
1091 const sect_id = self.got_section_index orelse return;
1092 const header = self.sections.items(.header)[sect_id];1079 const header = self.sections.items(.header)[sect_id];
1093 var buffer = try std.ArrayList(u8).initCapacity(self.gpa, header.size);1080 var buffer = try std.ArrayList(u8).initCapacity(self.gpa, header.size);
1094 defer buffer.deinit();1081 defer buffer.deinit();
1095 for (self.got_table.entries.items) |entry| {1082 for (table.entries.items) |entry| {
1096 const sym = self.getSymbol(entry);1083 const sym = self.getSymbol(entry);
1097 buffer.writer().writeIntLittle(u64, sym.n_value) catch unreachable;1084 buffer.writer().writeIntLittle(u64, sym.n_value) catch unreachable;
1098 }1085 }
...@@ -1147,6 +1134,7 @@ pub const Zld = struct {...@@ -1147,6 +1134,7 @@ pub const Zld = struct {
11471134
1148 for (&[_]*?u8{1135 for (&[_]*?u8{
1149 &self.got_section_index,1136 &self.got_section_index,
1137 &self.tlv_ptr_section_index,
1150 }) |maybe_index| {1138 }) |maybe_index| {
1151 if (maybe_index.*) |*index| {1139 if (maybe_index.*) |*index| {
1152 index.* = backlinks[index.*];1140 index.* = backlinks[index.*];
...@@ -1236,6 +1224,12 @@ pub const Zld = struct {...@@ -1236,6 +1224,12 @@ pub const Zld = struct {
1236 header.size = self.got_table.count() * @sizeOf(u64);1224 header.size = self.got_table.count() * @sizeOf(u64);
1237 header.@"align" = 3;1225 header.@"align" = 3;
1238 }1226 }
1227
1228 if (self.tlv_ptr_section_index) |sect_id| {
1229 const header = &self.sections.items(.header)[sect_id];
1230 header.size = self.tlv_ptr_table.count() * @sizeOf(u64);
1231 header.@"align" = 3;
1232 }
1239 }1233 }
12401234
1241 fn allocateSegments(self: *Zld) !void {1235 fn allocateSegments(self: *Zld) !void {
...@@ -1579,44 +1573,6 @@ pub const Zld = struct {...@@ -1579,44 +1573,6 @@ pub const Zld = struct {
1579 try rebase.finalize(self.gpa);1573 try rebase.finalize(self.gpa);
1580 }1574 }
15811575
1582 fn collectBindDataFromContainer(
1583 self: *Zld,
1584 sect_id: u8,
1585 bind: *Bind,
1586 container: anytype,
1587 ) !void {
1588 const slice = self.sections.slice();
1589 const segment_index = slice.items(.segment_index)[sect_id];
1590 const seg = self.getSegment(sect_id);
1591
1592 try bind.entries.ensureUnusedCapacity(self.gpa, container.items.len);
1593
1594 for (container.items) |entry| {
1595 const bind_sym_name = entry.getTargetSymbolName(self);
1596 const bind_sym = entry.getTargetSymbol(self);
1597 if (bind_sym.sect()) continue;
1598
1599 const sym = entry.getAtomSymbol(self);
1600 const base_offset = sym.n_value - seg.vmaddr;
1601
1602 const dylib_ordinal = @divTrunc(@as(i16, @bitCast(bind_sym.n_desc)), macho.N_SYMBOL_RESOLVER);
1603 log.debug(" | bind at {x}, import('{s}') in dylib({d})", .{
1604 base_offset,
1605 bind_sym_name,
1606 dylib_ordinal,
1607 });
1608 if (bind_sym.weakRef()) {
1609 log.debug(" | marking as weak ref ", .{});
1610 }
1611 bind.entries.appendAssumeCapacity(.{
1612 .target = entry.target,
1613 .offset = base_offset,
1614 .segment_id = segment_index,
1615 .addend = 0,
1616 });
1617 }
1618 }
1619
1620 fn collectBindData(1576 fn collectBindData(
1621 self: *Zld,1577 self: *Zld,
1622 bind: *Bind,1578 bind: *Bind,
...@@ -1629,8 +1585,8 @@ pub const Zld = struct {...@@ -1629,8 +1585,8 @@ pub const Zld = struct {
1629 }1585 }
16301586
1631 // Next, unpack TLV pointers section1587 // Next, unpack TLV pointers section
1632 if (self.getSectionByName("__DATA", "__thread_ptrs")) |sect_id| {1588 if (self.tlv_ptr_section_index) |sect_id| {
1633 try self.collectBindDataFromContainer(sect_id, bind, self.tlv_ptr_entries);1589 try MachO.collectBindDataFromTableSection(self.gpa, self, sect_id, bind, self.tlv_ptr_table);
1634 }1590 }
16351591
1636 // Finally, unpack the rest.1592 // Finally, unpack the rest.
...@@ -2488,6 +2444,12 @@ pub const Zld = struct {...@@ -2488,6 +2444,12 @@ pub const Zld = struct {
2488 return header.addr + @sizeOf(u64) * index;2444 return header.addr + @sizeOf(u64) * index;
2489 }2445 }
24902446
2447 pub fn getTlvPtrEntryAddress(self: *Zld, sym_with_loc: SymbolWithLoc) ?u64 {
2448 const index = self.tlv_ptr_table.lookup.get(sym_with_loc) orelse return null;
2449 const header = self.sections.items(.header)[self.tlv_ptr_section_index.?];
2450 return header.addr + @sizeOf(u64) * index;
2451 }
2452
2491 /// Returns stubs atom that references `sym_with_loc` if one exists.2453 /// Returns stubs atom that references `sym_with_loc` if one exists.
2492 /// Returns null otherwise.2454 /// Returns null otherwise.
2493 pub fn getStubsAtomIndexForSymbol(self: *Zld, sym_with_loc: SymbolWithLoc) ?AtomIndex {2455 pub fn getStubsAtomIndexForSymbol(self: *Zld, sym_with_loc: SymbolWithLoc) ?AtomIndex {
...@@ -2496,14 +2458,6 @@ pub const Zld = struct {...@@ -2496,14 +2458,6 @@ pub const Zld = struct {
2496 return entry.atom_index;2458 return entry.atom_index;
2497 }2459 }
24982460
2499 /// Returns TLV pointer atom that references `sym_with_loc` if one exists.
2500 /// Returns null otherwise.
2501 pub fn getTlvPtrAtomIndexForSymbol(self: *Zld, sym_with_loc: SymbolWithLoc) ?AtomIndex {
2502 const index = self.tlv_ptr_table.get(sym_with_loc) orelse return null;
2503 const entry = self.tlv_ptr_entries.items[index];
2504 return entry.atom_index;
2505 }
2506
2507 /// Returns symbol location corresponding to the set entrypoint.2461 /// Returns symbol location corresponding to the set entrypoint.
2508 /// Asserts output mode is executable.2462 /// Asserts output mode is executable.
2509 pub fn getEntryPoint(self: Zld) SymbolWithLoc {2463 pub fn getEntryPoint(self: Zld) SymbolWithLoc {
...@@ -2835,18 +2789,8 @@ pub const Zld = struct {...@@ -2835,18 +2789,8 @@ pub const Zld = struct {
2835 scoped_log.debug("GOT entries:", .{});2789 scoped_log.debug("GOT entries:", .{});
2836 scoped_log.debug("{}", .{self.got_table});2790 scoped_log.debug("{}", .{self.got_table});
28372791
2838 scoped_log.debug("__thread_ptrs entries:", .{});2792 scoped_log.debug("TLV pointers:", .{});
2839 for (self.tlv_ptr_entries.items, 0..) |entry, i| {2793 scoped_log.debug("{}", .{self.tlv_ptr_table});
2840 const atom_sym = entry.getAtomSymbol(self);
2841 const target_sym = entry.getTargetSymbol(self);
2842 const target_sym_name = entry.getTargetSymbolName(self);
2843 assert(target_sym.undf());
2844 scoped_log.debug(" {d}@{x} => import('{s}')", .{
2845 i,
2846 atom_sym.n_value,
2847 target_sym_name,
2848 });
2849 }
28502794
2851 scoped_log.debug("stubs entries:", .{});2795 scoped_log.debug("stubs entries:", .{});
2852 for (self.stubs.items, 0..) |entry, i| {2796 for (self.stubs.items, 0..) |entry, i| {
...@@ -3435,7 +3379,10 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -3435,7 +3379,10 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
3435 }3379 }
34363380
3437 try zld.writeAtoms();3381 try zld.writeAtoms();
3438 try zld.writeGotEntries();3382
3383 if (zld.got_section_index) |sect_id| try zld.writePointerEntries(sect_id, &zld.got_table);
3384 if (zld.tlv_ptr_section_index) |sect_id| try zld.writePointerEntries(sect_id, &zld.tlv_ptr_table);
3385
3439 try eh_frame.write(&zld, &unwind_info);3386 try eh_frame.write(&zld, &unwind_info);
3440 try unwind_info.write(&zld);3387 try unwind_info.write(&zld);
3441 try zld.writeLinkeditSegmentData();3388 try zld.writeLinkeditSegmentData();