Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -132,7 +132,7 @@ Type = Target->getPLTRefReloc(Type); } else if (Target->relocNeedsGot(Type, Body)) { SymVA = Out::Got->getEntryAddr(Body); - Type = Target->getGotRefReloc(); + Type = Body.isTLS() ? Target->getTlsGotReloc() : Target->getGotRefReloc(); } else if (Target->relocPointsToGot(Type)) { SymVA = Out::Got->getVA(); Type = Target->getPCRelReloc(); Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -212,10 +212,11 @@ Target->relocNeedsPlt(Type, *Body); if (CanBePreempted) { + unsigned GotReloc = + Body->isTLS() ? Target->getTlsGotReloc() : Target->getGotReloc(); if (NeedsGot) P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), - LazyReloc ? Target->getPltReloc() - : Target->getGotReloc(), + LazyReloc ? Target->getPltReloc() : GotReloc, Config->Mips64EL); else P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -29,6 +29,7 @@ unsigned getPltReloc() const { return PltReloc; } unsigned getGotRefReloc() const { return GotRefReloc; } unsigned getRelativeReloc() const { return RelativeReloc; } + unsigned getTlsGotReloc() const { return TlsGotReloc; } unsigned getTlsLocalDynamicReloc() const { return TlsLocalDynamicReloc; } unsigned getTlsModuleIndexReloc() const { return TlsModuleIndexReloc; } unsigned getPltZeroEntrySize() const { return PltZeroEntrySize; } @@ -69,6 +70,7 @@ unsigned GotReloc; unsigned PltReloc; unsigned RelativeReloc; + unsigned TlsGotReloc = 0; unsigned TlsLocalDynamicReloc = 0; unsigned TlsModuleIndexReloc; unsigned PltEntrySize = 8; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -215,6 +215,7 @@ GotRefReloc = R_X86_64_PC32; PltReloc = R_X86_64_JUMP_SLOT; RelativeReloc = R_X86_64_RELATIVE; + TlsGotReloc = R_X86_64_TPOFF64; TlsLocalDynamicReloc = R_X86_64_TLSLD; TlsModuleIndexReloc = R_X86_64_DTPMOD64; LazyRelocations = true; @@ -264,7 +265,8 @@ } bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { - return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S); + return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_GOTPCREL || + relocNeedsPlt(Type, S); } unsigned X86_64TargetInfo::getPLTRefReloc(unsigned Type) const { @@ -335,6 +337,7 @@ case R_X86_64_GOTPCREL: case R_X86_64_PLT32: case R_X86_64_TLSLD: + case R_X86_64_TPOFF64: write32le(Loc, SA - P); break; case R_X86_64_64: Index: test/elf2/Inputs/tls-got.s =================================================================== --- test/elf2/Inputs/tls-got.s +++ test/elf2/Inputs/tls-got.s @@ -0,0 +1,14 @@ +.type tls0,@object +.section .tbss,"awT",@nobits +.globl tls0 +.align 4 +tls0: + .long 0 + .size tls0, 4 + +.type tls1,@object +.globl tls1 +.align 4 +tls1: + .long 0 + .size tls1, 4 Index: test/elf2/tls-got.s =================================================================== --- test/elf2/tls-got.s +++ test/elf2/tls-got.s @@ -0,0 +1,58 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-got.s -o %t2.o +// RUN: ld.lld2 -shared %t2.o -o %t2.so +// RUN: ld.lld2 -e main %t1.o %t2.so -o %t3 +// RUN: llvm-readobj -s -r %t3 | FileCheck %s +// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM %s + +// CHECK: Section { +// CHECK: Index: 8 +// CHECK-NEXT: Name: .got +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: [[ADDR:.*]] +// CHECK-NEXT: Offset: 0x20A0 +// CHECK-NEXT: Size: 16 +// CHECK-NEXT: Link: 0 +// CHECK-NEXT: Info: 0 +// CHECK-NEXT: AddressAlignment: 8 +// CHECK-NEXT: EntrySize: 0 +// CHECK-NEXT: } + +// CHECK: Relocations [ +// CHECK-NEXT: Section (4) .rela.dyn { +// CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0 +// CHECK-NEXT: 0x120A8 R_X86_64_TPOFF64 tls0 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: ] + +//0x11000 + 4249 + 7 = 0x120A0 +//0x1100A + 4247 + 7 = 0x120A8 +//0x11014 + 4237 + 7 = 0x120A8 +//DISASM: Disassembly of section .text: +//DISASM-NEXT: main: +//DISASM-NEXT: 11000: 48 8b 05 99 10 00 00 movq 4249(%rip), %rax +//DISASM-NEXT: 11007: 64 8b 00 movl %fs:(%rax), %eax +//DISASM-NEXT: 1100a: 48 8b 05 97 10 00 00 movq 4247(%rip), %rax +//DISASM-NEXT: 11011: 64 8b 00 movl %fs:(%rax), %eax +//DISASM-NEXT: 11014: 48 8b 05 8d 10 00 00 movq 4237(%rip), %rax +//DISASM-NEXT: 1101b: 64 8b 00 movl %fs:(%rax), %eax +//DISASM-NEXT: 1101e: c3 retq + +.section .tdata,"awT",@progbits + +.text + .globl main + .align 16, 0x90 + .type main,@function +main: + movq tls1@GOTTPOFF(%rip), %rax + movl %fs:0(%rax), %eax + movq tls0@GOTTPOFF(%rip), %rax + movl %fs:0(%rax), %eax + movq tls0@GOTTPOFF(%rip), %rax + movl %fs:0(%rax), %eax + ret