mirror of
https://github.com/ziglang/zig.git
synced 2026-01-09 17:05:16 +00:00
x86_64: emit TLS local dynamic model when PIC
This commit is contained in:
parent
51efee2cb6
commit
984c598590
@ -84,6 +84,24 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
} else return emit.fail("TODO implement extern reloc for {s}", .{
|
||||
@tagName(emit.lower.bin_file.tag),
|
||||
}),
|
||||
.linker_tlsld => |data| {
|
||||
const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;
|
||||
const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
|
||||
try atom.addReloc(elf_file, .{
|
||||
.r_offset = end_offset - 4,
|
||||
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | std.elf.R_X86_64_TLSLD,
|
||||
.r_addend = -4,
|
||||
});
|
||||
},
|
||||
.linker_dtpoff => |data| {
|
||||
const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;
|
||||
const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
|
||||
try atom.addReloc(elf_file, .{
|
||||
.r_offset = end_offset - 4,
|
||||
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | std.elf.R_X86_64_DTPOFF32,
|
||||
.r_addend = 0,
|
||||
});
|
||||
},
|
||||
.linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const is_obj_or_static_lib = switch (emit.lower.bin_file.options.output_mode) {
|
||||
.Exe => false,
|
||||
|
||||
@ -11,6 +11,7 @@ result_relocs_len: u8 = undefined,
|
||||
result_insts: [
|
||||
std.mem.max(usize, &.{
|
||||
1, // non-pseudo instructions
|
||||
3, // TLS local dynamic (LD) sequence in PIC mode
|
||||
2, // cmovcc: cmovcc \ cmovcc
|
||||
3, // setcc: setcc \ setcc \ logicop
|
||||
2, // jcc: jcc \ jcc
|
||||
@ -28,6 +29,7 @@ result_relocs: [
|
||||
2, // jcc: jcc \ jcc
|
||||
2, // test \ jcc \ probe \ sub \ jmp
|
||||
1, // probe \ sub \ jcc
|
||||
3, // TLS local dynamic (LD) sequence in PIC mode
|
||||
})
|
||||
]Reloc = undefined,
|
||||
|
||||
@ -51,6 +53,8 @@ pub const Reloc = struct {
|
||||
const Target = union(enum) {
|
||||
inst: Mir.Inst.Index,
|
||||
linker_reloc: bits.Symbol,
|
||||
linker_tlsld: bits.Symbol,
|
||||
linker_dtpoff: bits.Symbol,
|
||||
linker_extern_fn: bits.Symbol,
|
||||
linker_got: bits.Symbol,
|
||||
linker_direct: bits.Symbol,
|
||||
@ -353,24 +357,56 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
||||
assert(mem_op.sib.scale_index.scale == 0);
|
||||
|
||||
if (isTls(sym, lower.bin_file)) {
|
||||
lower.result_insts[lower.result_insts_len] =
|
||||
try Instruction.new(.none, .mov, &[_]Operand{
|
||||
.{ .reg = ops[0].reg.to64() },
|
||||
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
|
||||
});
|
||||
lower.result_insts_len += 1;
|
||||
_ = lower.reloc(.{ .linker_reloc = sym });
|
||||
if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
|
||||
elf_file.symbol(sym_index).flags.needs_zig_got = false;
|
||||
}
|
||||
emit_mnemonic = .lea;
|
||||
switch (mnemonic) {
|
||||
.lea, .mov => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
|
||||
// TODO handle extern TLS vars, i.e., emit GD model
|
||||
if (lower.bin_file.options.pic) {
|
||||
// Here, we currently assume local dynamic TLS vars, and so
|
||||
// we emit LD model.
|
||||
_ = lower.reloc(.{ .linker_tlsld = sym });
|
||||
lower.result_insts[lower.result_insts_len] =
|
||||
try Instruction.new(.none, .lea, &[_]Operand{
|
||||
.{ .reg = ops[0].reg.to64() },
|
||||
.{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
|
||||
});
|
||||
lower.result_insts_len += 1;
|
||||
if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
_ = lower.reloc(.{ .linker_extern_fn = .{
|
||||
.atom_index = sym.atom_index,
|
||||
.sym_index = try elf_file.getGlobalSymbol("__tls_get_address", null),
|
||||
} });
|
||||
}
|
||||
lower.result_insts[lower.result_insts_len] =
|
||||
try Instruction.new(.none, .call, &[_]Operand{
|
||||
.{ .imm = Immediate.s(0) },
|
||||
});
|
||||
lower.result_insts_len += 1;
|
||||
_ = lower.reloc(.{ .linker_dtpoff = sym });
|
||||
if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
|
||||
elf_file.symbol(sym_index).flags.needs_zig_got = false;
|
||||
}
|
||||
emit_mnemonic = .lea;
|
||||
break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
|
||||
.base = .{ .reg = ops[0].reg.to64() },
|
||||
.disp = undefined,
|
||||
}) },
|
||||
else => unreachable,
|
||||
}) };
|
||||
} else {
|
||||
// Since we are linking statically, we emit LE model directly.
|
||||
lower.result_insts[lower.result_insts_len] =
|
||||
try Instruction.new(.none, .mov, &[_]Operand{
|
||||
.{ .reg = ops[0].reg.to64() },
|
||||
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
|
||||
});
|
||||
lower.result_insts_len += 1;
|
||||
_ = lower.reloc(.{ .linker_reloc = sym });
|
||||
if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
|
||||
elf_file.symbol(sym_index).flags.needs_zig_got = false;
|
||||
}
|
||||
emit_mnemonic = .lea;
|
||||
break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
|
||||
.base = .{ .reg = ops[0].reg.to64() },
|
||||
.disp = undefined,
|
||||
}) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user