mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 15:13:08 +00:00
x86_64: add -fPIC support targeting ELF
This commit is contained in:
parent
b3d98a4b88
commit
17635e4f2a
@ -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|
|
||||
|
||||
@ -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 }).?;
|
||||
|
||||
@ -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)) |_| {
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user