Skip to content

Commit af40bce

Browse files
committed
x86_64: emit R_X86_64_GOT32 for non-PIC GOT references
1 parent 8e1421f commit af40bce

File tree

5 files changed

+66
-12
lines changed

5 files changed

+66
-12
lines changed

src/arch/x86_64/CodeGen.zig

+25-10
Original file line numberDiff line numberDiff line change
@@ -8223,11 +8223,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
82238223
const sym = elf_file.symbol(sym_index);
82248224
sym.flags.needs_got = true;
82258225
_ = 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+
});
82318234
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
82328235
const atom = try coff_file.getOrCreateAtomForDecl(owner_decl);
82338236
const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
@@ -10290,12 +10293,24 @@ fn genLazySymbolRef(
1029010293
const sym = elf_file.symbol(sym_index);
1029110294
sym.flags.needs_got = true;
1029210295
_ = 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+
};
1029610300
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+
}),
1029910314
else => unreachable,
1030010315
}
1030110316
switch (tag) {

src/arch/x86_64/Emit.zig

+13-1
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,21 @@ pub fn emitMir(emit: *Emit) Error!void {
8080
}),
8181
.linker_got,
8282
.linker_direct,
83+
.linker_direct_got,
8384
.linker_import,
8485
.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| {
8698
const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
8799
try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
88100
.type = switch (lowered_relocs[0].target) {

src/arch/x86_64/Lower.zig

+22-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub const Reloc = struct {
5252
linker_extern_fn: Mir.Reloc,
5353
linker_got: Mir.Reloc,
5454
linker_direct: Mir.Reloc,
55+
linker_direct_got: Mir.Reloc,
5556
linker_import: Mir.Reloc,
5657
linker_tlv: Mir.Reloc,
5758
};
@@ -387,7 +388,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
387388
.rrmi_sib, .rrmi_rip => inst.data.rrix.fixes,
388389
.mi_sib_u, .mi_rip_u, .mi_sib_s, .mi_rip_s => inst.data.x.fixes,
389390
.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 => ._,
391392
else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
392393
};
393394
try lower.emit(switch (fixes) {
@@ -511,6 +512,26 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
511512
.extern_fn_reloc => &.{
512513
.{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
513514
},
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+
},
514535
.got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ops: {
515536
const reg = inst.data.rx.r1;
516537
const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;

src/arch/x86_64/Mir.zig

+3
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,9 @@ pub const Inst = struct {
783783
/// Linker relocation - threadlocal variable via GOT indirection.
784784
/// Uses `rx` payload with extra data of type `Reloc`.
785785
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,
786789

787790
// Pseudo instructions:
788791

src/link/Elf/Atom.zig

+3
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,9 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
518518
elf.R_X86_64_PC32,
519519
=> try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))),
520520

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+
521524
elf.R_X86_64_GOTPCREL => try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A - P))),
522525
elf.R_X86_64_GOTPC32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(GOT + A - P))),
523526
elf.R_X86_64_GOTPC64 => try cwriter.writeIntLittle(i64, GOT + A - P),

0 commit comments

Comments
 (0)