[lld] r174425 - [ELF] Replace local dynamic tls access with direct access.
Michael J. Spencer
bigcheesegs at gmail.com
Tue Feb 5 11:14:07 PST 2013
Author: mspencer
Date: Tue Feb 5 13:14:07 2013
New Revision: 174425
URL: http://llvm.org/viewvc/llvm-project?rev=174425&view=rev
Log:
[ELF] Replace local dynamic tls access with direct access.
Modified:
lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
lld/trunk/test/elf/Inputs/tls.S
lld/trunk/test/elf/Inputs/tls.x86-64
lld/trunk/test/elf/tls.test
Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp?rev=174425&r1=174424&r2=174425&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp Tue Feb 5 13:14:07 2013
@@ -61,6 +61,8 @@ ErrorOr<void> X86_64TargetRelocationHand
uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
switch (ref.kind()) {
+ case R_X86_64_NONE:
+ break;
case R_X86_64_64:
reloc64(location, relocVAddress, targetVAddress, ref.addend());
break;
@@ -74,6 +76,7 @@ ErrorOr<void> X86_64TargetRelocationHand
reloc32S(location, relocVAddress, targetVAddress, ref.addend());
break;
case R_X86_64_TPOFF64:
+ case R_X86_64_DTPOFF32:
case R_X86_64_TPOFF32: {
// Get the start and end of the TLS segment.
if (_tlsSize == 0) {
@@ -88,7 +91,7 @@ ErrorOr<void> X86_64TargetRelocationHand
if (tbss)
_tlsSize += tbss->memSize();
}
- if (ref.kind() == R_X86_64_TPOFF32) {
+ if (ref.kind() == R_X86_64_TPOFF32 || ref.kind() == R_X86_64_DTPOFF32) {
int32_t result = (int32_t)(targetVAddress - _tlsSize);
*reinterpret_cast<llvm::support::little32_t *>(location) = result;
} else {
@@ -96,6 +99,13 @@ ErrorOr<void> X86_64TargetRelocationHand
*reinterpret_cast<llvm::support::little64_t *>(location) = result;
}
break;
+ case R_X86_64_TLSLD:
+ // Rewrite to move %fs:0 into %rax. Technically we should verify that the
+ // next relocation is a PC32 to __tls_get_addr...
+ static uint8_t instr[] = { 0x66, 0x66, 0x66, 0x64, 0x48, 0x8b, 0x04, 0x25,
+ 0x00, 0x00, 0x00, 0x00 };
+ std::memcpy(location - 3, instr, sizeof(instr));
+ break;
}
// Runtime only relocations. Ignore here.
case R_X86_64_IRELATIVE:
@@ -143,9 +153,35 @@ public:
return ArrayRef<uint8_t>();
}
};
+
+class TLSGETADDRAtom : public SimpleDefinedAtom {
+public:
+ TLSGETADDRAtom(const File &f) : SimpleDefinedAtom(f) {}
+
+ virtual StringRef name() const { return "__tls_get_addr"; }
+
+ virtual Scope scope() const { return scopeGlobal; }
+
+ virtual Merge merge() const { return mergeAsWeak; }
+
+ virtual SectionChoice sectionChoice() const { return sectionCustomRequired; }
+
+ virtual StringRef customSectionName() const { return ".text"; }
+
+ virtual ContentType contentType() const { return typeCode; }
+
+ virtual uint64_t size() const { return 0; }
+
+ virtual ContentPermissions permissions() const { return permR_X; }
+
+ virtual Alignment alignment() const { return Alignment(0); }
+
+ virtual ArrayRef<uint8_t> rawContent() const { return ArrayRef<uint8_t>(); }
+};
} // end anon namespace
void X86_64TargetHandler::addFiles(InputFiles &f) {
_gotFile.addAtom(*new (_gotFile._alloc) GLOBAL_OFFSET_TABLEAtom(_gotFile));
+ _gotFile.addAtom(*new (_gotFile._alloc) TLSGETADDRAtom(_gotFile));
f.appendFile(_gotFile);
}
Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp?rev=174425&r1=174424&r2=174425&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp Tue Feb 5 13:14:07 2013
@@ -137,8 +137,12 @@ class GOTPLTPass LLVM_FINAL : public Pas
const DefinedAtom *da = dyn_cast_or_null<const DefinedAtom>(ref.target());
switch (ref.kind()) {
case R_X86_64_PLT32:
- // Static code doesn't need PLTs.
- const_cast<Reference &>(ref).setKind(R_X86_64_PC32);
+ // __tls_get_addr is handled elsewhere.
+ if (ref.target() && ref.target()->name() == "__tls_get_addr")
+ const_cast<Reference &>(ref).setKind(R_X86_64_NONE);
+ else
+ // Static code doesn't need PLTs.
+ const_cast<Reference &>(ref).setKind(R_X86_64_PC32);
break;
case R_X86_64_PC32: // IFUNC
if (da && da->contentType() == DefinedAtom::typeResolver)
Modified: lld/trunk/test/elf/Inputs/tls.S
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Inputs/tls.S?rev=174425&r1=174424&r2=174425&view=diff
==============================================================================
--- lld/trunk/test/elf/Inputs/tls.S (original)
+++ lld/trunk/test/elf/Inputs/tls.S Tue Feb 5 13:14:07 2013
@@ -17,6 +17,15 @@ GOTTPOFF:
movl %fs:0(%rax), %eax
ret
+ .text
+ .globl TLSLD
+ .type TLSLD, at function
+TLSLD:
+ leaq tls0 at tlsld(%rip), %rdi
+ call __tls_get_addr at plt
+ leaq tls0 at dtpoff(%rax), %rax
+ ret
+
.type tls0, at object # @tls0
.section .tbss,"awT", at nobits
.globl tls0
Modified: lld/trunk/test/elf/Inputs/tls.x86-64
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Inputs/tls.x86-64?rev=174425&r1=174424&r2=174425&view=diff
==============================================================================
Binary files lld/trunk/test/elf/Inputs/tls.x86-64 (original) and lld/trunk/test/elf/Inputs/tls.x86-64 Tue Feb 5 13:14:07 2013 differ
Modified: lld/trunk/test/elf/tls.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/tls.test?rev=174425&r1=174424&r2=174425&view=diff
==============================================================================
--- lld/trunk/test/elf/tls.test (original)
+++ lld/trunk/test/elf/tls.test Tue Feb 5 13:14:07 2013
@@ -26,8 +26,14 @@ YAML: type: got
YAML: kind: R_X86_64_TPOFF64
YAML: target: tls2
+// main
CHECK: addl %fs:-4
CHECK: addl %fs:-8
CHECK: addl %fs:-12
+// GOTTPOFF
CHECK: movq {{[0-9]+}}(%rip)
+
+// TLSLD
+CHECK: movq %fs:0, %rax
+CHECK: leaq -8(%rax), %rax
More information about the llvm-commits
mailing list