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 {
360360
361361pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc) ?Index {
362362 if (zld.getStubsAtomIndexForSymbol(target)) |stubs_atom| return stubs_atom;
363 if (zld.getTlvPtrAtomIndexForSymbol(target)) |tlv_ptr_atom| return tlv_ptr_atom;
364363
365364 if (target.getFile() == null) {
366365 const target_sym_name = zld.getSymbolName(target);
......@@ -413,7 +412,8 @@ fn scanAtomRelocsArm64(zld: *Zld, atom_index: Index, relocs: []align(1) const ma
413412 .ARM64_RELOC_TLVP_LOAD_PAGE21,
414413 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
415414 => {
416 try addTlvPtrEntry(zld, target);
415 const sym = zld.getSymbol(target);
416 if (sym.undf()) try zld.addTlvPtrEntry(target);
417417 },
418418 else => {},
419419 }
......@@ -454,28 +454,14 @@ fn scanAtomRelocsX86(zld: *Zld, atom_index: Index, relocs: []align(1) const mach
454454 try zld.addGotEntry(target);
455455 },
456456 .X86_64_RELOC_TLV => {
457 try addTlvPtrEntry(zld, target);
457 const sym = zld.getSymbol(target);
458 if (sym.undf()) try zld.addTlvPtrEntry(target);
458459 },
459460 else => {},
460461 }
461462 }
462463}
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
479465pub fn addStub(zld: *Zld, target: SymbolWithLoc) !void {
480466 const target_sym = zld.getSymbol(target);
481467 if (!target_sym.undf()) return;
......@@ -641,10 +627,12 @@ fn resolveRelocsArm64(
641627 const header = zld.sections.items(.header)[source_sym.n_sect - 1];
642628 break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;
643629 };
644 const target_addr = if (is_via_got)
645 zld.getGotEntryAddress(target).?
646 else
647 try getRelocTargetAddress(zld, target, is_tlv);
630 const target_addr = blk: {
631 if (is_via_got) break :blk zld.getGotEntryAddress(target).?;
632 if (relocIsTlv(zld, rel) and zld.getSymbol(target).undf())
633 break :blk zld.getTlvPtrEntryAddress(target).?;
634 break :blk try getRelocTargetAddress(zld, target, is_tlv);
635 };
648636
649637 log.debug(" | source_addr = 0x{x}", .{source_addr});
650638
......@@ -802,7 +790,7 @@ fn resolveRelocsArm64(
802790 }
803791 };
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{
806794 .load_store_register = .{
807795 .rt = reg_info.rd,
808796 .rn = reg_info.rn,
......@@ -938,14 +926,15 @@ fn resolveRelocsX86(
938926 const header = zld.sections.items(.header)[source_sym.n_sect - 1];
939927 break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;
940928 };
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
942936 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
949938 switch (rel_type) {
950939 .X86_64_RELOC_BRANCH => {
951940 const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]);
......@@ -971,7 +960,7 @@ fn resolveRelocsX86(
971960 log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr});
972961 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) {
975964 // We need to rewrite the opcode from movq to leaq.
976965 atom_code[rel_offset - 2] = 0x8d;
977966 }
......@@ -1112,3 +1101,19 @@ pub fn relocRequiresGot(zld: *Zld, rel: macho.relocation_info) bool {
11121101 else => unreachable,
11131102 }
11141103}
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 {
6868 sections: std.MultiArrayList(Section) = .{},
6969
7070 got_section_index: ?u8 = null,
71 tlv_ptr_section_index: ?u8 = null,
7172
7273 locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
7374 globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
......@@ -81,9 +82,7 @@ pub const Zld = struct {
8182
8283 strtab: StringTable(.strtab) = .{},
8384
84 tlv_ptr_entries: std.ArrayListUnmanaged(IndirectPointer) = .{},
85 tlv_ptr_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
86
85 tlv_ptr_table: TableSection(SymbolWithLoc) = .{},
8786 got_table: TableSection(SymbolWithLoc) = .{},
8887
8988 stubs: std.ArrayListUnmanaged(IndirectPointer) = .{},
......@@ -268,24 +267,6 @@ pub const Zld = struct {
268267 return index;
269268 }
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
289270 fn createDyldStubBinderGotAtom(self: *Zld) !void {
290271 const global_index = self.dyld_stub_binder_index orelse return;
291272 const target = self.globals.items[global_index];
......@@ -841,7 +822,6 @@ pub const Zld = struct {
841822 pub fn deinit(self: *Zld) void {
842823 const gpa = self.gpa;
843824
844 self.tlv_ptr_entries.deinit(gpa);
845825 self.tlv_ptr_table.deinit(gpa);
846826 self.got_table.deinit(gpa);
847827 self.stubs.deinit(gpa);
......@@ -959,16 +939,26 @@ pub const Zld = struct {
959939 return global_index;
960940 }
961941
962 pub fn addGotEntry(zld: *Zld, target: SymbolWithLoc) !void {
963 if (zld.got_table.lookup.contains(target)) return;
964 _ = try zld.got_table.allocateEntry(zld.gpa, target);
965 if (zld.got_section_index == null) {
966 zld.got_section_index = try zld.initSection("__DATA_CONST", "__got", .{
942 pub fn addGotEntry(self: *Zld, target: SymbolWithLoc) !void {
943 if (self.got_table.lookup.contains(target)) return;
944 _ = try self.got_table.allocateEntry(self.gpa, target);
945 if (self.got_section_index == null) {
946 self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{
967947 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
968948 });
969949 }
970950 }
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
972962 fn allocateSpecialSymbols(self: *Zld) !void {
973963 for (&[_]?u32{
974964 self.dso_handle_index,
......@@ -1033,12 +1023,10 @@ pub const Zld = struct {
10331023 } else if (atom.getFile() == null) outer: {
10341024 switch (header.type()) {
10351025 macho.S_NON_LAZY_SYMBOL_POINTERS => unreachable,
1026 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => unreachable,
10361027 macho.S_LAZY_SYMBOL_POINTERS => {
10371028 try self.writeLazyPointer(count, buffer.writer());
10381029 },
1039 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => {
1040 buffer.appendSliceAssumeCapacity(&[_]u8{0} ** @sizeOf(u64));
1041 },
10421030 else => {
10431031 if (self.stub_helper_preamble_sym_index) |sym_index| {
10441032 if (sym_index == atom.sym_index) {
......@@ -1087,12 +1075,11 @@ pub const Zld = struct {
10871075 }
10881076 }
10891077
1090 fn writeGotEntries(self: *Zld) !void {
1091 const sect_id = self.got_section_index orelse return;
1078 fn writePointerEntries(self: *Zld, sect_id: u8, table: anytype) !void {
10921079 const header = self.sections.items(.header)[sect_id];
10931080 var buffer = try std.ArrayList(u8).initCapacity(self.gpa, header.size);
10941081 defer buffer.deinit();
1095 for (self.got_table.entries.items) |entry| {
1082 for (table.entries.items) |entry| {
10961083 const sym = self.getSymbol(entry);
10971084 buffer.writer().writeIntLittle(u64, sym.n_value) catch unreachable;
10981085 }
......@@ -1147,6 +1134,7 @@ pub const Zld = struct {
11471134
11481135 for (&[_]*?u8{
11491136 &self.got_section_index,
1137 &self.tlv_ptr_section_index,
11501138 }) |maybe_index| {
11511139 if (maybe_index.*) |*index| {
11521140 index.* = backlinks[index.*];
......@@ -1236,6 +1224,12 @@ pub const Zld = struct {
12361224 header.size = self.got_table.count() * @sizeOf(u64);
12371225 header.@"align" = 3;
12381226 }
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 }
12391233 }
12401234
12411235 fn allocateSegments(self: *Zld) !void {
......@@ -1579,44 +1573,6 @@ pub const Zld = struct {
15791573 try rebase.finalize(self.gpa);
15801574 }
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
16201576 fn collectBindData(
16211577 self: *Zld,
16221578 bind: *Bind,
......@@ -1629,8 +1585,8 @@ pub const Zld = struct {
16291585 }
16301586
16311587 // Next, unpack TLV pointers section
1632 if (self.getSectionByName("__DATA", "__thread_ptrs")) |sect_id| {
1633 try self.collectBindDataFromContainer(sect_id, bind, self.tlv_ptr_entries);
1588 if (self.tlv_ptr_section_index) |sect_id| {
1589 try MachO.collectBindDataFromTableSection(self.gpa, self, sect_id, bind, self.tlv_ptr_table);
16341590 }
16351591
16361592 // Finally, unpack the rest.
......@@ -2488,6 +2444,12 @@ pub const Zld = struct {
24882444 return header.addr + @sizeOf(u64) * index;
24892445 }
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
24912453 /// Returns stubs atom that references `sym_with_loc` if one exists.
24922454 /// Returns null otherwise.
24932455 pub fn getStubsAtomIndexForSymbol(self: *Zld, sym_with_loc: SymbolWithLoc) ?AtomIndex {
......@@ -2496,14 +2458,6 @@ pub const Zld = struct {
24962458 return entry.atom_index;
24972459 }
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
25072461 /// Returns symbol location corresponding to the set entrypoint.
25082462 /// Asserts output mode is executable.
25092463 pub fn getEntryPoint(self: Zld) SymbolWithLoc {
......@@ -2835,18 +2789,8 @@ pub const Zld = struct {
28352789 scoped_log.debug("GOT entries:", .{});
28362790 scoped_log.debug("{}", .{self.got_table});
28372791
2838 scoped_log.debug("__thread_ptrs entries:", .{});
2839 for (self.tlv_ptr_entries.items, 0..) |entry, i| {
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 }
2792 scoped_log.debug("TLV pointers:", .{});
2793 scoped_log.debug("{}", .{self.tlv_ptr_table});
28502794
28512795 scoped_log.debug("stubs entries:", .{});
28522796 for (self.stubs.items, 0..) |entry, i| {
......@@ -3435,7 +3379,10 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
34353379 }
34363380
34373381 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
34393386 try eh_frame.write(&zld, &unwind_info);
34403387 try unwind_info.write(&zld);
34413388 try zld.writeLinkeditSegmentData();