| author | |
| committer | |
| log | af40bce08adf232c9f6b9016810a24f7d0260399 |
| tree | 3933dcd1ea2016bb709b6a5bd3aba880f89dfaff |
| parent | 8e1421f19ef3daea9b8a414bd5783189bc292676 |
5 files changed, 66 insertions(+), 12 deletions(-)
src/arch/x86_64/CodeGen.zig+25-10| ... | ... | @@ -8223,11 +8223,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8223 | 8223 | const sym = elf_file.symbol(sym_index); |
| 8224 | 8224 | sym.flags.needs_got = true; |
| 8225 | 8225 | _ = try sym.getOrCreateGotEntry(sym_index, elf_file); |
| 8226 | const got_addr = sym.gotAddress(elf_file); | |
| 8227 | try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{ | |
| 8228 | .base = .{ .reg = .ds }, | |
| 8229 | .disp = @intCast(got_addr), | |
| 8230 | })); | |
| 8226 | _ = try self.addInst(.{ | |
| 8227 | .tag = .call, | |
| 8228 | .ops = .direct_got_reloc, | |
| 8229 | .data = .{ .reloc = .{ | |
| 8230 | .atom_index = try self.owner.getSymbolIndex(self), | |
| 8231 | .sym_index = sym.esym_index, | |
| 8232 | } }, | |
| 8233 | }); | |
| 8231 | 8234 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 8232 | 8235 | const atom = try coff_file.getOrCreateAtomForDecl(owner_decl); |
| 8233 | 8236 | const sym_index = coff_file.getAtom(atom).getSymbolIndex().?; |
| ... | ... | @@ -10290,12 +10293,24 @@ fn genLazySymbolRef( |
| 10290 | 10293 | const sym = elf_file.symbol(sym_index); |
| 10291 | 10294 | sym.flags.needs_got = true; |
| 10292 | 10295 | _ = try sym.getOrCreateGotEntry(sym_index, elf_file); |
| 10293 | const got_addr = sym.gotAddress(elf_file); | |
| 10294 | const got_mem = | |
| 10295 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(got_addr) }); | |
| 10296 | const reloc = Mir.Reloc{ | |
| 10297 | .atom_index = try self.owner.getSymbolIndex(self), | |
| 10298 | .sym_index = sym.esym_index, | |
| 10299 | }; | |
| 10296 | 10300 | switch (tag) { |
| 10297 | .lea, .mov => try self.asmRegisterMemory(.{ ._, .mov }, reg.to64(), got_mem), | |
| 10298 | .call => try self.asmMemory(.{ ._, .call }, got_mem), | |
| 10301 | .lea, .mov => _ = try self.addInst(.{ | |
| 10302 | .tag = .mov, | |
| 10303 | .ops = .direct_got_reloc, | |
| 10304 | .data = .{ .rx = .{ | |
| 10305 | .r1 = reg.to64(), | |
| 10306 | .payload = try self.addExtra(reloc), | |
| 10307 | } }, | |
| 10308 | }), | |
| 10309 | .call => _ = try self.addInst(.{ | |
| 10310 | .tag = .call, | |
| 10311 | .ops = .direct_got_reloc, | |
| 10312 | .data = .{ .reloc = reloc }, | |
| 10313 | }), | |
| 10299 | 10314 | else => unreachable, |
| 10300 | 10315 | } |
| 10301 | 10316 | switch (tag) { |
src/arch/x86_64/Emit.zig+13-1| ... | ... | @@ -80,9 +80,21 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 80 | 80 | }), |
| 81 | 81 | .linker_got, |
| 82 | 82 | .linker_direct, |
| 83 | .linker_direct_got, | |
| 83 | 84 | .linker_import, |
| 84 | 85 | .linker_tlv, |
| 85 | => |symbol| if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 86 | => |symbol| if (emit.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 87 | const r_type: u32 = switch (lowered_relocs[0].target) { | |
| 88 | .linker_direct_got => std.elf.R_X86_64_GOT32, | |
| 89 | else => unreachable, | |
| 90 | }; | |
| 91 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | |
| 92 | try atom_ptr.addReloc(elf_file, .{ | |
| 93 | .r_offset = end_offset - 4, | |
| 94 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type, | |
| 95 | .r_addend = 0, | |
| 96 | }); | |
| 97 | } else if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 86 | 98 | const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; |
| 87 | 99 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ |
| 88 | 100 | .type = switch (lowered_relocs[0].target) { |
src/arch/x86_64/Lower.zig+22-1| ... | ... | @@ -52,6 +52,7 @@ pub const Reloc = struct { |
| 52 | 52 | linker_extern_fn: Mir.Reloc, |
| 53 | 53 | linker_got: Mir.Reloc, |
| 54 | 54 | linker_direct: Mir.Reloc, |
| 55 | linker_direct_got: Mir.Reloc, | |
| 55 | 56 | linker_import: Mir.Reloc, |
| 56 | 57 | linker_tlv: Mir.Reloc, |
| 57 | 58 | }; |
| ... | ... | @@ -387,7 +388,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 387 | 388 | .rrmi_sib, .rrmi_rip => inst.data.rrix.fixes, |
| 388 | 389 | .mi_sib_u, .mi_rip_u, .mi_sib_s, .mi_rip_s => inst.data.x.fixes, |
| 389 | 390 | .m_sib, .m_rip, .rax_moffs, .moffs_rax => inst.data.x.fixes, |
| 390 | .extern_fn_reloc, .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ._, | |
| 391 | .extern_fn_reloc, .got_reloc, .direct_reloc, .direct_got_reloc, .import_reloc, .tlv_reloc => ._, | |
| 391 | 392 | else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}), |
| 392 | 393 | }; |
| 393 | 394 | try lower.emit(switch (fixes) { |
| ... | ... | @@ -511,6 +512,26 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 511 | 512 | .extern_fn_reloc => &.{ |
| 512 | 513 | .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) }, |
| 513 | 514 | }, |
| 515 | .direct_got_reloc => ops: { | |
| 516 | switch (inst.tag) { | |
| 517 | .call => { | |
| 518 | _ = lower.reloc(.{ .linker_direct_got = inst.data.reloc }); | |
| 519 | break :ops &.{ | |
| 520 | .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) }, | |
| 521 | }; | |
| 522 | }, | |
| 523 | .mov => { | |
| 524 | const reg = inst.data.rx.r1; | |
| 525 | const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data; | |
| 526 | _ = lower.reloc(.{ .linker_direct_got = extra }); | |
| 527 | break :ops &.{ | |
| 528 | .{ .reg = reg }, | |
| 529 | .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) }, | |
| 530 | }; | |
| 531 | }, | |
| 532 | else => unreachable, | |
| 533 | } | |
| 534 | }, | |
| 514 | 535 | .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ops: { |
| 515 | 536 | const reg = inst.data.rx.r1; |
| 516 | 537 | const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data; |
src/arch/x86_64/Mir.zig+3| ... | ... | @@ -783,6 +783,9 @@ pub const Inst = struct { |
| 783 | 783 | /// Linker relocation - threadlocal variable via GOT indirection. |
| 784 | 784 | /// Uses `rx` payload with extra data of type `Reloc`. |
| 785 | 785 | tlv_reloc, |
| 786 | /// Linker relocation - non-PIC direct reference to GOT cell. | |
| 787 | /// Uses `reloc` payload if tag is `call`, `rx` otherwise. | |
| 788 | direct_got_reloc, | |
| 786 | 789 | |
| 787 | 790 | // Pseudo instructions: |
| 788 | 791 |
src/link/Elf/Atom.zig+3| ... | ... | @@ -518,6 +518,9 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void { |
| 518 | 518 | elf.R_X86_64_PC32, |
| 519 | 519 | => try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))), |
| 520 | 520 | |
| 521 | elf.R_X86_64_GOT32 => try cwriter.writeIntLittle(u32, @as(u32, @intCast(G + GOT + A))), | |
| 522 | elf.R_X86_64_GOT64 => try cwriter.writeIntLittle(u64, @as(u64, @intCast(G + GOT + A))), | |
| 523 | ||
| 521 | 524 | elf.R_X86_64_GOTPCREL => try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A - P))), |
| 522 | 525 | elf.R_X86_64_GOTPC32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(GOT + A - P))), |
| 523 | 526 | elf.R_X86_64_GOTPC64 => try cwriter.writeIntLittle(i64, GOT + A - P), |