| ... | @@ -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) = .{}, |
| 69 | | 69 | |
| 70 | got_section_index: ?u8 = null, | 70 | got_section_index: ?u8 = null, |
| | 71 | tlv_ptr_section_index: ?u8 = null, |
| 71 | | 72 | |
| 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 { |
| 81 | | 82 | |
| 82 | strtab: StringTable(.strtab) = .{}, | 83 | strtab: StringTable(.strtab) = .{}, |
| 83 | | 84 | |
| 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) = .{}, |
| 88 | | 87 | |
| 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 | } |
| 270 | | 269 | |
| 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; |
| 843 | | 824 | |
| 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 | } |
| 961 | | 941 | |
| 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 | } |
| 971 | | 951 | |
| | 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 | } |
| 1089 | | 1077 | |
| 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 { |
| 1147 | | 1134 | |
| 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 | } |
| 1240 | | 1234 | |
| 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 | } |
| 1581 | | 1575 | |
| 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 | } |
| 1630 | | 1586 | |
| 1631 | // Next, unpack TLV pointers section | 1587 | // 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 | } |
| 1635 | | 1591 | |
| 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 | } |
| 2490 | | 2446 | |
| | 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 | } |
| 2498 | | 2460 | |
| 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}); |
| 2837 | | 2791 | |
| 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 | } | | |
| 2850 | | 2794 | |
| 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 | } |
| 3436 | | 3380 | |
| 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(); |