authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-12 10:28:45+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-11-12 18:12:41-05:00
log984c5985907fdb6f48543e3d1e27ffd4d54b0957
tree9a02372cd267891caef98e8445296a1fe83c4477
parent51efee2cb6748d668d573133e63a5b3c96de6995

x86_64: emit TLS local dynamic model when PIC


2 files changed, 70 insertions(+), 16 deletions(-)

src/arch/x86_64/Emit.zig+18
...@@ -84,6 +84,24 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -84,6 +84,24 @@ pub fn emitMir(emit: *Emit) Error!void {
84 } else return emit.fail("TODO implement extern reloc for {s}", .{84 } else return emit.fail("TODO implement extern reloc for {s}", .{
85 @tagName(emit.lower.bin_file.tag),85 @tagName(emit.lower.bin_file.tag),
86 }),86 }),
87 .linker_tlsld => |data| {
88 const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;
89 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
90 try atom.addReloc(elf_file, .{
91 .r_offset = end_offset - 4,
92 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | std.elf.R_X86_64_TLSLD,
93 .r_addend = -4,
94 });
95 },
96 .linker_dtpoff => |data| {
97 const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;
98 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
99 try atom.addReloc(elf_file, .{
100 .r_offset = end_offset - 4,
101 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | std.elf.R_X86_64_DTPOFF32,
102 .r_addend = 0,
103 });
104 },
87 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {105 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
88 const is_obj_or_static_lib = switch (emit.lower.bin_file.options.output_mode) {106 const is_obj_or_static_lib = switch (emit.lower.bin_file.options.output_mode) {
89 .Exe => false,107 .Exe => false,
src/arch/x86_64/Lower.zig+52-16
...@@ -11,6 +11,7 @@ result_relocs_len: u8 = undefined,...@@ -11,6 +11,7 @@ result_relocs_len: u8 = undefined,
11result_insts: [11result_insts: [
12 std.mem.max(usize, &.{12 std.mem.max(usize, &.{
13 1, // non-pseudo instructions13 1, // non-pseudo instructions
14 3, // TLS local dynamic (LD) sequence in PIC mode
14 2, // cmovcc: cmovcc \ cmovcc15 2, // cmovcc: cmovcc \ cmovcc
15 3, // setcc: setcc \ setcc \ logicop16 3, // setcc: setcc \ setcc \ logicop
16 2, // jcc: jcc \ jcc17 2, // jcc: jcc \ jcc
...@@ -28,6 +29,7 @@ result_relocs: [...@@ -28,6 +29,7 @@ result_relocs: [
28 2, // jcc: jcc \ jcc29 2, // jcc: jcc \ jcc
29 2, // test \ jcc \ probe \ sub \ jmp30 2, // test \ jcc \ probe \ sub \ jmp
30 1, // probe \ sub \ jcc31 1, // probe \ sub \ jcc
32 3, // TLS local dynamic (LD) sequence in PIC mode
31 })33 })
32]Reloc = undefined,34]Reloc = undefined,
3335
...@@ -51,6 +53,8 @@ pub const Reloc = struct {...@@ -51,6 +53,8 @@ pub const Reloc = struct {
51 const Target = union(enum) {53 const Target = union(enum) {
52 inst: Mir.Inst.Index,54 inst: Mir.Inst.Index,
53 linker_reloc: bits.Symbol,55 linker_reloc: bits.Symbol,
56 linker_tlsld: bits.Symbol,
57 linker_dtpoff: bits.Symbol,
54 linker_extern_fn: bits.Symbol,58 linker_extern_fn: bits.Symbol,
55 linker_got: bits.Symbol,59 linker_got: bits.Symbol,
56 linker_direct: bits.Symbol,60 linker_direct: bits.Symbol,
...@@ -353,24 +357,56 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -353,24 +357,56 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
353 assert(mem_op.sib.scale_index.scale == 0);357 assert(mem_op.sib.scale_index.scale == 0);
354358
355 if (isTls(sym, lower.bin_file)) {359 if (isTls(sym, lower.bin_file)) {
356 lower.result_insts[lower.result_insts_len] =360 // TODO handle extern TLS vars, i.e., emit GD model
357 try Instruction.new(.none, .mov, &[_]Operand{361 if (lower.bin_file.options.pic) {
358 .{ .reg = ops[0].reg.to64() },362 // Here, we currently assume local dynamic TLS vars, and so
359 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },363 // we emit LD model.
360 });364 _ = lower.reloc(.{ .linker_tlsld = sym });
361 lower.result_insts_len += 1;365 lower.result_insts[lower.result_insts_len] =
362 _ = lower.reloc(.{ .linker_reloc = sym });366 try Instruction.new(.none, .lea, &[_]Operand{
363 if (lower.bin_file.cast(link.File.Elf)) |elf_file| {367 .{ .reg = ops[0].reg.to64() },
364 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);368 .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
365 elf_file.symbol(sym_index).flags.needs_zig_got = false;369 });
366 }370 lower.result_insts_len += 1;
367 emit_mnemonic = .lea;371 if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
368 switch (mnemonic) {372 _ = lower.reloc(.{ .linker_extern_fn = .{
369 .lea, .mov => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{373 .atom_index = sym.atom_index,
374 .sym_index = try elf_file.getGlobalSymbol("__tls_get_address", null),
375 } });
376 }
377 lower.result_insts[lower.result_insts_len] =
378 try Instruction.new(.none, .call, &[_]Operand{
379 .{ .imm = Immediate.s(0) },
380 });
381 lower.result_insts_len += 1;
382 _ = lower.reloc(.{ .linker_dtpoff = sym });
383 if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
384 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
385 elf_file.symbol(sym_index).flags.needs_zig_got = false;
386 }
387 emit_mnemonic = .lea;
388 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
370 .base = .{ .reg = ops[0].reg.to64() },389 .base = .{ .reg = ops[0].reg.to64() },
371 .disp = undefined,390 .disp = undefined,
372 }) },391 }) };
373 else => unreachable,392 } else {
393 // Since we are linking statically, we emit LE model directly.
394 lower.result_insts[lower.result_insts_len] =
395 try Instruction.new(.none, .mov, &[_]Operand{
396 .{ .reg = ops[0].reg.to64() },
397 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
398 });
399 lower.result_insts_len += 1;
400 _ = lower.reloc(.{ .linker_reloc = sym });
401 if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
402 const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
403 elf_file.symbol(sym_index).flags.needs_zig_got = false;
404 }
405 emit_mnemonic = .lea;
406 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
407 .base = .{ .reg = ops[0].reg.to64() },
408 .disp = undefined,
409 }) };
374 }410 }
375 }411 }
376412