authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-17 17:17:01+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-17 17:17:01+02:00
log5d2bf96c02b766a6ddeb3bd0e8594f2c70c9bfb6
tree03670257529c98e11f48b4e48f9274f250c42693
parentbb70501060a8bfff25818cf1d80491d724f8a634
parentdf9ac485da7c59ddb5dc65e192d5902baf975ddd
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21098 from ziglang/macho-zig-got

macho: replace __got_zig with distributed jump table

11 files changed, 147 insertions(+), 272 deletions(-)

src/arch/x86_64/CodeGen.zig+25-23
...@@ -12364,13 +12364,10 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12364,13 +12364,10 @@ fn genCall(self: *Self, info: union(enum) {
12364 const zo = macho_file.getZigObject().?;12364 const zo = macho_file.getZigObject().?;
12365 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);12365 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
12366 const sym = zo.symbols.items[sym_index];12366 const sym = zo.symbols.items[sym_index];
12367 try self.genSetReg(12367 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12368 .rax,12368 .atom_index = try self.owner.getSymbolIndex(self),
12369 Type.usize,12369 .sym_index = sym.nlist_idx,
12370 .{ .load_symbol = .{ .sym = sym.nlist_idx } },12370 }));
12371 .{},
12372 );
12373 try self.asmRegister(.{ ._, .call }, .rax);
12374 } else if (self.bin_file.cast(.plan9)) |p9| {12371 } else if (self.bin_file.cast(.plan9)) |p9| {
12375 const atom_index = try p9.seeNav(pt, func.owner_nav);12372 const atom_index = try p9.seeNav(pt, func.owner_nav);
12376 const atom = p9.getAtom(atom_index);12373 const atom = p9.getAtom(atom_index);
...@@ -12392,6 +12389,15 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12392,6 +12389,15 @@ fn genCall(self: *Self, info: union(enum) {
12392 .atom_index = try self.owner.getSymbolIndex(self),12389 .atom_index = try self.owner.getSymbolIndex(self),
12393 .sym_index = target_sym_index,12390 .sym_index = target_sym_index,
12394 }));12391 }));
12392 } else if (self.bin_file.cast(.macho)) |macho_file| {
12393 const target_sym_index = try macho_file.getGlobalSymbol(
12394 @"extern".name.toSlice(ip),
12395 @"extern".lib_name.toSlice(ip),
12396 );
12397 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12398 .atom_index = try self.owner.getSymbolIndex(self),
12399 .sym_index = target_sym_index,
12400 }));
12395 } else try self.genExternSymbolRef(12401 } else try self.genExternSymbolRef(
12396 .call,12402 .call,
12397 @"extern".lib_name.toSlice(ip),12403 @"extern".lib_name.toSlice(ip),
...@@ -12410,6 +12416,12 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12410,6 +12416,12 @@ fn genCall(self: *Self, info: union(enum) {
12410 .atom_index = try self.owner.getSymbolIndex(self),12416 .atom_index = try self.owner.getSymbolIndex(self),
12411 .sym_index = target_sym_index,12417 .sym_index = target_sym_index,
12412 }));12418 }));
12419 } else if (self.bin_file.cast(.macho)) |macho_file| {
12420 const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
12421 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12422 .atom_index = try self.owner.getSymbolIndex(self),
12423 .sym_index = target_sym_index,
12424 }));
12413 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),12425 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
12414 }12426 }
12415 return call_info.return_value.short;12427 return call_info.return_value.short;
...@@ -15335,15 +15347,6 @@ fn genExternSymbolRef(...@@ -15335,15 +15347,6 @@ fn genExternSymbolRef(
15335 .call => try self.asmRegister(.{ ._, .call }, .rax),15347 .call => try self.asmRegister(.{ ._, .call }, .rax),
15336 else => unreachable,15348 else => unreachable,
15337 }15349 }
15338 } else if (self.bin_file.cast(.macho)) |macho_file| {
15339 _ = try self.addInst(.{
15340 .tag = .call,
15341 .ops = .extern_fn_reloc,
15342 .data = .{ .reloc = .{
15343 .atom_index = atom_index,
15344 .sym_index = try macho_file.getGlobalSymbol(callee, lib),
15345 } },
15346 });
15347 } else return self.fail("TODO implement calling extern functions", .{});15350 } else return self.fail("TODO implement calling extern functions", .{});
15348}15351}
1534915352
...@@ -15434,13 +15437,12 @@ fn genLazySymbolRef(...@@ -15434,13 +15437,12 @@ fn genLazySymbolRef(
15434 return self.fail("{s} creating lazy symbol", .{@errorName(err)});15437 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
15435 const sym = zo.symbols.items[sym_index];15438 const sym = zo.symbols.items[sym_index];
15436 switch (tag) {15439 switch (tag) {
15437 .lea, .call => try self.genSetReg(15440 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15438 reg,15441 .lea_symbol = .{ .sym = sym.nlist_idx },
15439 Type.usize,15442 }, .{}),
15440 .{ .load_symbol = .{ .sym = sym.nlist_idx } },15443 .mov => try self.genSetReg(reg, Type.usize, .{
15441 .{},15444 .load_symbol = .{ .sym = sym.nlist_idx },
15442 ),15445 }, .{}),
15443 .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }, .{}),
15444 else => unreachable,15446 else => unreachable,
15445 }15447 }
15446 switch (tag) {15448 switch (tag) {
src/arch/x86_64/Emit.zig+2-14
...@@ -135,23 +135,11 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -135,23 +135,11 @@ pub fn emitMir(emit: *Emit) Error!void {
135 });135 });
136 }136 }
137 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {137 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
138 const is_obj_or_static_lib = switch (emit.lower.output_mode) {
139 .Exe => false,
140 .Obj => true,
141 .Lib => emit.lower.link_mode == .static,
142 };
143 const zo = macho_file.getZigObject().?;138 const zo = macho_file.getZigObject().?;
144 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;139 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
145 const sym = &zo.symbols.items[data.sym_index];140 const sym = &zo.symbols.items[data.sym_index];
146 if (sym.getSectionFlags().needs_zig_got and !is_obj_or_static_lib) {141 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)
147 _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);142 .got_load
148 }
149 const @"type": link.File.MachO.Relocation.Type = if (sym.getSectionFlags().needs_zig_got and !is_obj_or_static_lib)
150 .zig_got_load
151 else if (sym.getSectionFlags().needs_got)
152 // TODO: it is possible to emit .got_load here that can potentially be relaxed
153 // however this requires always to use a MOVQ mnemonic
154 .got
155 else if (sym.flags.tlv)143 else if (sym.flags.tlv)
156 .tlv144 .tlv
157 else145 else
src/arch/x86_64/Lower.zig+13-7
...@@ -328,12 +328,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {...@@ -328,12 +328,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
328}328}
329329
330fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {330fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
331 const is_obj_or_static_lib = switch (lower.output_mode) {
332 .Exe => false,
333 .Obj => true,
334 .Lib => lower.link_mode == .static,
335 };
336
337 const emit_prefix = prefix;331 const emit_prefix = prefix;
338 var emit_mnemonic = mnemonic;332 var emit_mnemonic = mnemonic;
339 var emit_ops_storage: [4]Operand = undefined;333 var emit_ops_storage: [4]Operand = undefined;
...@@ -455,10 +449,22 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -455,10 +449,22 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
455 _ = lower.reloc(.{ .linker_reloc = sym });449 _ = lower.reloc(.{ .linker_reloc = sym });
456 break :op switch (mnemonic) {450 break :op switch (mnemonic) {
457 .lea => {451 .lea => {
452 if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
458 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };453 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
459 },454 },
460 .mov => {455 .mov => {
461 if (is_obj_or_static_lib and macho_sym.getSectionFlags().needs_zig_got) emit_mnemonic = .lea;456 if (macho_sym.flags.is_extern_ptr) {
457 const reg = ops[0].reg;
458 lower.result_insts[lower.result_insts_len] =
459 try Instruction.new(.none, .mov, &[_]Operand{
460 .{ .reg = reg.to64() },
461 .{ .mem = Memory.rip(.qword, 0) },
462 });
463 lower.result_insts_len += 1;
464 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ .base = .{
465 .reg = reg.to64(),
466 } }) };
467 }
462 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };468 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
463 },469 },
464 else => unreachable,470 else => unreachable,
src/codegen.zig+3-3
...@@ -910,15 +910,15 @@ fn genNavRef(...@@ -910,15 +910,15 @@ fn genNavRef(
910 const zo = macho_file.getZigObject().?;910 const zo = macho_file.getZigObject().?;
911 if (is_extern) {911 if (is_extern) {
912 const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));912 const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
913 zo.symbols.items[sym_index].setSectionFlags(.{ .needs_got = true });913 zo.symbols.items[sym_index].flags.is_extern_ptr = true;
914 return .{ .mcv = .{ .load_symbol = sym_index } };914 return .{ .mcv = .{ .lea_symbol = sym_index } };
915 }915 }
916 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);916 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index);
917 const sym = zo.symbols.items[sym_index];917 const sym = zo.symbols.items[sym_index];
918 if (!single_threaded and is_threadlocal) {918 if (!single_threaded and is_threadlocal) {
919 return .{ .mcv = .{ .load_tlv = sym.nlist_idx } };919 return .{ .mcv = .{ .load_tlv = sym.nlist_idx } };
920 }920 }
921 return .{ .mcv = .{ .load_symbol = sym.nlist_idx } };921 return .{ .mcv = .{ .lea_symbol = sym.nlist_idx } };
922 } else if (lf.cast(.coff)) |coff_file| {922 } else if (lf.cast(.coff)) |coff_file| {
923 if (is_extern) {923 if (is_extern) {
924 // TODO audit this924 // TODO audit this
src/link/MachO.zig-29
...@@ -59,7 +59,6 @@ symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},...@@ -59,7 +59,6 @@ symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
59strtab: std.ArrayListUnmanaged(u8) = .{},59strtab: std.ArrayListUnmanaged(u8) = .{},
60indsymtab: Indsymtab = .{},60indsymtab: Indsymtab = .{},
61got: GotSection = .{},61got: GotSection = .{},
62zig_got: ZigGotSection = .{},
63stubs: StubsSection = .{},62stubs: StubsSection = .{},
64stubs_helper: StubsHelperSection = .{},63stubs_helper: StubsHelperSection = .{},
65objc_stubs: ObjcStubsSection = .{},64objc_stubs: ObjcStubsSection = .{},
...@@ -75,14 +74,12 @@ data_in_code: DataInCode = .{},...@@ -75,14 +74,12 @@ data_in_code: DataInCode = .{},
7574
76/// Tracked loadable segments during incremental linking.75/// Tracked loadable segments during incremental linking.
77zig_text_seg_index: ?u8 = null,76zig_text_seg_index: ?u8 = null,
78zig_got_seg_index: ?u8 = null,
79zig_const_seg_index: ?u8 = null,77zig_const_seg_index: ?u8 = null,
80zig_data_seg_index: ?u8 = null,78zig_data_seg_index: ?u8 = null,
81zig_bss_seg_index: ?u8 = null,79zig_bss_seg_index: ?u8 = null,
8280
83/// Tracked section headers with incremental updates to Zig object.81/// Tracked section headers with incremental updates to Zig object.
84zig_text_sect_index: ?u8 = null,82zig_text_sect_index: ?u8 = null,
85zig_got_sect_index: ?u8 = null,
86zig_const_sect_index: ?u8 = null,83zig_const_sect_index: ?u8 = null,
87zig_data_sect_index: ?u8 = null,84zig_data_sect_index: ?u8 = null,
88zig_bss_sect_index: ?u8 = null,85zig_bss_sect_index: ?u8 = null,
...@@ -324,7 +321,6 @@ pub fn deinit(self: *MachO) void {...@@ -324,7 +321,6 @@ pub fn deinit(self: *MachO) void {
324 self.symtab.deinit(gpa);321 self.symtab.deinit(gpa);
325 self.strtab.deinit(gpa);322 self.strtab.deinit(gpa);
326 self.got.deinit(gpa);323 self.got.deinit(gpa);
327 self.zig_got.deinit(gpa);
328 self.stubs.deinit(gpa);324 self.stubs.deinit(gpa);
329 self.objc_stubs.deinit(gpa);325 self.objc_stubs.deinit(gpa);
330 self.tlv_ptr.deinit(gpa);326 self.tlv_ptr.deinit(gpa);
...@@ -1796,7 +1792,6 @@ pub fn sortSections(self: *MachO) !void {...@@ -1796,7 +1792,6 @@ pub fn sortSections(self: *MachO) !void {
1796 &self.data_sect_index,1792 &self.data_sect_index,
1797 &self.got_sect_index,1793 &self.got_sect_index,
1798 &self.zig_text_sect_index,1794 &self.zig_text_sect_index,
1799 &self.zig_got_sect_index,
1800 &self.zig_const_sect_index,1795 &self.zig_const_sect_index,
1801 &self.zig_data_sect_index,1796 &self.zig_data_sect_index,
1802 &self.zig_bss_sect_index,1797 &self.zig_bss_sect_index,
...@@ -2114,7 +2109,6 @@ fn initSegments(self: *MachO) !void {...@@ -2114,7 +2109,6 @@ fn initSegments(self: *MachO) !void {
2114 &self.text_seg_index,2109 &self.text_seg_index,
2115 &self.linkedit_seg_index,2110 &self.linkedit_seg_index,
2116 &self.zig_text_seg_index,2111 &self.zig_text_seg_index,
2117 &self.zig_got_seg_index,
2118 &self.zig_const_seg_index,2112 &self.zig_const_seg_index,
2119 &self.zig_data_seg_index,2113 &self.zig_data_seg_index,
2120 &self.zig_bss_seg_index,2114 &self.zig_bss_seg_index,
...@@ -3231,18 +3225,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {...@@ -3231,18 +3225,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3231 });3225 });
3232 }3226 }
32333227
3234 {
3235 const filesize = options.symbol_count_hint * @sizeOf(u64);
3236 const off = try self.findFreeSpace(filesize, self.getPageSize());
3237 self.zig_got_seg_index = try self.addSegment("__GOT_ZIG", .{
3238 .fileoff = off,
3239 .filesize = filesize,
3240 .vmaddr = base_vmaddr + 0x4000000,
3241 .vmsize = filesize,
3242 .prot = macho.PROT.READ | macho.PROT.WRITE,
3243 });
3244 }
3245
3246 {3228 {
3247 const filesize: u64 = 1024;3229 const filesize: u64 = 1024;
3248 const off = try self.findFreeSpace(filesize, self.getPageSize());3230 const off = try self.findFreeSpace(filesize, self.getPageSize());
...@@ -3343,13 +3325,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {...@@ -3343,13 +3325,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3343 }3325 }
3344 }3326 }
33453327
3346 if (!self.base.isRelocatable()) {
3347 self.zig_got_sect_index = try self.addSection("__GOT_ZIG", "__got_zig", .{
3348 .alignment = 3,
3349 });
3350 appendSect(self, self.zig_got_sect_index.?, self.zig_got_seg_index.?);
3351 }
3352
3353 {3328 {
3354 self.zig_const_sect_index = try self.addSection("__CONST_ZIG", "__const_zig", .{});3329 self.zig_const_sect_index = try self.addSection("__CONST_ZIG", "__const_zig", .{});
3355 if (self.base.isRelocatable()) {3330 if (self.base.isRelocatable()) {
...@@ -3572,7 +3547,6 @@ inline fn requiresThunks(self: MachO) bool {...@@ -3572,7 +3547,6 @@ inline fn requiresThunks(self: MachO) bool {
3572pub fn isZigSegment(self: MachO, seg_id: u8) bool {3547pub fn isZigSegment(self: MachO, seg_id: u8) bool {
3573 inline for (&[_]?u8{3548 inline for (&[_]?u8{
3574 self.zig_text_seg_index,3549 self.zig_text_seg_index,
3575 self.zig_got_seg_index,
3576 self.zig_const_seg_index,3550 self.zig_const_seg_index,
3577 self.zig_data_seg_index,3551 self.zig_data_seg_index,
3578 self.zig_bss_seg_index,3552 self.zig_bss_seg_index,
...@@ -3587,7 +3561,6 @@ pub fn isZigSegment(self: MachO, seg_id: u8) bool {...@@ -3587,7 +3561,6 @@ pub fn isZigSegment(self: MachO, seg_id: u8) bool {
3587pub fn isZigSection(self: MachO, sect_id: u8) bool {3561pub fn isZigSection(self: MachO, sect_id: u8) bool {
3588 inline for (&[_]?u8{3562 inline for (&[_]?u8{
3589 self.zig_text_sect_index,3563 self.zig_text_sect_index,
3590 self.zig_got_sect_index,
3591 self.zig_const_sect_index,3564 self.zig_const_sect_index,
3592 self.zig_data_sect_index,3565 self.zig_data_sect_index,
3593 self.zig_bss_sect_index,3566 self.zig_bss_sect_index,
...@@ -3957,7 +3930,6 @@ fn fmtDumpState(...@@ -3957,7 +3930,6 @@ fn fmtDumpState(
3957 try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)});3930 try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)});
3958 try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)});3931 try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)});
3959 try writer.print("got\n{}\n", .{self.got.fmt(self)});3932 try writer.print("got\n{}\n", .{self.got.fmt(self)});
3960 try writer.print("zig_got\n{}\n", .{self.zig_got.fmt(self)});
3961 try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)});3933 try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)});
3962 try writer.writeByte('\n');3934 try writer.writeByte('\n');
3963 try writer.print("sections\n{}\n", .{self.fmtSections()});3935 try writer.print("sections\n{}\n", .{self.fmtSections()});
...@@ -4665,7 +4637,6 @@ const Value = @import("../Value.zig");...@@ -4665,7 +4637,6 @@ const Value = @import("../Value.zig");
4665const UnwindInfo = @import("MachO/UnwindInfo.zig");4637const UnwindInfo = @import("MachO/UnwindInfo.zig");
4666const WaitGroup = std.Thread.WaitGroup;4638const WaitGroup = std.Thread.WaitGroup;
4667const WeakBind = bind.WeakBind;4639const WeakBind = bind.WeakBind;
4668const ZigGotSection = synthetic.ZigGotSection;
4669const ZigObject = @import("MachO/ZigObject.zig");4640const ZigObject = @import("MachO/ZigObject.zig");
4670const dev = @import("../dev.zig");4641const dev = @import("../dev.zig");
46714642
src/link/MachO/Atom.zig+1-21
...@@ -492,10 +492,6 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -492,10 +492,6 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
492 }492 }
493 },493 },
494494
495 .zig_got_load => {
496 assert(rel.getTargetSymbol(self, macho_file).getSectionFlags().has_zig_got);
497 },
498
499 .got => {495 .got => {
500 rel.getTargetSymbol(self, macho_file).setSectionFlags(.{ .needs_got = true });496 rel.getTargetSymbol(self, macho_file).setSectionFlags(.{ .needs_got = true });
501 },497 },
...@@ -652,8 +648,6 @@ fn resolveRelocInner(...@@ -652,8 +648,6 @@ fn resolveRelocInner(
652 const G: i64 = @intCast(rel.getGotTargetAddress(self, macho_file));648 const G: i64 = @intCast(rel.getGotTargetAddress(self, macho_file));
653 const TLS = @as(i64, @intCast(macho_file.getTlsAddress()));649 const TLS = @as(i64, @intCast(macho_file.getTlsAddress()));
654 const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(self, macho_file))) else 0;650 const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(self, macho_file))) else 0;
655 // Address of the __got_zig table entry if any.
656 const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(macho_file)));
657651
658 const divExact = struct {652 const divExact = struct {
659 fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 {653 fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 {
...@@ -676,13 +670,12 @@ fn resolveRelocInner(...@@ -676,13 +670,12 @@ fn resolveRelocInner(
676 S + A - SUB,670 S + A - SUB,
677 rel.getTargetAtom(self, macho_file).atom_index,671 rel.getTargetAtom(self, macho_file).atom_index,
678 }),672 }),
679 .@"extern" => relocs_log.debug(" {x}<+{d}>: {}: [=> {x}] G({x}) ZG({x}) ({s})", .{673 .@"extern" => relocs_log.debug(" {x}<+{d}>: {}: [=> {x}] G({x}) ({s})", .{
680 P,674 P,
681 rel_offset,675 rel_offset,
682 rel.fmtPretty(cpu_arch),676 rel.fmtPretty(cpu_arch),
683 S + A - SUB,677 S + A - SUB,
684 G + A,678 G + A,
685 ZIG_GOT + A,
686 rel.getTargetSymbol(self, macho_file).getName(macho_file),679 rel.getTargetSymbol(self, macho_file).getName(macho_file),
687 }),680 }),
688 }681 }
...@@ -745,17 +738,6 @@ fn resolveRelocInner(...@@ -745,17 +738,6 @@ fn resolveRelocInner(
745 }738 }
746 },739 },
747740
748 .zig_got_load => {
749 assert(rel.tag == .@"extern");
750 assert(rel.meta.length == 2);
751 assert(rel.meta.pcrel);
752 switch (cpu_arch) {
753 .x86_64 => try writer.writeInt(i32, @intCast(ZIG_GOT + A - P), .little),
754 .aarch64 => @panic("TODO resolve __got_zig indirection reloc"),
755 else => unreachable,
756 }
757 },
758
759 .tlv => {741 .tlv => {
760 assert(rel.tag == .@"extern");742 assert(rel.tag == .@"extern");
761 assert(rel.meta.length == 2);743 assert(rel.meta.length == 2);
...@@ -1065,7 +1047,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r...@@ -1065,7 +1047,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r
1065 .subtractor => .ARM64_RELOC_SUBTRACTOR,1047 .subtractor => .ARM64_RELOC_SUBTRACTOR,
1066 .unsigned => .ARM64_RELOC_UNSIGNED,1048 .unsigned => .ARM64_RELOC_UNSIGNED,
10671049
1068 .zig_got_load,
1069 .signed,1050 .signed,
1070 .signed1,1051 .signed1,
1071 .signed2,1052 .signed2,
...@@ -1109,7 +1090,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r...@@ -1109,7 +1090,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r
1109 .subtractor => .X86_64_RELOC_SUBTRACTOR,1090 .subtractor => .X86_64_RELOC_SUBTRACTOR,
1110 .unsigned => .X86_64_RELOC_UNSIGNED,1091 .unsigned => .X86_64_RELOC_UNSIGNED,
11111092
1112 .zig_got_load,
1113 .page,1093 .page,
1114 .pageoff,1094 .pageoff,
1115 .got_load_page,1095 .got_load_page,
src/link/MachO/Relocation.zig-3
...@@ -92,7 +92,6 @@ fn formatPretty(...@@ -92,7 +92,6 @@ fn formatPretty(
92 .signed4 => "X86_64_RELOC_SIGNED_4",92 .signed4 => "X86_64_RELOC_SIGNED_4",
93 .got_load => "X86_64_RELOC_GOT_LOAD",93 .got_load => "X86_64_RELOC_GOT_LOAD",
94 .tlv => "X86_64_RELOC_TLV",94 .tlv => "X86_64_RELOC_TLV",
95 .zig_got_load => "ZIG_GOT_LOAD",
96 .page => "ARM64_RELOC_PAGE21",95 .page => "ARM64_RELOC_PAGE21",
97 .pageoff => "ARM64_RELOC_PAGEOFF12",96 .pageoff => "ARM64_RELOC_PAGEOFF12",
98 .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21",97 .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21",
...@@ -137,8 +136,6 @@ pub const Type = enum {...@@ -137,8 +136,6 @@ pub const Type = enum {
137 got_load,136 got_load,
138 /// RIP-relative TLV load (X86_64_RELOC_TLV)137 /// RIP-relative TLV load (X86_64_RELOC_TLV)
139 tlv,138 tlv,
140 /// Zig-specific __got_zig indirection
141 zig_got_load,
142139
143 // arm64140 // arm64
144 /// PC-relative load (distance to page, ARM64_RELOC_PAGE21)141 /// PC-relative load (distance to page, ARM64_RELOC_PAGE21)
src/link/MachO/Symbol.zig+19-24
...@@ -123,6 +123,7 @@ pub fn getSymbolRank(symbol: Symbol, macho_file: *MachO) u32 {...@@ -123,6 +123,7 @@ pub fn getSymbolRank(symbol: Symbol, macho_file: *MachO) u32 {
123123
124pub fn getAddress(symbol: Symbol, opts: struct {124pub fn getAddress(symbol: Symbol, opts: struct {
125 stubs: bool = true,125 stubs: bool = true,
126 trampoline: bool = true,
126}, macho_file: *MachO) u64 {127}, macho_file: *MachO) u64 {
127 if (opts.stubs) {128 if (opts.stubs) {
128 if (symbol.getSectionFlags().stubs) {129 if (symbol.getSectionFlags().stubs) {
...@@ -131,6 +132,9 @@ pub fn getAddress(symbol: Symbol, opts: struct {...@@ -131,6 +132,9 @@ pub fn getAddress(symbol: Symbol, opts: struct {
131 return symbol.getObjcStubsAddress(macho_file);132 return symbol.getObjcStubsAddress(macho_file);
132 }133 }
133 }134 }
135 if (symbol.flags.trampoline and opts.trampoline) {
136 return symbol.getTrampolineAddress(macho_file);
137 }
134 if (symbol.getAtom(macho_file)) |atom| return atom.getAddress(macho_file) + symbol.value;138 if (symbol.getAtom(macho_file)) |atom| return atom.getAddress(macho_file) + symbol.value;
135 return symbol.value;139 return symbol.value;
136}140}
...@@ -169,23 +173,11 @@ pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 {...@@ -169,23 +173,11 @@ pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 {
169 return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file);173 return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file);
170}174}
171175
172const GetOrCreateZigGotEntryResult = struct {176pub fn getTrampolineAddress(symbol: Symbol, macho_file: *MachO) u64 {
173 found_existing: bool,177 if (!symbol.flags.trampoline) return 0;
174 index: ZigGotSection.Index,178 const zo = macho_file.getZigObject().?;
175};179 const index = symbol.getExtra(macho_file).trampoline;
176180 return zo.symbols.items[index].getAddress(.{}, macho_file);
177pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, macho_file: *MachO) !GetOrCreateZigGotEntryResult {
178 assert(!macho_file.base.isRelocatable());
179 assert(symbol.getSectionFlags().needs_zig_got);
180 if (symbol.getSectionFlags().has_zig_got) return .{ .found_existing = true, .index = symbol.getExtra(macho_file).zig_got };
181 const index = try macho_file.zig_got.addSymbol(symbol_index, macho_file);
182 return .{ .found_existing = false, .index = index };
183}
184
185pub fn getZigGotAddress(symbol: Symbol, macho_file: *MachO) u64 {
186 if (!symbol.getSectionFlags().has_zig_got) return 0;
187 const extras = symbol.getExtra(macho_file);
188 return macho_file.zig_got.entryAddress(extras.zig_got, macho_file);
189}181}
190182
191pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 {183pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 {
...@@ -209,12 +201,12 @@ pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 {...@@ -209,12 +201,12 @@ pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 {
209201
210const AddExtraOpts = struct {202const AddExtraOpts = struct {
211 got: ?u32 = null,203 got: ?u32 = null,
212 zig_got: ?u32 = null,
213 stubs: ?u32 = null,204 stubs: ?u32 = null,
214 objc_stubs: ?u32 = null,205 objc_stubs: ?u32 = null,
215 objc_selrefs: ?u32 = null,206 objc_selrefs: ?u32 = null,
216 tlv_ptr: ?u32 = null,207 tlv_ptr: ?u32 = null,
217 symtab: ?u32 = null,208 symtab: ?u32 = null,
209 trampoline: ?u32 = null,
218};210};
219211
220pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) void {212pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) void {
...@@ -393,6 +385,13 @@ pub const Flags = packed struct {...@@ -393,6 +385,13 @@ pub const Flags = packed struct {
393385
394 /// Whether the symbol makes into the output symtab or not.386 /// Whether the symbol makes into the output symtab or not.
395 output_symtab: bool = false,387 output_symtab: bool = false,
388
389 /// ZigObject specific flags
390 /// Whether the symbol has a trampoline
391 trampoline: bool = false,
392
393 /// Whether the symbol is an extern pointer (as opposed to function).
394 is_extern_ptr: bool = false,
396};395};
397396
398pub const SectionFlags = packed struct(u8) {397pub const SectionFlags = packed struct(u8) {
...@@ -400,10 +399,6 @@ pub const SectionFlags = packed struct(u8) {...@@ -400,10 +399,6 @@ pub const SectionFlags = packed struct(u8) {
400 needs_got: bool = false,399 needs_got: bool = false,
401 has_got: bool = false,400 has_got: bool = false,
402401
403 /// Whether the symbol contains __got_zig indirection.
404 needs_zig_got: bool = false,
405 has_zig_got: bool = false,
406
407 /// Whether the symbols contains __stubs indirection.402 /// Whether the symbols contains __stubs indirection.
408 stubs: bool = false,403 stubs: bool = false,
409404
...@@ -413,7 +408,7 @@ pub const SectionFlags = packed struct(u8) {...@@ -413,7 +408,7 @@ pub const SectionFlags = packed struct(u8) {
413 /// Whether the symbol contains __objc_stubs indirection.408 /// Whether the symbol contains __objc_stubs indirection.
414 objc_stubs: bool = false,409 objc_stubs: bool = false,
415410
416 _: u1 = 0,411 _: u3 = 0,
417};412};
418413
419pub const Visibility = enum {414pub const Visibility = enum {
...@@ -432,12 +427,12 @@ pub const Visibility = enum {...@@ -432,12 +427,12 @@ pub const Visibility = enum {
432427
433pub const Extra = struct {428pub const Extra = struct {
434 got: u32 = 0,429 got: u32 = 0,
435 zig_got: u32 = 0,
436 stubs: u32 = 0,430 stubs: u32 = 0,
437 objc_stubs: u32 = 0,431 objc_stubs: u32 = 0,
438 objc_selrefs: u32 = 0,432 objc_selrefs: u32 = 0,
439 tlv_ptr: u32 = 0,433 tlv_ptr: u32 = 0,
440 symtab: u32 = 0,434 symtab: u32 = 0,
435 trampoline: u32 = 0,
441};436};
442437
443pub const Index = u32;438pub const Index = u32;
src/link/MachO/ZigObject.zig+84-28
...@@ -795,7 +795,15 @@ pub fn updateFunc(...@@ -795,7 +795,15 @@ pub fn updateFunc(
795 };795 };
796796
797 const sect_index = try self.getNavOutputSection(macho_file, zcu, func.owner_nav, code);797 const sect_index = try self.getNavOutputSection(macho_file, zcu, func.owner_nav, code);
798 const old_rva, const old_alignment = blk: {
799 const atom = self.symbols.items[sym_index].getAtom(macho_file).?;
800 break :blk .{ atom.value, atom.alignment };
801 };
798 try self.updateNavCode(macho_file, pt, func.owner_nav, sym_index, sect_index, code);802 try self.updateNavCode(macho_file, pt, func.owner_nav, sym_index, sect_index, code);
803 const new_rva, const new_alignment = blk: {
804 const atom = self.symbols.items[sym_index].getAtom(macho_file).?;
805 break :blk .{ atom.value, atom.alignment };
806 };
799807
800 if (dwarf_wip_nav) |*wip_nav| {808 if (dwarf_wip_nav) |*wip_nav| {
801 const sym = self.symbols.items[sym_index];809 const sym = self.symbols.items[sym_index];
...@@ -812,6 +820,42 @@ pub fn updateFunc(...@@ -812,6 +820,42 @@ pub fn updateFunc(
812 }820 }
813821
814 // Exports will be updated by `Zcu.processExports` after the update.822 // Exports will be updated by `Zcu.processExports` after the update.
823 if (old_rva != new_rva and old_rva > 0) {
824 // If we had to reallocate the function, we re-use the existing slot for a trampoline.
825 // In the rare case that the function has been further overaligned we skip creating a
826 // trampoline and update all symbols referring this function.
827 if (old_alignment.order(new_alignment) == .lt) {
828 @panic("TODO update all symbols referring this function");
829 }
830
831 // Create a trampoline to the new location at `old_rva`.
832 if (!self.symbols.items[sym_index].flags.trampoline) {
833 const name = try std.fmt.allocPrint(gpa, "{s}$trampoline", .{
834 self.symbols.items[sym_index].getName(macho_file),
835 });
836 defer gpa.free(name);
837 const name_off = try self.addString(gpa, name);
838 const tr_size = trampolineSize(macho_file.getTarget().cpu.arch);
839 const tr_sym_index = try self.newSymbolWithAtom(gpa, name_off, macho_file);
840 const tr_sym = &self.symbols.items[tr_sym_index];
841 tr_sym.out_n_sect = macho_file.zig_text_sect_index.?;
842 const tr_nlist = &self.symtab.items(.nlist)[tr_sym.nlist_idx];
843 tr_nlist.n_sect = macho_file.zig_text_sect_index.? + 1;
844 const tr_atom = tr_sym.getAtom(macho_file).?;
845 tr_atom.value = old_rva;
846 tr_atom.setAlive(true);
847 tr_atom.alignment = old_alignment;
848 tr_atom.out_n_sect = macho_file.zig_text_sect_index.?;
849 tr_atom.size = tr_size;
850 self.symtab.items(.size)[tr_sym.nlist_idx] = tr_size;
851 const target_sym = &self.symbols.items[sym_index];
852 target_sym.addExtra(.{ .trampoline = tr_sym_index }, macho_file);
853 target_sym.flags.trampoline = true;
854 }
855 const target_sym = self.symbols.items[sym_index];
856 const source_sym = self.symbols.items[target_sym.getExtra(macho_file).trampoline];
857 try writeTrampoline(source_sym, target_sym, macho_file);
858 }
815}859}
816860
817pub fn updateNav(861pub fn updateNav(
...@@ -836,7 +880,7 @@ pub fn updateNav(...@@ -836,7 +880,7 @@ pub fn updateNav(
836 const lib_name = @"extern".lib_name.toSlice(ip);880 const lib_name = @"extern".lib_name.toSlice(ip);
837 const index = try self.getGlobalSymbol(macho_file, name, lib_name);881 const index = try self.getGlobalSymbol(macho_file, name, lib_name);
838 const sym = &self.symbols.items[index];882 const sym = &self.symbols.items[index];
839 sym.setSectionFlags(.{ .needs_got = true });883 sym.flags.is_extern_ptr = true;
840 return;884 return;
841 },885 },
842 else => nav_val,886 else => nav_val,
...@@ -946,13 +990,6 @@ fn updateNavCode(...@@ -946,13 +990,6 @@ fn updateNavCode(
946 if (old_vaddr != atom.value) {990 if (old_vaddr != atom.value) {
947 sym.value = 0;991 sym.value = 0;
948 nlist.n_value = 0;992 nlist.n_value = 0;
949
950 if (!macho_file.base.isRelocatable()) {
951 log.debug(" (updating offset table entry)", .{});
952 assert(sym.getSectionFlags().has_zig_got);
953 const extra = sym.getExtra(macho_file);
954 try macho_file.zig_got.writeOne(macho_file, extra.zig_got);
955 }
956 }993 }
957 } else if (code.len < old_size) {994 } else if (code.len < old_size) {
958 atom.shrink(macho_file);995 atom.shrink(macho_file);
...@@ -965,13 +1002,7 @@ fn updateNavCode(...@@ -965,13 +1002,7 @@ fn updateNavCode(
965 errdefer self.freeNavMetadata(macho_file, sym_index);1002 errdefer self.freeNavMetadata(macho_file, sym_index);
9661003
967 sym.value = 0;1004 sym.value = 0;
968 sym.setSectionFlags(.{ .needs_zig_got = true });
969 nlist.n_value = 0;1005 nlist.n_value = 0;
970
971 if (!macho_file.base.isRelocatable()) {
972 const gop = try sym.getOrCreateZigGotEntry(sym_index, macho_file);
973 try macho_file.zig_got.writeOne(macho_file, gop.index);
974 }
975 }1006 }
9761007
977 if (!sect.isZerofill()) {1008 if (!sect.isZerofill()) {
...@@ -1381,14 +1412,8 @@ fn updateLazySymbol(...@@ -1381,14 +1412,8 @@ fn updateLazySymbol(
1381 errdefer self.freeNavMetadata(macho_file, symbol_index);1412 errdefer self.freeNavMetadata(macho_file, symbol_index);
13821413
1383 sym.value = 0;1414 sym.value = 0;
1384 sym.setSectionFlags(.{ .needs_zig_got = true });
1385 nlist.n_value = 0;1415 nlist.n_value = 0;
13861416
1387 if (!macho_file.base.isRelocatable()) {
1388 const gop = try sym.getOrCreateZigGotEntry(symbol_index, macho_file);
1389 try macho_file.zig_got.writeOne(macho_file, gop.index);
1390 }
1391
1392 const sect = macho_file.sections.items(.header)[output_section_index];1417 const sect = macho_file.sections.items(.header)[output_section_index];
1393 const file_offset = sect.offset + atom.value;1418 const file_offset = sect.offset + atom.value;
1394 try macho_file.base.file.?.pwriteAll(code, file_offset);1419 try macho_file.base.file.?.pwriteAll(code, file_offset);
...@@ -1448,6 +1473,31 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l...@@ -1448,6 +1473,31 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l
1448 return lookup_gop.value_ptr.*;1473 return lookup_gop.value_ptr.*;
1449}1474}
14501475
1476const max_trampoline_len = 12;
1477
1478fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {
1479 const len = switch (cpu_arch) {
1480 .x86_64 => 5, // jmp rel32
1481 else => @panic("TODO implement trampoline size for this CPU arch"),
1482 };
1483 comptime assert(len <= max_trampoline_len);
1484 return len;
1485}
1486
1487fn writeTrampoline(tr_sym: Symbol, target: Symbol, macho_file: *MachO) !void {
1488 const atom = tr_sym.getAtom(macho_file).?;
1489 const header = macho_file.sections.items(.header)[atom.out_n_sect];
1490 const fileoff = header.offset + atom.value;
1491 const source_addr = tr_sym.getAddress(.{}, macho_file);
1492 const target_addr = target.getAddress(.{ .trampoline = false }, macho_file);
1493 var buf: [max_trampoline_len]u8 = undefined;
1494 const out = switch (macho_file.getTarget().cpu.arch) {
1495 .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
1496 else => @panic("TODO implement write trampoline for this CPU arch"),
1497 };
1498 try macho_file.base.file.?.pwriteAll(out, fileoff);
1499}
1500
1451pub fn getOrCreateMetadataForNav(1501pub fn getOrCreateMetadataForNav(
1452 self: *ZigObject,1502 self: *ZigObject,
1453 macho_file: *MachO,1503 macho_file: *MachO,
...@@ -1460,8 +1510,6 @@ pub fn getOrCreateMetadataForNav(...@@ -1460,8 +1510,6 @@ pub fn getOrCreateMetadataForNav(
1460 const sym = &self.symbols.items[sym_index];1510 const sym = &self.symbols.items[sym_index];
1461 if (isThreadlocal(macho_file, nav_index)) {1511 if (isThreadlocal(macho_file, nav_index)) {
1462 sym.flags.tlv = true;1512 sym.flags.tlv = true;
1463 } else {
1464 sym.setSectionFlags(.{ .needs_zig_got = true });
1465 }1513 }
1466 gop.value_ptr.* = .{ .symbol_index = sym_index };1514 gop.value_ptr.* = .{ .symbol_index = sym_index };
1467 }1515 }
...@@ -1482,12 +1530,7 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -1482,12 +1530,7 @@ pub fn getOrCreateMetadataForLazySymbol(
1482 .const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state },1530 .const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state },
1483 };1531 };
1484 switch (state_ptr.*) {1532 switch (state_ptr.*) {
1485 .unused => {1533 .unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, .{}, macho_file),
1486 const symbol_index = try self.newSymbolWithAtom(pt.zcu.gpa, .{}, macho_file);
1487 const sym = &self.symbols.items[symbol_index];
1488 sym.setSectionFlags(.{ .needs_zig_got = true });
1489 symbol_index_ptr.* = symbol_index;
1490 },
1491 .pending_flush => return symbol_index_ptr.*,1534 .pending_flush => return symbol_index_ptr.*,
1492 .flushed => {},1535 .flushed => {},
1493 }1536 }
...@@ -1749,6 +1792,19 @@ const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymb...@@ -1749,6 +1792,19 @@ const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymb
1749const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation));1792const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation));
1750const TlvInitializerTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlvInitializer);1793const TlvInitializerTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlvInitializer);
17511794
1795const x86_64 = struct {
1796 fn writeTrampolineCode(source_addr: u64, target_addr: u64, buf: *[max_trampoline_len]u8) ![]u8 {
1797 const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr)) - 5;
1798 var bytes = [_]u8{
1799 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp rel32
1800 };
1801 assert(bytes.len == trampolineSize(.x86_64));
1802 mem.writeInt(i32, bytes[1..][0..4], @intCast(disp), .little);
1803 @memcpy(buf[0..bytes.len], &bytes);
1804 return buf[0..bytes.len];
1805 }
1806};
1807
1752const assert = std.debug.assert;1808const assert = std.debug.assert;
1753const builtin = @import("builtin");1809const builtin = @import("builtin");
1754const codegen = @import("../../codegen.zig");1810const codegen = @import("../../codegen.zig");
src/link/MachO/dyld_info/Rebase.zig-12
...@@ -56,18 +56,6 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {...@@ -56,18 +56,6 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {
56 }56 }
57 }57 }
5858
59 if (macho_file.zig_got_sect_index) |sid| {
60 const seg_id = macho_file.sections.items(.segment_id)[sid];
61 const seg = macho_file.segments.items[seg_id];
62 for (0..macho_file.zig_got.entries.items.len) |idx| {
63 const addr = macho_file.zig_got.entryAddress(@intCast(idx), macho_file);
64 try rebase.entries.append(gpa, .{
65 .offset = addr - seg.vmaddr,
66 .segment_id = seg_id,
67 });
68 }
69 }
70
71 if (macho_file.got_sect_index) |sid| {59 if (macho_file.got_sect_index) |sid| {
72 const seg_id = macho_file.sections.items(.segment_id)[sid];60 const seg_id = macho_file.sections.items(.segment_id)[sid];
73 const seg = macho_file.segments.items[seg_id];61 const seg = macho_file.segments.items[seg_id];
src/link/MachO/synthetic.zig-108
...@@ -1,111 +1,3 @@...@@ -1,111 +1,3 @@
1pub const ZigGotSection = struct {
2 entries: std.ArrayListUnmanaged(Symbol.Index) = .{},
3 dirty: bool = false,
4
5 pub const Index = u32;
6
7 pub fn deinit(zig_got: *ZigGotSection, allocator: Allocator) void {
8 zig_got.entries.deinit(allocator);
9 }
10
11 fn allocateEntry(zig_got: *ZigGotSection, allocator: Allocator) !Index {
12 try zig_got.entries.ensureUnusedCapacity(allocator, 1);
13 // TODO add free list
14 const index = @as(Index, @intCast(zig_got.entries.items.len));
15 _ = zig_got.entries.addOneAssumeCapacity();
16 zig_got.dirty = true;
17 return index;
18 }
19
20 pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, macho_file: *MachO) !Index {
21 const gpa = macho_file.base.comp.gpa;
22 const zo = macho_file.getZigObject().?;
23 const index = try zig_got.allocateEntry(gpa);
24 const entry = &zig_got.entries.items[index];
25 entry.* = sym_index;
26 const symbol = &zo.symbols.items[sym_index];
27 assert(symbol.getSectionFlags().needs_zig_got);
28 symbol.setSectionFlags(.{ .has_zig_got = true });
29 symbol.addExtra(.{ .zig_got = index }, macho_file);
30 return index;
31 }
32
33 pub fn entryOffset(zig_got: ZigGotSection, index: Index, macho_file: *MachO) u64 {
34 _ = zig_got;
35 const sect = macho_file.sections.items(.header)[macho_file.zig_got_sect_index.?];
36 return sect.offset + @sizeOf(u64) * index;
37 }
38
39 pub fn entryAddress(zig_got: ZigGotSection, index: Index, macho_file: *MachO) u64 {
40 _ = zig_got;
41 const sect = macho_file.sections.items(.header)[macho_file.zig_got_sect_index.?];
42 return sect.addr + @sizeOf(u64) * index;
43 }
44
45 pub fn size(zig_got: ZigGotSection, macho_file: *MachO) usize {
46 _ = macho_file;
47 return @sizeOf(u64) * zig_got.entries.items.len;
48 }
49
50 pub fn writeOne(zig_got: *ZigGotSection, macho_file: *MachO, index: Index) !void {
51 if (zig_got.dirty) {
52 const needed_size = zig_got.size(macho_file);
53 try macho_file.growSection(macho_file.zig_got_sect_index.?, needed_size);
54 zig_got.dirty = false;
55 }
56 const zo = macho_file.getZigObject().?;
57 const off = zig_got.entryOffset(index, macho_file);
58 const entry = zig_got.entries.items[index];
59 const value = zo.symbols.items[entry].getAddress(.{ .stubs = false }, macho_file);
60
61 var buf: [8]u8 = undefined;
62 std.mem.writeInt(u64, &buf, value, .little);
63 try macho_file.base.file.?.pwriteAll(&buf, off);
64 }
65
66 pub fn writeAll(zig_got: ZigGotSection, macho_file: *MachO, writer: anytype) !void {
67 const zo = macho_file.getZigObject().?;
68 for (zig_got.entries.items) |entry| {
69 const symbol = zo.symbols.items[entry];
70 const value = symbol.address(.{ .stubs = false }, macho_file);
71 try writer.writeInt(u64, value, .little);
72 }
73 }
74
75 const FormatCtx = struct {
76 zig_got: ZigGotSection,
77 macho_file: *MachO,
78 };
79
80 pub fn fmt(zig_got: ZigGotSection, macho_file: *MachO) std.fmt.Formatter(format2) {
81 return .{ .data = .{ .zig_got = zig_got, .macho_file = macho_file } };
82 }
83
84 pub fn format2(
85 ctx: FormatCtx,
86 comptime unused_fmt_string: []const u8,
87 options: std.fmt.FormatOptions,
88 writer: anytype,
89 ) !void {
90 _ = options;
91 _ = unused_fmt_string;
92 const zig_got = ctx.zig_got;
93 const macho_file = ctx.macho_file;
94 try writer.writeAll("__zig_got\n");
95 for (zig_got.entries.items, 0..) |entry, index| {
96 const zo = macho_file.getZigObject().?;
97 const symbol = zo.symbols.items[entry];
98 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
99 index,
100 zig_got.entryAddress(@intCast(index), macho_file),
101 entry,
102 symbol.getAddress(.{}, macho_file),
103 symbol.getName(macho_file),
104 });
105 }
106 }
107};
108
109pub const GotSection = struct {1pub const GotSection = struct {
110 symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},2 symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
1113