summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/OutputSections.cpp3
-rw-r--r--lld/ELF/OutputSections.h3
-rw-r--r--lld/ELF/Target.cpp3
-rw-r--r--lld/ELF/Writer.cpp4
-rw-r--r--lld/test/elf2/tls.s64
5 files changed, 73 insertions, 4 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index e3e3fef8be5..5007ba003fa 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -644,6 +644,9 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
case SymbolBody::DefinedRegularKind: {
const auto &DR = cast<DefinedRegular<ELFT>>(S);
InputSectionBase<ELFT> &SC = DR.Section;
+ if (DR.Sym.getType() == STT_TLS)
+ return SC.OutSec->getVA() + SC.getOffset(DR.Sym) -
+ Out<ELFT>::TlsInitImageVA;
return SC.OutSec->getVA() + SC.getOffset(DR.Sym);
}
case SymbolBody::DefinedCommonKind:
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 5a23c86411c..df173361da2 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -353,6 +353,7 @@ private:
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
template <class ELFT> struct Out {
+ typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
static DynamicSection<ELFT> *Dynamic;
static GnuHashTableSection<ELFT> *GnuHashTab;
static GotPltSection<ELFT> *GotPlt;
@@ -370,6 +371,7 @@ template <class ELFT> struct Out {
static StringTableSection<ELFT> *StrTab;
static SymbolTableSection<ELFT> *DynSymTab;
static SymbolTableSection<ELFT> *SymTab;
+ static uintX_t TlsInitImageVA;
};
template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic;
@@ -389,6 +391,7 @@ template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::ShStrTab;
template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
+template <class ELFT> typename Out<ELFT>::uintX_t Out<ELFT>::TlsInitImageVA;
}
}
#endif
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 0ebcf827d9d..7adc5c6de43 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -339,6 +339,9 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
error("R_X86_64_32S out of range");
write32le(Loc, SA);
break;
+ case R_X86_64_TPOFF32:
+ write32le(Loc, SA);
+ break;
default:
error("unrecognized reloc " + Twine(Type));
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 4f8f623c740..fe87d926067 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -716,8 +716,10 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
}
if ((Sec->getFlags() & SHF_ALLOC) && (Sec->getFlags() & SHF_TLS)) {
- if (!TlsPhdr.p_vaddr)
+ if (!TlsPhdr.p_vaddr) {
setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
+ Out<ELFT>::TlsInitImageVA = VA;
+ }
if (Sec->getType() != SHT_NOBITS)
VA = RoundUpToAlignment(VA, Sec->getAlign());
uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign());
diff --git a/lld/test/elf2/tls.s b/lld/test/elf2/tls.s
index 5b5fc4f822a..6b3cad13885 100644
--- a/lld/test/elf2/tls.s
+++ b/lld/test/elf2/tls.s
@@ -1,21 +1,34 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
// RUN: ld.lld2 %t -o %tout
-// RUN: llvm-readobj -sections -program-headers %tout | FileCheck %s
+// RUN: llvm-readobj -symbols -sections -program-headers %tout | FileCheck %s
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
.global _start
_start:
+ movl %fs:a@tpoff, %eax
+ movl %fs:b@tpoff, %eax
+ movl %fs:c@tpoff, %eax
+ movl %fs:d@tpoff, %eax
+ .global a
.section .tbss,"awT",@nobits
+a:
.long 0
+ .global b
.section .tdata,"awT",@progbits
+b:
.long 1
+ .global c
.section .thread_bss,"awT",@nobits
+c:
.long 0
+ .global d
.section .thread_data,"awT",@progbits
+d:
.long 2
// CHECK: Name: .tdata
@@ -77,9 +90,9 @@ _start:
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
-// 0x1100C = TBSS_ADDR + 4
+// 0x1200C = TBSS_ADDR + 4
-// CHECK-NEXT: Address: 0x1100C
+// CHECK-NEXT: Address: 0x1200C
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Link:
@@ -88,11 +101,49 @@ _start:
// CHECK-NEXT: EntrySize:
// CHECK-NEXT: }
+// CHECK: Symbols [
+// CHECK: Name: a
+// CHECK-NEXT: Value: 0x8
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: TLS
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .tbss
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: b
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: TLS
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .tdata
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: c
+// CHECK-NEXT: Value: 0xC
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: TLS
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .thread_bss
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: d
+// CHECK-NEXT: Value: 0x4
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: TLS
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .thread_data
+// CHECK-NEXT: }
+
// Check that the TLS NOBITS sections weren't added to the R/W PT_LOAD's size.
// CHECK: ProgramHeaders [
// CHECK: Type: PT_LOAD
// CHECK: Type: PT_LOAD
+// CHECK: Type: PT_LOAD
// CHECK: FileSize: 8
// CHECK-NEXT: MemSize: 8
// CHECK-NEXT: Flags [
@@ -110,3 +161,10 @@ _start:
// CHECK-NEXT: ]
// CHECK-NEXT: Alignment:
// CHECK-NEXT: }
+
+// DIS: Disassembly of section .text:
+// DIS-NEXT: _start:
+// DIS-NEXT: 11000: {{.+}} movl %fs:8, %eax
+// DIS-NEXT: 11008: {{.+}} movl %fs:0, %eax
+// DIS-NEXT: 11010: {{.+}} movl %fs:12, %eax
+// DIS-NEXT: 11018: {{.+}} movl %fs:4, %eax
OpenPOWER on IntegriCloud