Commit 17635e4f2a
Changed files (5)
src
src/arch/x86_64/CodeGen.zig
@@ -9190,14 +9190,19 @@ fn genCall(self: *Self, info: union(enum) {
const sym_index = try elf_file.getOrCreateMetadataForDecl(owner_decl);
const sym = elf_file.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
- _ = try self.addInst(.{
- .tag = .call,
- .ops = .direct_got_reloc,
- .data = .{ .reloc = .{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = sym.esym_index,
- } },
- });
+ if (self.bin_file.options.pic) {
+ try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym.esym_index });
+ try self.asmRegister(.{ ._, .call }, .rax);
+ } else {
+ _ = try self.addInst(.{
+ .tag = .call,
+ .ops = .direct_got_reloc,
+ .data = .{ .reloc = .{
+ .atom_index = try self.owner.getSymbolIndex(self),
+ .sym_index = sym.esym_index,
+ } },
+ });
+ }
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
const atom = try coff_file.getOrCreateAtomForDecl(owner_decl);
const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
@@ -11637,34 +11642,48 @@ fn genLazySymbolRef(
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
const sym = elf_file.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
- const reloc = Mir.Reloc{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = sym.esym_index,
- };
- switch (tag) {
- .lea, .mov => _ = try self.addInst(.{
- .tag = .mov,
- .ops = .direct_got_reloc,
- .data = .{ .rx = .{
- .r1 = reg.to64(),
- .payload = try self.addExtra(reloc),
- } },
- }),
- .call => _ = try self.addInst(.{
- .tag = .call,
- .ops = .direct_got_reloc,
- .data = .{ .reloc = reloc },
- }),
- else => unreachable,
- }
- switch (tag) {
- .lea, .call => {},
- .mov => try self.asmRegisterMemory(
- .{ ._, tag },
- reg.to64(),
- Memory.sib(.qword, .{ .base = .{ .reg = reg.to64() } }),
- ),
- else => unreachable,
+
+ if (self.bin_file.options.pic) {
+ switch (tag) {
+ .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym.esym_index }),
+ .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym.esym_index }),
+ else => unreachable,
+ }
+ switch (tag) {
+ .lea, .mov => {},
+ .call => try self.asmRegister(.{ ._, .call }, reg),
+ else => unreachable,
+ }
+ } else {
+ const reloc = Mir.Reloc{
+ .atom_index = try self.owner.getSymbolIndex(self),
+ .sym_index = sym.esym_index,
+ };
+ switch (tag) {
+ .lea, .mov => _ = try self.addInst(.{
+ .tag = .mov,
+ .ops = .direct_got_reloc,
+ .data = .{ .rx = .{
+ .r1 = reg.to64(),
+ .payload = try self.addExtra(reloc),
+ } },
+ }),
+ .call => _ = try self.addInst(.{
+ .tag = .call,
+ .ops = .direct_got_reloc,
+ .data = .{ .reloc = reloc },
+ }),
+ else => unreachable,
+ }
+ switch (tag) {
+ .lea, .call => {},
+ .mov => try self.asmRegisterMemory(
+ .{ ._, tag },
+ reg.to64(),
+ Memory.sib(.qword, .{ .base = .{ .reg = reg.to64() } }),
+ ),
+ else => unreachable,
+ }
}
} else if (self.bin_file.cast(link.File.Plan9)) |p9_file| {
const atom_index = p9_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
src/arch/x86_64/Emit.zig
@@ -85,14 +85,21 @@ pub fn emitMir(emit: *Emit) Error!void {
.linker_tlv,
=> |symbol| if (emit.bin_file.cast(link.File.Elf)) |elf_file| {
const r_type: u32 = switch (lowered_relocs[0].target) {
- .linker_direct_got => std.elf.R_X86_64_GOT32,
+ .linker_direct_got => link.File.Elf.R_X86_64_ZIG_GOT32,
+ .linker_got => link.File.Elf.R_X86_64_ZIG_GOTPCREL,
+ .linker_direct => std.elf.R_X86_64_PC32,
+ else => unreachable,
+ };
+ const r_addend: i64 = switch (lowered_relocs[0].target) {
+ .linker_direct_got => 0,
+ .linker_got, .linker_direct => -4,
else => unreachable,
};
const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
try atom_ptr.addReloc(elf_file, .{
.r_offset = end_offset - 4,
.r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
- .r_addend = 0,
+ .r_addend = r_addend,
});
} else if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
src/link/Elf/Atom.zig
@@ -370,16 +370,6 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
try self.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
},
- // TODO I have temporarily repurposed those for handling .zig.got indirection
- // but we should probably claim unused custom values for incremental linking
- // that get rewritten to standard relocs when lowering to a relocatable object
- // file.
- elf.R_X86_64_GOT32,
- elf.R_X86_64_GOT64,
- => {
- assert(symbol.flags.has_zig_got);
- },
-
elf.R_X86_64_GOTPC32,
elf.R_X86_64_GOTPC64,
elf.R_X86_64_GOTPCREL,
@@ -461,6 +451,13 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
elf.R_X86_64_TLSDESC_CALL,
=> {},
+ // Zig custom relocations
+ Elf.R_X86_64_ZIG_GOT32,
+ Elf.R_X86_64_ZIG_GOTPCREL,
+ => {
+ assert(symbol.flags.has_zig_got);
+ },
+
else => try self.reportUnhandledRelocError(rel, elf_file),
}
}
@@ -813,13 +810,6 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
elf.R_X86_64_32 => try cwriter.writeIntLittle(u32, @as(u32, @truncate(@as(u64, @intCast(S + A))))),
elf.R_X86_64_32S => try cwriter.writeIntLittle(i32, @as(i32, @truncate(S + A))),
- // TODO I have temporarily repurposed those for handling .zig.got indirection
- // but we should probably claim unused custom values for incremental linking
- // that get rewritten to standard relocs when lowering to a relocatable object
- // file.
- elf.R_X86_64_GOT32 => try cwriter.writeIntLittle(u32, @as(u32, @intCast(ZIG_GOT + A))),
- elf.R_X86_64_GOT64 => try cwriter.writeIntLittle(u64, @as(u64, @intCast(ZIG_GOT + A))),
-
elf.R_X86_64_TPOFF32 => try cwriter.writeIntLittle(i32, @as(i32, @truncate(S + A - TP))),
elf.R_X86_64_TPOFF64 => try cwriter.writeIntLittle(i64, S + A - TP),
@@ -888,6 +878,10 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
}
},
+ // Zig custom relocations
+ Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeIntLittle(u32, @as(u32, @intCast(ZIG_GOT + A))),
+ Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeIntLittle(i32, @as(i32, @intCast(ZIG_GOT + A - P))),
+
else => {},
}
}
@@ -1136,6 +1130,9 @@ fn formatRelocType(
elf.R_X86_64_GOTPCRELX => "R_X86_64_GOTPCRELX",
elf.R_X86_64_REX_GOTPCRELX => "R_X86_64_REX_GOTPCRELX",
elf.R_X86_64_NUM => "R_X86_64_NUM",
+ // Zig custom relocations
+ Elf.R_X86_64_ZIG_GOT32 => "R_X86_64_ZIG_GOT32",
+ Elf.R_X86_64_ZIG_GOTPCREL => "R_X86_64_ZIG_GOTPCREL",
else => "R_X86_64_UNKNOWN",
};
try writer.print("{s}", .{str});
src/link/Elf.zig
@@ -6074,6 +6074,9 @@ const SystemLib = struct {
path: []const u8,
};
+pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1;
+pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2;
+
const std = @import("std");
const build_options = @import("build_options");
const builtin = @import("builtin");
src/codegen.zig
@@ -890,7 +890,11 @@ fn genDeclRef(
const sym_index = try elf_file.getOrCreateMetadataForDecl(decl_index);
const sym = elf_file.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
- return GenResult.mcv(.{ .memory = sym.zigGotAddress(elf_file) });
+ if (bin_file.options.pic) {
+ return GenResult.mcv(.{ .load_got = sym.esym_index });
+ } else {
+ return GenResult.mcv(.{ .memory = sym.zigGotAddress(elf_file) });
+ }
} else if (bin_file.cast(link.File.MachO)) |macho_file| {
const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
@@ -925,7 +929,12 @@ fn genUnnamedConst(
return GenResult.fail(bin_file.allocator, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)});
};
if (bin_file.cast(link.File.Elf)) |elf_file| {
- return GenResult.mcv(.{ .memory = elf_file.symbol(local_sym_index).value });
+ const local = elf_file.symbol(local_sym_index);
+ if (bin_file.options.pic) {
+ return GenResult.mcv(.{ .load_direct = local.esym_index });
+ } else {
+ return GenResult.mcv(.{ .memory = local.value });
+ }
} else if (bin_file.cast(link.File.MachO)) |_| {
return GenResult.mcv(.{ .load_direct = local_sym_index });
} else if (bin_file.cast(link.File.Coff)) |_| {