| author | |
| committer | |
| log | 96441bd829b731cba080753c4833aff3f672a24a |
| tree | fc4d4d5eb4654d81dd09e91052be11b55fcb09f8 |
| parent | bb70501060a8bfff25818cf1d80491d724f8a634 |
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 | 12364 | const zo = macho_file.getZigObject().?; |
| 12365 | 12365 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav); |
| 12366 | 12366 | const sym = zo.symbols.items[sym_index]; |
| 12367 | try self.genSetReg( | |
| 12368 | .rax, | |
| 12369 | Type.usize, | |
| 12370 | .{ .load_symbol = .{ .sym = sym.nlist_idx } }, | |
| 12371 | .{}, | |
| 12372 | ); | |
| 12373 | try self.asmRegister(.{ ._, .call }, .rax); | |
| 12367 | try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ | |
| 12368 | .atom_index = try self.owner.getSymbolIndex(self), | |
| 12369 | .sym_index = sym.nlist_idx, | |
| 12370 | })); | |
| 12374 | 12371 | } else if (self.bin_file.cast(.plan9)) |p9| { |
| 12375 | 12372 | const atom_index = try p9.seeNav(pt, func.owner_nav); |
| 12376 | 12373 | const atom = p9.getAtom(atom_index); |
| ... | ... | @@ -12392,6 +12389,15 @@ fn genCall(self: *Self, info: union(enum) { |
| 12392 | 12389 | .atom_index = try self.owner.getSymbolIndex(self), |
| 12393 | 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 | 12401 | } else try self.genExternSymbolRef( |
| 12396 | 12402 | .call, |
| 12397 | 12403 | @"extern".lib_name.toSlice(ip), |
| ... | ... | @@ -12410,6 +12416,12 @@ fn genCall(self: *Self, info: union(enum) { |
| 12410 | 12416 | .atom_index = try self.owner.getSymbolIndex(self), |
| 12411 | 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 | 12425 | } else try self.genExternSymbolRef(.call, lib.lib, lib.callee), |
| 12414 | 12426 | } |
| 12415 | 12427 | return call_info.return_value.short; |
| ... | ... | @@ -15335,15 +15347,6 @@ fn genExternSymbolRef( |
| 15335 | 15347 | .call => try self.asmRegister(.{ ._, .call }, .rax), |
| 15336 | 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 | 15350 | } else return self.fail("TODO implement calling extern functions", .{}); |
| 15348 | 15351 | } |
| 15349 | 15352 | |
| ... | ... | @@ -15434,13 +15437,12 @@ fn genLazySymbolRef( |
| 15434 | 15437 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); |
| 15435 | 15438 | const sym = zo.symbols.items[sym_index]; |
| 15436 | 15439 | switch (tag) { |
| 15437 | .lea, .call => try self.genSetReg( | |
| 15438 | reg, | |
| 15439 | Type.usize, | |
| 15440 | .{ .load_symbol = .{ .sym = sym.nlist_idx } }, | |
| 15441 | .{}, | |
| 15442 | ), | |
| 15443 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.nlist_idx } }, .{}), | |
| 15440 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ | |
| 15441 | .lea_symbol = .{ .sym = sym.nlist_idx }, | |
| 15442 | }, .{}), | |
| 15443 | .mov => try self.genSetReg(reg, Type.usize, .{ | |
| 15444 | .load_symbol = .{ .sym = sym.nlist_idx }, | |
| 15445 | }, .{}), | |
| 15444 | 15446 | else => unreachable, |
| 15445 | 15447 | } |
| 15446 | 15448 | switch (tag) { |
src/arch/x86_64/Emit.zig+2-14| ... | ... | @@ -135,23 +135,11 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 135 | 135 | }); |
| 136 | 136 | } |
| 137 | 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 | 138 | const zo = macho_file.getZigObject().?; |
| 144 | 139 | const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?; |
| 145 | 140 | const sym = &zo.symbols.items[data.sym_index]; |
| 146 | if (sym.getSectionFlags().needs_zig_got and !is_obj_or_static_lib) { | |
| 147 | _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file); | |
| 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 | |
| 141 | const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr) | |
| 142 | .got_load | |
| 155 | 143 | else if (sym.flags.tlv) |
| 156 | 144 | .tlv |
| 157 | 145 | else |
src/arch/x86_64/Lower.zig+13-7| ... | ... | @@ -328,12 +328,6 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { |
| 328 | 328 | } |
| 329 | 329 | |
| 330 | 330 | fn 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 | 331 | const emit_prefix = prefix; |
| 338 | 332 | var emit_mnemonic = mnemonic; |
| 339 | 333 | var emit_ops_storage: [4]Operand = undefined; |
| ... | ... | @@ -455,10 +449,22 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 455 | 449 | _ = lower.reloc(.{ .linker_reloc = sym }); |
| 456 | 450 | break :op switch (mnemonic) { |
| 457 | 451 | .lea => { |
| 452 | if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov; | |
| 458 | 453 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; |
| 459 | 454 | }, |
| 460 | 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 | 468 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; |
| 463 | 469 | }, |
| 464 | 470 | else => unreachable, |
src/codegen.zig+3-3| ... | ... | @@ -910,15 +910,15 @@ fn genNavRef( |
| 910 | 910 | const zo = macho_file.getZigObject().?; |
| 911 | 911 | if (is_extern) { |
| 912 | 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 }); | |
| 914 | return .{ .mcv = .{ .load_symbol = sym_index } }; | |
| 913 | zo.symbols.items[sym_index].flags.is_extern_ptr = true; | |
| 914 | return GenResult.mcv(.{ .lea_symbol = sym_index }); | |
| 915 | 915 | } |
| 916 | 916 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); |
| 917 | 917 | const sym = zo.symbols.items[sym_index]; |
| 918 | 918 | if (!single_threaded and is_threadlocal) { |
| 919 | 919 | return .{ .mcv = .{ .load_tlv = sym.nlist_idx } }; |
| 920 | 920 | } |
| 921 | return .{ .mcv = .{ .load_symbol = sym.nlist_idx } }; | |
| 921 | return GenResult.mcv(.{ .lea_symbol = sym.nlist_idx }); | |
| 922 | 922 | } else if (lf.cast(.coff)) |coff_file| { |
| 923 | 923 | if (is_extern) { |
| 924 | 924 | // TODO audit this |
src/link/MachO.zig-29| ... | ... | @@ -59,7 +59,6 @@ symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 59 | 59 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 60 | 60 | indsymtab: Indsymtab = .{}, |
| 61 | 61 | got: GotSection = .{}, |
| 62 | zig_got: ZigGotSection = .{}, | |
| 63 | 62 | stubs: StubsSection = .{}, |
| 64 | 63 | stubs_helper: StubsHelperSection = .{}, |
| 65 | 64 | objc_stubs: ObjcStubsSection = .{}, |
| ... | ... | @@ -75,14 +74,12 @@ data_in_code: DataInCode = .{}, |
| 75 | 74 | |
| 76 | 75 | /// Tracked loadable segments during incremental linking. |
| 77 | 76 | zig_text_seg_index: ?u8 = null, |
| 78 | zig_got_seg_index: ?u8 = null, | |
| 79 | 77 | zig_const_seg_index: ?u8 = null, |
| 80 | 78 | zig_data_seg_index: ?u8 = null, |
| 81 | 79 | zig_bss_seg_index: ?u8 = null, |
| 82 | 80 | |
| 83 | 81 | /// Tracked section headers with incremental updates to Zig object. |
| 84 | 82 | zig_text_sect_index: ?u8 = null, |
| 85 | zig_got_sect_index: ?u8 = null, | |
| 86 | 83 | zig_const_sect_index: ?u8 = null, |
| 87 | 84 | zig_data_sect_index: ?u8 = null, |
| 88 | 85 | zig_bss_sect_index: ?u8 = null, |
| ... | ... | @@ -324,7 +321,6 @@ pub fn deinit(self: *MachO) void { |
| 324 | 321 | self.symtab.deinit(gpa); |
| 325 | 322 | self.strtab.deinit(gpa); |
| 326 | 323 | self.got.deinit(gpa); |
| 327 | self.zig_got.deinit(gpa); | |
| 328 | 324 | self.stubs.deinit(gpa); |
| 329 | 325 | self.objc_stubs.deinit(gpa); |
| 330 | 326 | self.tlv_ptr.deinit(gpa); |
| ... | ... | @@ -1796,7 +1792,6 @@ pub fn sortSections(self: *MachO) !void { |
| 1796 | 1792 | &self.data_sect_index, |
| 1797 | 1793 | &self.got_sect_index, |
| 1798 | 1794 | &self.zig_text_sect_index, |
| 1799 | &self.zig_got_sect_index, | |
| 1800 | 1795 | &self.zig_const_sect_index, |
| 1801 | 1796 | &self.zig_data_sect_index, |
| 1802 | 1797 | &self.zig_bss_sect_index, |
| ... | ... | @@ -2114,7 +2109,6 @@ fn initSegments(self: *MachO) !void { |
| 2114 | 2109 | &self.text_seg_index, |
| 2115 | 2110 | &self.linkedit_seg_index, |
| 2116 | 2111 | &self.zig_text_seg_index, |
| 2117 | &self.zig_got_seg_index, | |
| 2118 | 2112 | &self.zig_const_seg_index, |
| 2119 | 2113 | &self.zig_data_seg_index, |
| 2120 | 2114 | &self.zig_bss_seg_index, |
| ... | ... | @@ -3231,18 +3225,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { |
| 3231 | 3225 | }); |
| 3232 | 3226 | } |
| 3233 | 3227 | |
| 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 | 3229 | const filesize: u64 = 1024; |
| 3248 | 3230 | const off = try self.findFreeSpace(filesize, self.getPageSize()); |
| ... | ... | @@ -3343,13 +3325,6 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { |
| 3343 | 3325 | } |
| 3344 | 3326 | } |
| 3345 | 3327 | |
| 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 | 3329 | self.zig_const_sect_index = try self.addSection("__CONST_ZIG", "__const_zig", .{}); |
| 3355 | 3330 | if (self.base.isRelocatable()) { |
| ... | ... | @@ -3572,7 +3547,6 @@ inline fn requiresThunks(self: MachO) bool { |
| 3572 | 3547 | pub fn isZigSegment(self: MachO, seg_id: u8) bool { |
| 3573 | 3548 | inline for (&[_]?u8{ |
| 3574 | 3549 | self.zig_text_seg_index, |
| 3575 | self.zig_got_seg_index, | |
| 3576 | 3550 | self.zig_const_seg_index, |
| 3577 | 3551 | self.zig_data_seg_index, |
| 3578 | 3552 | self.zig_bss_seg_index, |
| ... | ... | @@ -3587,7 +3561,6 @@ pub fn isZigSegment(self: MachO, seg_id: u8) bool { |
| 3587 | 3561 | pub fn isZigSection(self: MachO, sect_id: u8) bool { |
| 3588 | 3562 | inline for (&[_]?u8{ |
| 3589 | 3563 | self.zig_text_sect_index, |
| 3590 | self.zig_got_sect_index, | |
| 3591 | 3564 | self.zig_const_sect_index, |
| 3592 | 3565 | self.zig_data_sect_index, |
| 3593 | 3566 | self.zig_bss_sect_index, |
| ... | ... | @@ -3957,7 +3930,6 @@ fn fmtDumpState( |
| 3957 | 3930 | try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)}); |
| 3958 | 3931 | try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)}); |
| 3959 | 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 | 3933 | try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)}); |
| 3962 | 3934 | try writer.writeByte('\n'); |
| 3963 | 3935 | try writer.print("sections\n{}\n", .{self.fmtSections()}); |
| ... | ... | @@ -4665,7 +4637,6 @@ const Value = @import("../Value.zig"); |
| 4665 | 4637 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); |
| 4666 | 4638 | const WaitGroup = std.Thread.WaitGroup; |
| 4667 | 4639 | const WeakBind = bind.WeakBind; |
| 4668 | const ZigGotSection = synthetic.ZigGotSection; | |
| 4669 | 4640 | const ZigObject = @import("MachO/ZigObject.zig"); |
| 4670 | 4641 | const dev = @import("../dev.zig"); |
| 4671 | 4642 |
src/link/MachO/Atom.zig+1-21| ... | ... | @@ -492,10 +492,6 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void { |
| 492 | 492 | } |
| 493 | 493 | }, |
| 494 | 494 | |
| 495 | .zig_got_load => { | |
| 496 | assert(rel.getTargetSymbol(self, macho_file).getSectionFlags().has_zig_got); | |
| 497 | }, | |
| 498 | ||
| 499 | 495 | .got => { |
| 500 | 496 | rel.getTargetSymbol(self, macho_file).setSectionFlags(.{ .needs_got = true }); |
| 501 | 497 | }, |
| ... | ... | @@ -652,8 +648,6 @@ fn resolveRelocInner( |
| 652 | 648 | const G: i64 = @intCast(rel.getGotTargetAddress(self, macho_file)); |
| 653 | 649 | const TLS = @as(i64, @intCast(macho_file.getTlsAddress())); |
| 654 | 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))); | |
| 657 | 651 | |
| 658 | 652 | const divExact = struct { |
| 659 | 653 | fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 { |
| ... | ... | @@ -676,13 +670,12 @@ fn resolveRelocInner( |
| 676 | 670 | S + A - SUB, |
| 677 | 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 | 674 | P, |
| 681 | 675 | rel_offset, |
| 682 | 676 | rel.fmtPretty(cpu_arch), |
| 683 | 677 | S + A - SUB, |
| 684 | 678 | G + A, |
| 685 | ZIG_GOT + A, | |
| 686 | 679 | rel.getTargetSymbol(self, macho_file).getName(macho_file), |
| 687 | 680 | }), |
| 688 | 681 | } |
| ... | ... | @@ -745,17 +738,6 @@ fn resolveRelocInner( |
| 745 | 738 | } |
| 746 | 739 | }, |
| 747 | 740 | |
| 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 | 741 | .tlv => { |
| 760 | 742 | assert(rel.tag == .@"extern"); |
| 761 | 743 | assert(rel.meta.length == 2); |
| ... | ... | @@ -1065,7 +1047,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r |
| 1065 | 1047 | .subtractor => .ARM64_RELOC_SUBTRACTOR, |
| 1066 | 1048 | .unsigned => .ARM64_RELOC_UNSIGNED, |
| 1067 | 1049 | |
| 1068 | .zig_got_load, | |
| 1069 | 1050 | .signed, |
| 1070 | 1051 | .signed1, |
| 1071 | 1052 | .signed2, |
| ... | ... | @@ -1109,7 +1090,6 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r |
| 1109 | 1090 | .subtractor => .X86_64_RELOC_SUBTRACTOR, |
| 1110 | 1091 | .unsigned => .X86_64_RELOC_UNSIGNED, |
| 1111 | 1092 | |
| 1112 | .zig_got_load, | |
| 1113 | 1093 | .page, |
| 1114 | 1094 | .pageoff, |
| 1115 | 1095 | .got_load_page, |
src/link/MachO/Relocation.zig-3| ... | ... | @@ -92,7 +92,6 @@ fn formatPretty( |
| 92 | 92 | .signed4 => "X86_64_RELOC_SIGNED_4", |
| 93 | 93 | .got_load => "X86_64_RELOC_GOT_LOAD", |
| 94 | 94 | .tlv => "X86_64_RELOC_TLV", |
| 95 | .zig_got_load => "ZIG_GOT_LOAD", | |
| 96 | 95 | .page => "ARM64_RELOC_PAGE21", |
| 97 | 96 | .pageoff => "ARM64_RELOC_PAGEOFF12", |
| 98 | 97 | .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21", |
| ... | ... | @@ -137,8 +136,6 @@ pub const Type = enum { |
| 137 | 136 | got_load, |
| 138 | 137 | /// RIP-relative TLV load (X86_64_RELOC_TLV) |
| 139 | 138 | tlv, |
| 140 | /// Zig-specific __got_zig indirection | |
| 141 | zig_got_load, | |
| 142 | 139 | |
| 143 | 140 | // arm64 |
| 144 | 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 | 123 | |
| 124 | 124 | pub fn getAddress(symbol: Symbol, opts: struct { |
| 125 | 125 | stubs: bool = true, |
| 126 | trampoline: bool = true, | |
| 126 | 127 | }, macho_file: *MachO) u64 { |
| 127 | 128 | if (opts.stubs) { |
| 128 | 129 | if (symbol.getSectionFlags().stubs) { |
| ... | ... | @@ -131,6 +132,9 @@ pub fn getAddress(symbol: Symbol, opts: struct { |
| 131 | 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 | 138 | if (symbol.getAtom(macho_file)) |atom| return atom.getAddress(macho_file) + symbol.value; |
| 135 | 139 | return symbol.value; |
| 136 | 140 | } |
| ... | ... | @@ -169,23 +173,11 @@ pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 { |
| 169 | 173 | return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file); |
| 170 | 174 | } |
| 171 | 175 | |
| 172 | const GetOrCreateZigGotEntryResult = struct { | |
| 173 | found_existing: bool, | |
| 174 | index: ZigGotSection.Index, | |
| 175 | }; | |
| 176 | ||
| 177 | pub 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 | ||
| 185 | pub 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); | |
| 176 | pub fn getTrampolineAddress(symbol: Symbol, macho_file: *MachO) u64 { | |
| 177 | if (!symbol.flags.trampoline) return 0; | |
| 178 | const zo = macho_file.getZigObject().?; | |
| 179 | const index = symbol.getExtra(macho_file).trampoline; | |
| 180 | return zo.symbols.items[index].getAddress(.{}, macho_file); | |
| 189 | 181 | } |
| 190 | 182 | |
| 191 | 183 | pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 { |
| ... | ... | @@ -209,12 +201,12 @@ pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 { |
| 209 | 201 | |
| 210 | 202 | const AddExtraOpts = struct { |
| 211 | 203 | got: ?u32 = null, |
| 212 | zig_got: ?u32 = null, | |
| 213 | 204 | stubs: ?u32 = null, |
| 214 | 205 | objc_stubs: ?u32 = null, |
| 215 | 206 | objc_selrefs: ?u32 = null, |
| 216 | 207 | tlv_ptr: ?u32 = null, |
| 217 | 208 | symtab: ?u32 = null, |
| 209 | trampoline: ?u32 = null, | |
| 218 | 210 | }; |
| 219 | 211 | |
| 220 | 212 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, macho_file: *MachO) void { |
| ... | ... | @@ -393,6 +385,13 @@ pub const Flags = packed struct { |
| 393 | 385 | |
| 394 | 386 | /// Whether the symbol makes into the output symtab or not. |
| 395 | 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 | }; |
| 397 | 396 | |
| 398 | 397 | pub const SectionFlags = packed struct(u8) { |
| ... | ... | @@ -400,10 +399,6 @@ pub const SectionFlags = packed struct(u8) { |
| 400 | 399 | needs_got: bool = false, |
| 401 | 400 | has_got: bool = false, |
| 402 | 401 | |
| 403 | /// Whether the symbol contains __got_zig indirection. | |
| 404 | needs_zig_got: bool = false, | |
| 405 | has_zig_got: bool = false, | |
| 406 | ||
| 407 | 402 | /// Whether the symbols contains __stubs indirection. |
| 408 | 403 | stubs: bool = false, |
| 409 | 404 | |
| ... | ... | @@ -413,7 +408,7 @@ pub const SectionFlags = packed struct(u8) { |
| 413 | 408 | /// Whether the symbol contains __objc_stubs indirection. |
| 414 | 409 | objc_stubs: bool = false, |
| 415 | 410 | |
| 416 | _: u1 = 0, | |
| 411 | _: u3 = 0, | |
| 417 | 412 | }; |
| 418 | 413 | |
| 419 | 414 | pub const Visibility = enum { |
| ... | ... | @@ -432,12 +427,12 @@ pub const Visibility = enum { |
| 432 | 427 | |
| 433 | 428 | pub const Extra = struct { |
| 434 | 429 | got: u32 = 0, |
| 435 | zig_got: u32 = 0, | |
| 436 | 430 | stubs: u32 = 0, |
| 437 | 431 | objc_stubs: u32 = 0, |
| 438 | 432 | objc_selrefs: u32 = 0, |
| 439 | 433 | tlv_ptr: u32 = 0, |
| 440 | 434 | symtab: u32 = 0, |
| 435 | trampoline: u32 = 0, | |
| 441 | 436 | }; |
| 442 | 437 | |
| 443 | 438 | pub const Index = u32; |
src/link/MachO/ZigObject.zig+84-28| ... | ... | @@ -795,7 +795,15 @@ pub fn updateFunc( |
| 795 | 795 | }; |
| 796 | 796 | |
| 797 | 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 | 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 | }; | |
| 799 | 807 | |
| 800 | 808 | if (dwarf_wip_nav) |*wip_nav| { |
| 801 | 809 | const sym = self.symbols.items[sym_index]; |
| ... | ... | @@ -812,6 +820,42 @@ pub fn updateFunc( |
| 812 | 820 | } |
| 813 | 821 | |
| 814 | 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 | } |
| 816 | 860 | |
| 817 | 861 | pub fn updateNav( |
| ... | ... | @@ -836,7 +880,7 @@ pub fn updateNav( |
| 836 | 880 | const lib_name = @"extern".lib_name.toSlice(ip); |
| 837 | 881 | const index = try self.getGlobalSymbol(macho_file, name, lib_name); |
| 838 | 882 | const sym = &self.symbols.items[index]; |
| 839 | sym.setSectionFlags(.{ .needs_got = true }); | |
| 883 | sym.flags.is_extern_ptr = true; | |
| 840 | 884 | return; |
| 841 | 885 | }, |
| 842 | 886 | else => nav_val, |
| ... | ... | @@ -946,13 +990,6 @@ fn updateNavCode( |
| 946 | 990 | if (old_vaddr != atom.value) { |
| 947 | 991 | sym.value = 0; |
| 948 | 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 | 994 | } else if (code.len < old_size) { |
| 958 | 995 | atom.shrink(macho_file); |
| ... | ... | @@ -965,13 +1002,7 @@ fn updateNavCode( |
| 965 | 1002 | errdefer self.freeNavMetadata(macho_file, sym_index); |
| 966 | 1003 | |
| 967 | 1004 | sym.value = 0; |
| 968 | sym.setSectionFlags(.{ .needs_zig_got = true }); | |
| 969 | 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 | } |
| 976 | 1007 | |
| 977 | 1008 | if (!sect.isZerofill()) { |
| ... | ... | @@ -1381,14 +1412,8 @@ fn updateLazySymbol( |
| 1381 | 1412 | errdefer self.freeNavMetadata(macho_file, symbol_index); |
| 1382 | 1413 | |
| 1383 | 1414 | sym.value = 0; |
| 1384 | sym.setSectionFlags(.{ .needs_zig_got = true }); | |
| 1385 | 1415 | nlist.n_value = 0; |
| 1386 | 1416 | |
| 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 | 1417 | const sect = macho_file.sections.items(.header)[output_section_index]; |
| 1393 | 1418 | const file_offset = sect.offset + atom.value; |
| 1394 | 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 | 1473 | return lookup_gop.value_ptr.*; |
| 1449 | 1474 | } |
| 1450 | 1475 | |
| 1476 | const max_trampoline_len = 12; | |
| 1477 | ||
| 1478 | fn 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 | ||
| 1487 | fn 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 | ||
| 1451 | 1501 | pub fn getOrCreateMetadataForNav( |
| 1452 | 1502 | self: *ZigObject, |
| 1453 | 1503 | macho_file: *MachO, |
| ... | ... | @@ -1460,8 +1510,6 @@ pub fn getOrCreateMetadataForNav( |
| 1460 | 1510 | const sym = &self.symbols.items[sym_index]; |
| 1461 | 1511 | if (isThreadlocal(macho_file, nav_index)) { |
| 1462 | 1512 | sym.flags.tlv = true; |
| 1463 | } else { | |
| 1464 | sym.setSectionFlags(.{ .needs_zig_got = true }); | |
| 1465 | 1513 | } |
| 1466 | 1514 | gop.value_ptr.* = .{ .symbol_index = sym_index }; |
| 1467 | 1515 | } |
| ... | ... | @@ -1482,12 +1530,7 @@ pub fn getOrCreateMetadataForLazySymbol( |
| 1482 | 1530 | .const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state }, |
| 1483 | 1531 | }; |
| 1484 | 1532 | switch (state_ptr.*) { |
| 1485 | .unused => { | |
| 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 | }, | |
| 1533 | .unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, .{}, macho_file), | |
| 1491 | 1534 | .pending_flush => return symbol_index_ptr.*, |
| 1492 | 1535 | .flushed => {}, |
| 1493 | 1536 | } |
| ... | ... | @@ -1749,6 +1792,19 @@ const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymb |
| 1749 | 1792 | const RelocationTable = std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)); |
| 1750 | 1793 | const TlvInitializerTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlvInitializer); |
| 1751 | 1794 | |
| 1795 | const 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 | ||
| 1752 | 1808 | const assert = std.debug.assert; |
| 1753 | 1809 | const builtin = @import("builtin"); |
| 1754 | 1810 | const 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 | 56 | } |
| 57 | 57 | } |
| 58 | 58 | |
| 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 | 59 | if (macho_file.got_sect_index) |sid| { |
| 72 | 60 | const seg_id = macho_file.sections.items(.segment_id)[sid]; |
| 73 | 61 | const seg = macho_file.segments.items[seg_id]; |
src/link/MachO/synthetic.zig-108| ... | ... | @@ -1,111 +1,3 @@ |
| 1 | pub 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 | ||
| 109 | 1 | pub const GotSection = struct { |
| 110 | 2 | symbols: std.ArrayListUnmanaged(MachO.Ref) = .{}, |
| 111 | 3 |