authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-24 10:34:59+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
log04e93dd26572e8d1d69c0f714a6eb06b9435f771
treece2729d357027bbec58ae8fd01b3264f18e850db
parent837114f019a5ba2695165030790fb162ca199151

macho: use TableSection for GOT entries in zld driver


6 files changed, 153 insertions(+), 183 deletions(-)

src/link/MachO.zig+30-18
......@@ -3222,18 +3222,24 @@ fn writeLinkeditSegmentData(self: *MachO) !void {
32223222 seg.vmsize = mem.alignForward(u64, seg.filesize, page_size);
32233223}
32243224
3225fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase, table: anytype) !void {
3226 const header = self.sections.items(.header)[sect_id];
3227 const segment_index = self.sections.items(.segment_index)[sect_id];
3228 const segment = self.segments.items[segment_index];
3225pub fn collectRebaseDataFromTableSection(
3226 gpa: Allocator,
3227 ctx: anytype,
3228 sect_id: u8,
3229 rebase: *Rebase,
3230 table: anytype,
3231) !void {
3232 const header = ctx.sections.items(.header)[sect_id];
3233 const segment_index = ctx.sections.items(.segment_index)[sect_id];
3234 const segment = ctx.segments.items[segment_index];
32293235 const base_offset = header.addr - segment.vmaddr;
3230 const is_got = if (self.got_section_index) |index| index == sect_id else false;
3236 const is_got = if (ctx.got_section_index) |index| index == sect_id else false;
32313237
3232 try rebase.entries.ensureUnusedCapacity(self.base.allocator, table.entries.items.len);
3238 try rebase.entries.ensureUnusedCapacity(gpa, table.entries.items.len);
32333239
32343240 for (table.entries.items, 0..) |entry, i| {
32353241 if (!table.lookup.contains(entry)) continue;
3236 const sym = self.getSymbol(entry);
3242 const sym = ctx.getSymbol(entry);
32373243 if (is_got and sym.undf()) continue;
32383244 const offset = i * @sizeOf(u64);
32393245 log.debug(" | rebase at {x}", .{base_offset + offset});
......@@ -3271,28 +3277,34 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {
32713277 }
32723278 }
32733279
3274 try self.collectRebaseDataFromTableSection(self.got_section_index.?, rebase, self.got_table);
3275 try self.collectRebaseDataFromTableSection(self.la_symbol_ptr_section_index.?, rebase, self.stub_table);
3280 try collectRebaseDataFromTableSection(gpa, self, self.got_section_index.?, rebase, self.got_table);
3281 try collectRebaseDataFromTableSection(gpa, self, self.la_symbol_ptr_section_index.?, rebase, self.stub_table);
32763282
32773283 try rebase.finalize(gpa);
32783284}
32793285
3280fn collectBindDataFromTableSection(self: *MachO, sect_id: u8, bind: anytype, table: anytype) !void {
3281 const header = self.sections.items(.header)[sect_id];
3282 const segment_index = self.sections.items(.segment_index)[sect_id];
3283 const segment = self.segments.items[segment_index];
3286pub fn collectBindDataFromTableSection(
3287 gpa: Allocator,
3288 ctx: anytype,
3289 sect_id: u8,
3290 bind: anytype,
3291 table: anytype,
3292) !void {
3293 const header = ctx.sections.items(.header)[sect_id];
3294 const segment_index = ctx.sections.items(.segment_index)[sect_id];
3295 const segment = ctx.segments.items[segment_index];
32843296 const base_offset = header.addr - segment.vmaddr;
32853297
3286 try bind.entries.ensureUnusedCapacity(self.base.allocator, table.entries.items.len);
3298 try bind.entries.ensureUnusedCapacity(gpa, table.entries.items.len);
32873299
32883300 for (table.entries.items, 0..) |entry, i| {
32893301 if (!table.lookup.contains(entry)) continue;
3290 const bind_sym = self.getSymbol(entry);
3302 const bind_sym = ctx.getSymbol(entry);
32913303 if (!bind_sym.undf()) continue;
32923304 const offset = i * @sizeOf(u64);
32933305 log.debug(" | bind at {x}, import('{s}') in dylib({d})", .{
32943306 base_offset + offset,
3295 self.getSymbolName(entry),
3307 ctx.getSymbolName(entry),
32963308 @divTrunc(@as(i16, @bitCast(bind_sym.n_desc)), macho.N_SYMBOL_RESOLVER),
32973309 });
32983310 if (bind_sym.weakRef()) {
......@@ -3349,12 +3361,12 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {
33493361 }
33503362
33513363 // Gather GOT pointers
3352 try self.collectBindDataFromTableSection(self.got_section_index.?, bind, self.got_table);
3364 try collectBindDataFromTableSection(gpa, self, self.got_section_index.?, bind, self.got_table);
33533365 try bind.finalize(gpa, self);
33543366}
33553367
33563368fn collectLazyBindData(self: *MachO, bind: anytype) !void {
3357 try self.collectBindDataFromTableSection(self.la_symbol_ptr_section_index.?, bind, self.stub_table);
3369 try collectBindDataFromTableSection(self.base.allocator, self, self.la_symbol_ptr_section_index.?, bind, self.stub_table);
33583370 try bind.finalize(self.base.allocator, self);
33593371}
33603372
src/link/MachO/Atom.zig+14-23
......@@ -358,10 +358,7 @@ pub fn parseRelocTarget(zld: *Zld, ctx: struct {
358358 return target;
359359}
360360
361pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc, is_via_got: bool) ?Index {
362 if (is_via_got) {
363 return zld.getGotAtomIndexForSymbol(target).?; // panic means fatal error
364 }
361pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc) ?Index {
365362 if (zld.getStubsAtomIndexForSymbol(target)) |stubs_atom| return stubs_atom;
366363 if (zld.getTlvPtrAtomIndexForSymbol(target)) |tlv_ptr_atom| return tlv_ptr_atom;
367364
......@@ -411,7 +408,7 @@ fn scanAtomRelocsArm64(zld: *Zld, atom_index: Index, relocs: []align(1) const ma
411408 .ARM64_RELOC_POINTER_TO_GOT,
412409 => {
413410 // TODO rewrite relocation
414 try addGotEntry(zld, target);
411 try zld.addGotEntry(target);
415412 },
416413 .ARM64_RELOC_TLVP_LOAD_PAGE21,
417414 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
......@@ -454,7 +451,7 @@ fn scanAtomRelocsX86(zld: *Zld, atom_index: Index, relocs: []align(1) const mach
454451 },
455452 .X86_64_RELOC_GOT, .X86_64_RELOC_GOT_LOAD => {
456453 // TODO rewrite relocation
457 try addGotEntry(zld, target);
454 try zld.addGotEntry(target);
458455 },
459456 .X86_64_RELOC_TLV => {
460457 try addTlvPtrEntry(zld, target);
......@@ -479,18 +476,6 @@ fn addTlvPtrEntry(zld: *Zld, target: SymbolWithLoc) !void {
479476 try zld.tlv_ptr_table.putNoClobber(gpa, target, tlv_ptr_index);
480477}
481478
482pub fn addGotEntry(zld: *Zld, target: SymbolWithLoc) !void {
483 if (zld.got_table.contains(target)) return;
484 const gpa = zld.gpa;
485 const atom_index = try zld.createGotAtom();
486 const got_index = @as(u32, @intCast(zld.got_entries.items.len));
487 try zld.got_entries.append(gpa, .{
488 .target = target,
489 .atom_index = atom_index,
490 });
491 try zld.got_table.putNoClobber(gpa, target, got_index);
492}
493
494479pub fn addStub(zld: *Zld, target: SymbolWithLoc) !void {
495480 const target_sym = zld.getSymbol(target);
496481 if (!target_sym.undf()) return;
......@@ -532,8 +517,8 @@ pub fn resolveRelocs(
532517 };
533518}
534519
535pub fn getRelocTargetAddress(zld: *Zld, target: SymbolWithLoc, is_via_got: bool, is_tlv: bool) !u64 {
536 const target_atom_index = getRelocTargetAtomIndex(zld, target, is_via_got) orelse {
520pub fn getRelocTargetAddress(zld: *Zld, target: SymbolWithLoc, is_tlv: bool) !u64 {
521 const target_atom_index = getRelocTargetAtomIndex(zld, target) orelse {
537522 // If there is no atom for target, we still need to check for special, atom-less
538523 // symbols such as `___dso_handle`.
539524 const target_name = zld.getSymbolName(target);
......@@ -656,7 +641,10 @@ fn resolveRelocsArm64(
656641 const header = zld.sections.items(.header)[source_sym.n_sect - 1];
657642 break :is_tlv header.type() == macho.S_THREAD_LOCAL_VARIABLES;
658643 };
659 const target_addr = try getRelocTargetAddress(zld, target, is_via_got, is_tlv);
644 const target_addr = if (is_via_got)
645 zld.getGotEntryAddress(target).?
646 else
647 try getRelocTargetAddress(zld, target, is_tlv);
660648
661649 log.debug(" | source_addr = 0x{x}", .{source_addr});
662650
......@@ -670,7 +658,7 @@ fn resolveRelocsArm64(
670658 zld.getSymbolName(atom.getSymbolWithLoc()),
671659 atom.getFile(),
672660 zld.getSymbolName(target),
673 zld.getAtom(getRelocTargetAtomIndex(zld, target, is_via_got).?).getFile(),
661 zld.getAtom(getRelocTargetAtomIndex(zld, target).?).getFile(),
674662 });
675663
676664 const displacement = if (Relocation.calcPcRelativeDisplacementArm64(
......@@ -953,7 +941,10 @@ fn resolveRelocsX86(
953941
954942 log.debug(" | source_addr = 0x{x}", .{source_addr});
955943
956 const target_addr = try getRelocTargetAddress(zld, target, is_via_got, is_tlv);
944 const target_addr = if (is_via_got)
945 zld.getGotEntryAddress(target).?
946 else
947 try getRelocTargetAddress(zld, target, is_tlv);
957948
958949 switch (rel_type) {
959950 .X86_64_RELOC_BRANCH => {
src/link/MachO/UnwindInfo.zig+3-5
......@@ -226,7 +226,7 @@ pub fn scanRelocs(zld: *Zld) !void {
226226 .code = mem.asBytes(&record),
227227 .base_offset = @as(i32, @intCast(record_id * @sizeOf(macho.compact_unwind_entry))),
228228 });
229 try Atom.addGotEntry(zld, target);
229 try zld.addGotEntry(target);
230230 }
231231 }
232232 }
......@@ -585,10 +585,8 @@ pub fn write(info: *UnwindInfo, zld: *Zld) !void {
585585
586586 log.debug("Personalities:", .{});
587587 for (info.personalities[0..info.personalities_count], 0..) |target, i| {
588 const atom_index = zld.getGotAtomIndexForSymbol(target).?;
589 const atom = zld.getAtom(atom_index);
590 const sym = zld.getSymbol(atom.getSymbolWithLoc());
591 personalities[i] = @as(u32, @intCast(sym.n_value - seg.vmaddr));
588 const addr = zld.getGotEntryAddress(target).?;
589 personalities[i] = @as(u32, @intCast(addr - seg.vmaddr));
592590 log.debug(" {d}: 0x{x} ({s})", .{ i, personalities[i], zld.getSymbolName(target) });
593591 }
594592
src/link/MachO/eh_frame.zig+4-4
......@@ -267,7 +267,7 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {
267267 source_offset: u32,
268268 ) !void {
269269 if (rec.getPersonalityPointerReloc(zld, object_id, source_offset)) |target| {
270 try Atom.addGotEntry(zld, target);
270 try zld.addGotEntry(target);
271271 }
272272 }
273273
......@@ -357,14 +357,14 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {
357357 // Address of the __eh_frame in the source object file
358358 },
359359 .ARM64_RELOC_POINTER_TO_GOT => {
360 const target_addr = try Atom.getRelocTargetAddress(zld, target, true, false);
360 const target_addr = zld.getGotEntryAddress(target).?;
361361 const result = math.cast(i32, @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr))) orelse
362362 return error.Overflow;
363363 mem.writeIntLittle(i32, rec.data[rel_offset..][0..4], result);
364364 },
365365 .ARM64_RELOC_UNSIGNED => {
366366 assert(rel.r_extern == 1);
367 const target_addr = try Atom.getRelocTargetAddress(zld, target, false, false);
367 const target_addr = try Atom.getRelocTargetAddress(zld, target, false);
368368 const result = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr));
369369 mem.writeIntLittle(i64, rec.data[rel_offset..][0..8], @as(i64, @intCast(result)));
370370 },
......@@ -375,7 +375,7 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {
375375 const rel_type = @as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type));
376376 switch (rel_type) {
377377 .X86_64_RELOC_GOT => {
378 const target_addr = try Atom.getRelocTargetAddress(zld, target, true, false);
378 const target_addr = zld.getGotEntryAddress(target).?;
379379 const addend = mem.readIntLittle(i32, rec.data[rel_offset..][0..4]);
380380 const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend));
381381 const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0);
src/link/MachO/thunks.zig+4-1
......@@ -318,7 +318,10 @@ fn isReachable(
318318
319319 const source_addr = source_sym.n_value + @as(u32, @intCast(rel.r_address - base_offset));
320320 const is_via_got = Atom.relocRequiresGot(zld, rel);
321 const target_addr = Atom.getRelocTargetAddress(zld, target, is_via_got, false) catch unreachable;
321 const target_addr = if (is_via_got)
322 zld.getGotEntryAddress(target).?
323 else
324 Atom.getRelocTargetAddress(zld, target, false) catch unreachable;
322325 _ = Relocation.calcPcRelativeDisplacementArm64(source_addr, target_addr) catch
323326 return false;
324327
src/link/MachO/zld.zig+98-132
......@@ -35,6 +35,7 @@ const Section = MachO.Section;
3535const StringTable = @import("../strtab.zig").StringTable;
3636const SymbolWithLoc = MachO.SymbolWithLoc;
3737const SymbolResolver = MachO.SymbolResolver;
38const TableSection = @import("../table_section.zig").TableSection;
3839const Trie = @import("Trie.zig");
3940const UnwindInfo = @import("UnwindInfo.zig");
4041
......@@ -66,6 +67,8 @@ pub const Zld = struct {
6667 segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{},
6768 sections: std.MultiArrayList(Section) = .{},
6869
70 got_section_index: ?u8 = null,
71
6972 locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
7073 globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
7174
......@@ -81,8 +84,7 @@ pub const Zld = struct {
8184 tlv_ptr_entries: std.ArrayListUnmanaged(IndirectPointer) = .{},
8285 tlv_ptr_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
8386
84 got_entries: std.ArrayListUnmanaged(IndirectPointer) = .{},
85 got_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
87 got_table: TableSection(SymbolWithLoc) = .{},
8688
8789 stubs: std.ArrayListUnmanaged(IndirectPointer) = .{},
8890 stubs_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
......@@ -266,32 +268,6 @@ pub const Zld = struct {
266268 return index;
267269 }
268270
269 pub fn createGotAtom(self: *Zld) !AtomIndex {
270 const sym_index = try self.allocateSymbol();
271 const atom_index = try self.createEmptyAtom(sym_index, @sizeOf(u64), 3);
272 const sym = self.getSymbolPtr(.{ .sym_index = sym_index });
273 sym.n_type = macho.N_SECT;
274
275 const sect_id = self.getSectionByName("__DATA_CONST", "__got") orelse
276 try self.initSection("__DATA_CONST", "__got", .{
277 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
278 });
279 sym.n_sect = sect_id + 1;
280
281 self.addAtomToSection(atom_index);
282
283 return atom_index;
284 }
285
286 fn writeGotPointer(self: *Zld, got_index: u32, writer: anytype) !void {
287 const target_addr = blk: {
288 const entry = self.got_entries.items[got_index];
289 const sym = entry.getTargetSymbol(self);
290 break :blk sym.n_value;
291 };
292 try writer.writeIntLittle(u64, target_addr);
293 }
294
295271 pub fn createTlvPtrAtom(self: *Zld) !AtomIndex {
296272 const sym_index = try self.allocateSymbol();
297273 const atom_index = try self.createEmptyAtom(sym_index, @sizeOf(u64), 3);
......@@ -311,16 +287,9 @@ pub const Zld = struct {
311287 }
312288
313289 fn createDyldStubBinderGotAtom(self: *Zld) !void {
314 const gpa = self.gpa;
315290 const global_index = self.dyld_stub_binder_index orelse return;
316291 const target = self.globals.items[global_index];
317 const atom_index = try self.createGotAtom();
318 const got_index = @as(u32, @intCast(self.got_entries.items.len));
319 try self.got_entries.append(gpa, .{
320 .target = target,
321 .atom_index = atom_index,
322 });
323 try self.got_table.putNoClobber(gpa, target, got_index);
292 try self.addGotEntry(target);
324293 }
325294
326295 fn createDyldPrivateAtom(self: *Zld) !void {
......@@ -381,9 +350,7 @@ pub const Zld = struct {
381350 };
382351 const dyld_stub_binder_got_addr = blk: {
383352 const sym_loc = self.globals.items[self.dyld_stub_binder_index.?];
384 const index = self.got_table.get(sym_loc).?;
385 const entry = self.got_entries.items[index];
386 break :blk entry.getAtomSymbol(self).n_value;
353 break :blk self.getGotEntryAddress(sym_loc).?;
387354 };
388355 try stub_helpers.writeStubHelperPreambleCode(.{
389356 .cpu_arch = cpu_arch,
......@@ -876,7 +843,6 @@ pub const Zld = struct {
876843
877844 self.tlv_ptr_entries.deinit(gpa);
878845 self.tlv_ptr_table.deinit(gpa);
879 self.got_entries.deinit(gpa);
880846 self.got_table.deinit(gpa);
881847 self.stubs.deinit(gpa);
882848 self.stubs_table.deinit(gpa);
......@@ -993,6 +959,16 @@ pub const Zld = struct {
993959 return global_index;
994960 }
995961
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", .{
967 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
968 });
969 }
970 }
971
996972 fn allocateSpecialSymbols(self: *Zld) !void {
997973 for (&[_]?u32{
998974 self.dso_handle_index,
......@@ -1056,9 +1032,7 @@ pub const Zld = struct {
10561032 buffer.appendSliceAssumeCapacity(&[_]u8{0} ** @sizeOf(u64));
10571033 } else if (atom.getFile() == null) outer: {
10581034 switch (header.type()) {
1059 macho.S_NON_LAZY_SYMBOL_POINTERS => {
1060 try self.writeGotPointer(count, buffer.writer());
1061 },
1035 macho.S_NON_LAZY_SYMBOL_POINTERS => unreachable,
10621036 macho.S_LAZY_SYMBOL_POINTERS => {
10631037 try self.writeLazyPointer(count, buffer.writer());
10641038 },
......@@ -1113,41 +1087,70 @@ pub const Zld = struct {
11131087 }
11141088 }
11151089
1090 fn writeGotEntries(self: *Zld) !void {
1091 const sect_id = self.got_section_index orelse return;
1092 const header = self.sections.items(.header)[sect_id];
1093 var buffer = try std.ArrayList(u8).initCapacity(self.gpa, header.size);
1094 defer buffer.deinit();
1095 for (self.got_table.entries.items) |entry| {
1096 const sym = self.getSymbol(entry);
1097 buffer.writer().writeIntLittle(u64, sym.n_value) catch unreachable;
1098 }
1099 log.debug("writing .got contents at file offset 0x{x}", .{header.offset});
1100 try self.file.pwriteAll(buffer.items, header.offset);
1101 }
1102
11161103 fn pruneAndSortSections(self: *Zld) !void {
1117 const gpa = self.gpa;
1104 const Entry = struct {
1105 index: u8,
11181106
1119 const SortSection = struct {
1120 pub fn lessThan(_: void, lhs: Section, rhs: Section) bool {
1121 return getSectionPrecedence(lhs.header) < getSectionPrecedence(rhs.header);
1107 pub fn lessThan(zld: *Zld, lhs: @This(), rhs: @This()) bool {
1108 const lhs_header = zld.sections.items(.header)[lhs.index];
1109 const rhs_header = zld.sections.items(.header)[rhs.index];
1110 return getSectionPrecedence(lhs_header) < getSectionPrecedence(rhs_header);
11221111 }
11231112 };
11241113
1125 const slice = self.sections.slice();
1126 var sections = std.ArrayList(Section).init(gpa);
1127 defer sections.deinit();
1128 try sections.ensureTotalCapacity(slice.len);
1114 const gpa = self.gpa;
11291115
1130 {
1131 var i: u8 = 0;
1132 while (i < slice.len) : (i += 1) {
1133 const section = self.sections.get(i);
1134 if (section.header.size == 0) {
1135 log.debug("pruning section {s},{s} {?d}", .{
1136 section.header.segName(),
1137 section.header.sectName(),
1138 section.first_atom_index,
1139 });
1140 continue;
1141 }
1142 sections.appendAssumeCapacity(section);
1116 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.sections.slice().len);
1117 defer entries.deinit();
1118
1119 for (0..self.sections.slice().len) |index| {
1120 const section = self.sections.get(index);
1121 if (section.header.size == 0) {
1122 log.debug("pruning section {s},{s} {?d}", .{
1123 section.header.segName(),
1124 section.header.sectName(),
1125 section.first_atom_index,
1126 });
1127 continue;
11431128 }
1129 entries.appendAssumeCapacity(.{ .index = @intCast(index) });
1130 }
1131
1132 mem.sort(Entry, entries.items, self, Entry.lessThan);
1133
1134 var slice = self.sections.toOwnedSlice();
1135 defer slice.deinit(gpa);
1136
1137 const backlinks = try gpa.alloc(u8, slice.len);
1138 defer gpa.free(backlinks);
1139 for (entries.items, 0..) |entry, i| {
1140 backlinks[entry.index] = @as(u8, @intCast(i));
11441141 }
11451142
1146 mem.sort(Section, sections.items, {}, SortSection.lessThan);
1143 try self.sections.ensureTotalCapacity(gpa, entries.items.len);
1144 for (entries.items) |entry| {
1145 self.sections.appendAssumeCapacity(slice.get(entry.index));
1146 }
11471147
1148 self.sections.shrinkRetainingCapacity(0);
1149 for (sections.items) |out| {
1150 self.sections.appendAssumeCapacity(out);
1148 for (&[_]*?u8{
1149 &self.got_section_index,
1150 }) |maybe_index| {
1151 if (maybe_index.*) |*index| {
1152 index.* = backlinks[index.*];
1153 }
11511154 }
11521155 }
11531156
......@@ -1227,6 +1230,12 @@ pub const Zld = struct {
12271230 } else break;
12281231 }
12291232 }
1233
1234 if (self.got_section_index) |sect_id| {
1235 const header = &self.sections.items(.header)[sect_id];
1236 header.size = self.got_table.count() * @sizeOf(u64);
1237 header.@"align" = 3;
1238 }
12301239 }
12311240
12321241 fn allocateSegments(self: *Zld) !void {
......@@ -1448,40 +1457,12 @@ pub const Zld = struct {
14481457 seg.vmsize = mem.alignForward(u64, seg.filesize, MachO.getPageSize(self.options.target.cpu.arch));
14491458 }
14501459
1451 fn collectRebaseDataFromContainer(
1452 self: *Zld,
1453 sect_id: u8,
1454 rebase: *Rebase,
1455 container: anytype,
1456 ) !void {
1457 const slice = self.sections.slice();
1458 const segment_index = slice.items(.segment_index)[sect_id];
1459 const seg = self.getSegment(sect_id);
1460
1461 try rebase.entries.ensureUnusedCapacity(self.gpa, container.items.len);
1462
1463 for (container.items) |entry| {
1464 const target_sym = entry.getTargetSymbol(self);
1465 if (target_sym.undf()) continue;
1466
1467 const atom_sym = entry.getAtomSymbol(self);
1468 const base_offset = atom_sym.n_value - seg.vmaddr;
1469
1470 log.debug(" | rebase at {x}", .{base_offset});
1471
1472 rebase.entries.appendAssumeCapacity(.{
1473 .offset = base_offset,
1474 .segment_id = segment_index,
1475 });
1476 }
1477 }
1478
14791460 fn collectRebaseData(self: *Zld, rebase: *Rebase) !void {
14801461 log.debug("collecting rebase data", .{});
14811462
14821463 // First, unpack GOT entries
1483 if (self.getSectionByName("__DATA_CONST", "__got")) |sect_id| {
1484 try self.collectRebaseDataFromContainer(sect_id, rebase, self.got_entries);
1464 if (self.got_section_index) |sect_id| {
1465 try MachO.collectRebaseDataFromTableSection(self.gpa, self, sect_id, rebase, self.got_table);
14851466 }
14861467
14871468 const slice = self.sections.slice();
......@@ -1543,7 +1524,11 @@ pub const Zld = struct {
15431524 };
15441525
15451526 if (should_rebase) {
1546 log.debug(" ATOM({d}, %{d}, '{s}')", .{ atom_index, atom.sym_index, self.getSymbolName(atom.getSymbolWithLoc()) });
1527 log.debug(" ATOM({d}, %{d}, '{s}')", .{
1528 atom_index,
1529 atom.sym_index,
1530 self.getSymbolName(atom.getSymbolWithLoc()),
1531 });
15471532
15481533 const code = Atom.getAtomCode(self, atom_index);
15491534 const relocs = Atom.getAtomRelocs(self, atom_index);
......@@ -1639,8 +1624,8 @@ pub const Zld = struct {
16391624 log.debug("collecting bind data", .{});
16401625
16411626 // First, unpack GOT section
1642 if (self.getSectionByName("__DATA_CONST", "__got")) |sect_id| {
1643 try self.collectBindDataFromContainer(sect_id, bind, self.got_entries);
1627 if (self.got_section_index) |sect_id| {
1628 try MachO.collectBindDataFromTableSection(self.gpa, self, sect_id, bind, self.got_table);
16441629 }
16451630
16461631 // Next, unpack TLV pointers section
......@@ -2237,7 +2222,7 @@ pub const Zld = struct {
22372222 fn writeDysymtab(self: *Zld, ctx: SymtabCtx) !void {
22382223 const gpa = self.gpa;
22392224 const nstubs = @as(u32, @intCast(self.stubs.items.len));
2240 const ngot_entries = @as(u32, @intCast(self.got_entries.items.len));
2225 const ngot_entries = @as(u32, @intCast(self.got_table.lookup.count()));
22412226 const nindirectsyms = nstubs * 2 + ngot_entries;
22422227 const iextdefsym = ctx.nlocalsym;
22432228 const iundefsym = iextdefsym + ctx.nextdefsym;
......@@ -2266,13 +2251,14 @@ pub const Zld = struct {
22662251 }
22672252 }
22682253
2269 if (self.getSectionByName("__DATA_CONST", "__got")) |sect_id| {
2254 if (self.got_section_index) |sect_id| {
22702255 const got = &self.sections.items(.header)[sect_id];
22712256 got.reserved1 = nstubs;
2272 for (self.got_entries.items) |entry| {
2273 const target_sym = entry.getTargetSymbol(self);
2257 for (self.got_table.entries.items) |entry| {
2258 if (!self.got_table.lookup.contains(entry)) continue;
2259 const target_sym = self.getSymbol(entry);
22742260 if (target_sym.undf()) {
2275 try writer.writeIntLittle(u32, iundefsym + ctx.imports_table.get(entry.target).?);
2261 try writer.writeIntLittle(u32, iundefsym + ctx.imports_table.get(entry).?);
22762262 } else {
22772263 try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL);
22782264 }
......@@ -2496,12 +2482,10 @@ pub const Zld = struct {
24962482 }
24972483 }
24982484
2499 /// Returns GOT atom that references `sym_with_loc` if one exists.
2500 /// Returns null otherwise.
2501 pub fn getGotAtomIndexForSymbol(self: *Zld, sym_with_loc: SymbolWithLoc) ?AtomIndex {
2502 const index = self.got_table.get(sym_with_loc) orelse return null;
2503 const entry = self.got_entries.items[index];
2504 return entry.atom_index;
2485 pub fn getGotEntryAddress(self: *Zld, sym_with_loc: SymbolWithLoc) ?u64 {
2486 const index = self.got_table.lookup.get(sym_with_loc) orelse return null;
2487 const header = self.sections.items(.header)[self.got_section_index.?];
2488 return header.addr + @sizeOf(u64) * index;
25052489 }
25062490
25072491 /// Returns stubs atom that references `sym_with_loc` if one exists.
......@@ -2849,26 +2833,7 @@ pub const Zld = struct {
28492833 }
28502834
28512835 scoped_log.debug("GOT entries:", .{});
2852 for (self.got_entries.items, 0..) |entry, i| {
2853 const atom_sym = entry.getAtomSymbol(self);
2854 const target_sym = entry.getTargetSymbol(self);
2855 const target_sym_name = entry.getTargetSymbolName(self);
2856 if (target_sym.undf()) {
2857 scoped_log.debug(" {d}@{x} => import('{s}')", .{
2858 i,
2859 atom_sym.n_value,
2860 target_sym_name,
2861 });
2862 } else {
2863 scoped_log.debug(" {d}@{x} => local(%{d}) in object({?}) {s}", .{
2864 i,
2865 atom_sym.n_value,
2866 entry.target.sym_index,
2867 entry.target.file,
2868 logSymAttributes(target_sym, buf[0..4]),
2869 });
2870 }
2871 }
2836 scoped_log.debug("{}", .{self.got_table});
28722837
28732838 scoped_log.debug("__thread_ptrs entries:", .{});
28742839 for (self.tlv_ptr_entries.items, 0..) |entry, i| {
......@@ -3470,6 +3435,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
34703435 }
34713436
34723437 try zld.writeAtoms();
3438 try zld.writeGotEntries();
34733439 try eh_frame.write(&zld, &unwind_info);
34743440 try unwind_info.write(&zld);
34753441 try zld.writeLinkeditSegmentData();