| author | |
| committer | |
| log | 1afc6917f5e6acc7f7f700b54023a82e4ad923a6 |
| tree | 1f87cb8855dd6a4dfb9aa0f0a8fb037887dfe2a0 |
| parent | b48baeeebbec2f5d06f8ffc5305d2994d8389a72 |
4 files changed, 59 insertions(+), 11 deletions(-)
src/arch/x86_64/Emit.zig+2| ... | @@ -120,6 +120,8 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -120,6 +120,8 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 120 | link.File.Elf.R_X86_64_ZIG_GOT32 | 120 | link.File.Elf.R_X86_64_ZIG_GOT32 |
| 121 | else if (sym.flags.needs_got) | 121 | else if (sym.flags.needs_got) |
| 122 | std.elf.R_X86_64_GOT32 | 122 | std.elf.R_X86_64_GOT32 |
| 123 | else if (sym.isTls(elf_file)) | ||
| 124 | std.elf.R_X86_64_TPOFF32 | ||
| 123 | else | 125 | else |
| 124 | std.elf.R_X86_64_32; | 126 | std.elf.R_X86_64_32; |
| 125 | try atom.addReloc(elf_file, .{ | 127 | try atom.addReloc(elf_file, .{ |
src/arch/x86_64/Lower.zig+36-8| ... | @@ -319,20 +319,25 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { | ... | @@ -319,20 +319,25 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { |
| 319 | return Immediate.s(0); | 319 | return Immediate.s(0); |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { | 322 | fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool { |
| 323 | const needsZigGot = struct { | 323 | const elf_file = ctx.cast(link.File.Elf).?; |
| 324 | fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool { | 324 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); |
| 325 | const elf_file = ctx.cast(link.File.Elf).?; | 325 | return elf_file.symbol(sym_index).flags.needs_zig_got; |
| 326 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); | 326 | } |
| 327 | return elf_file.symbol(sym_index).flags.needs_zig_got; | 327 | |
| 328 | } | 328 | fn isTls(sym: bits.Symbol, ctx: *link.File) bool { |
| 329 | }.needsZigGot; | 329 | const elf_file = ctx.cast(link.File.Elf).?; |
| 330 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); | ||
| 331 | return elf_file.symbol(sym_index).isTls(elf_file); | ||
| 332 | } | ||
| 330 | 333 | ||
| 334 | fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { | ||
| 331 | const is_obj_or_static_lib = switch (lower.bin_file.options.output_mode) { | 335 | const is_obj_or_static_lib = switch (lower.bin_file.options.output_mode) { |
| 332 | .Exe => false, | 336 | .Exe => false, |
| 333 | .Obj => true, | 337 | .Obj => true, |
| 334 | .Lib => lower.bin_file.options.link_mode == .Static, | 338 | .Lib => lower.bin_file.options.link_mode == .Static, |
| 335 | }; | 339 | }; |
| 340 | |||
| 336 | var emit_prefix = prefix; | 341 | var emit_prefix = prefix; |
| 337 | var emit_mnemonic = mnemonic; | 342 | var emit_mnemonic = mnemonic; |
| 338 | var emit_ops_storage: [4]Operand = undefined; | 343 | var emit_ops_storage: [4]Operand = undefined; |
| ... | @@ -346,6 +351,29 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) | ... | @@ -346,6 +351,29 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 346 | assert(prefix == .none); | 351 | assert(prefix == .none); |
| 347 | assert(mem_op.sib.disp == 0); | 352 | assert(mem_op.sib.disp == 0); |
| 348 | assert(mem_op.sib.scale_index.scale == 0); | 353 | assert(mem_op.sib.scale_index.scale == 0); |
| 354 | |||
| 355 | if (isTls(sym, lower.bin_file)) { | ||
| 356 | lower.result_insts[lower.result_insts_len] = | ||
| 357 | try Instruction.new(.none, .mov, &[_]Operand{ | ||
| 358 | .{ .reg = ops[0].reg.to64() }, | ||
| 359 | .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) }, | ||
| 360 | }); | ||
| 361 | lower.result_insts_len += 1; | ||
| 362 | _ = lower.reloc(.{ .linker_reloc = sym }); | ||
| 363 | if (lower.bin_file.cast(link.File.Elf)) |elf_file| { | ||
| 364 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); | ||
| 365 | elf_file.symbol(sym_index).flags.needs_zig_got = false; | ||
| 366 | } | ||
| 367 | emit_mnemonic = .lea; | ||
| 368 | switch (mnemonic) { | ||
| 369 | .lea, .mov => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | ||
| 370 | .base = .{ .reg = ops[0].reg.to64() }, | ||
| 371 | .disp = undefined, | ||
| 372 | }) }, | ||
| 373 | else => unreachable, | ||
| 374 | } | ||
| 375 | } | ||
| 376 | |||
| 349 | _ = lower.reloc(.{ .linker_reloc = sym }); | 377 | _ = lower.reloc(.{ .linker_reloc = sym }); |
| 350 | break :op if (lower.bin_file.options.pic) switch (mnemonic) { | 378 | break :op if (lower.bin_file.options.pic) switch (mnemonic) { |
| 351 | .lea => { | 379 | .lea => { |
src/link/Elf/Symbol.zig+7| ... | @@ -51,6 +51,13 @@ pub fn isIFunc(symbol: Symbol, elf_file: *Elf) bool { | ... | @@ -51,6 +51,13 @@ pub fn isIFunc(symbol: Symbol, elf_file: *Elf) bool { |
| 51 | return symbol.type(elf_file) == elf.STT_GNU_IFUNC; | 51 | return symbol.type(elf_file) == elf.STT_GNU_IFUNC; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | // TODO this check is enough for ZigObject emitted TLS vars but what about those emitted | ||
| 55 | // by different backends/compilers? | ||
| 56 | pub fn isTls(symbol: Symbol, elf_file: *Elf) bool { | ||
| 57 | if (symbol.file(elf_file) == null) return false; | ||
| 58 | return symbol.type(elf_file) == elf.STT_TLS; | ||
| 59 | } | ||
| 60 | |||
| 54 | pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 { | 61 | pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 { |
| 55 | const esym = symbol.elfSym(elf_file); | 62 | const esym = symbol.elfSym(elf_file); |
| 56 | const file_ptr = symbol.file(elf_file).?; | 63 | const file_ptr = symbol.file(elf_file).?; |
src/link/Elf/ZigObject.zig+14-3| ... | @@ -723,7 +723,18 @@ pub fn getOrCreateMetadataForDecl( | ... | @@ -723,7 +723,18 @@ pub fn getOrCreateMetadataForDecl( |
| 723 | ) !Symbol.Index { | 723 | ) !Symbol.Index { |
| 724 | const gop = try self.decls.getOrPut(elf_file.base.allocator, decl_index); | 724 | const gop = try self.decls.getOrPut(elf_file.base.allocator, decl_index); |
| 725 | if (!gop.found_existing) { | 725 | if (!gop.found_existing) { |
| 726 | gop.value_ptr.* = .{ .symbol_index = try self.addAtom(elf_file) }; | 726 | const symbol_index = try self.addAtom(elf_file); |
| 727 | const mod = elf_file.base.options.module.?; | ||
| 728 | const decl = mod.declPtr(decl_index); | ||
| 729 | const single_threaded = elf_file.base.options.single_threaded; | ||
| 730 | if (decl.getOwnedVariable(mod)) |variable| { | ||
| 731 | if (variable.is_threadlocal and !single_threaded) { | ||
| 732 | const sym = elf_file.symbol(symbol_index); | ||
| 733 | self.elfSym(sym.esym_index).st_info = elf.STT_TLS; | ||
| 734 | } | ||
| 735 | } | ||
| 736 | |||
| 737 | gop.value_ptr.* = .{ .symbol_index = symbol_index }; | ||
| 727 | } | 738 | } |
| 728 | return gop.value_ptr.symbol_index; | 739 | return gop.value_ptr.symbol_index; |
| 729 | } | 740 | } |
| ... | @@ -891,7 +902,7 @@ fn updateTlv( | ... | @@ -891,7 +902,7 @@ fn updateTlv( |
| 891 | const decl = mod.declPtr(decl_index); | 902 | const decl = mod.declPtr(decl_index); |
| 892 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); | 903 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); |
| 893 | 904 | ||
| 894 | log.debug("updateTlv {s}{*}", .{ decl_name, decl }); | 905 | log.debug("updateTlv {s} ({*})", .{ decl_name, decl }); |
| 895 | 906 | ||
| 896 | const required_alignment = decl.getAlignment(mod); | 907 | const required_alignment = decl.getAlignment(mod); |
| 897 | 908 | ||
| ... | @@ -906,7 +917,7 @@ fn updateTlv( | ... | @@ -906,7 +917,7 @@ fn updateTlv( |
| 906 | atom_ptr.flags.alive = true; | 917 | atom_ptr.flags.alive = true; |
| 907 | atom_ptr.name_offset = sym.name_offset; | 918 | atom_ptr.name_offset = sym.name_offset; |
| 908 | esym.st_name = sym.name_offset; | 919 | esym.st_name = sym.name_offset; |
| 909 | esym.st_info |= elf.STT_TLS; | 920 | esym.st_info = elf.STT_TLS; |
| 910 | esym.st_size = code.len; | 921 | esym.st_size = code.len; |
| 911 | 922 | ||
| 912 | atom_ptr.alignment = required_alignment; | 923 | atom_ptr.alignment = required_alignment; |