forked from OSchip/llvm-project
[ELF] Replace local dynamic tls access with direct access.
llvm-svn: 174425
This commit is contained in:
parent
a5a9ec5755
commit
e6ab9f80a7
|
@ -61,6 +61,8 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||||
uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
|
uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
|
||||||
|
|
||||||
switch (ref.kind()) {
|
switch (ref.kind()) {
|
||||||
|
case R_X86_64_NONE:
|
||||||
|
break;
|
||||||
case R_X86_64_64:
|
case R_X86_64_64:
|
||||||
reloc64(location, relocVAddress, targetVAddress, ref.addend());
|
reloc64(location, relocVAddress, targetVAddress, ref.addend());
|
||||||
break;
|
break;
|
||||||
|
@ -74,6 +76,7 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||||
reloc32S(location, relocVAddress, targetVAddress, ref.addend());
|
reloc32S(location, relocVAddress, targetVAddress, ref.addend());
|
||||||
break;
|
break;
|
||||||
case R_X86_64_TPOFF64:
|
case R_X86_64_TPOFF64:
|
||||||
|
case R_X86_64_DTPOFF32:
|
||||||
case R_X86_64_TPOFF32: {
|
case R_X86_64_TPOFF32: {
|
||||||
// Get the start and end of the TLS segment.
|
// Get the start and end of the TLS segment.
|
||||||
if (_tlsSize == 0) {
|
if (_tlsSize == 0) {
|
||||||
|
@ -88,7 +91,7 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||||
if (tbss)
|
if (tbss)
|
||||||
_tlsSize += tbss->memSize();
|
_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);
|
int32_t result = (int32_t)(targetVAddress - _tlsSize);
|
||||||
*reinterpret_cast<llvm::support::little32_t *>(location) = result;
|
*reinterpret_cast<llvm::support::little32_t *>(location) = result;
|
||||||
} else {
|
} else {
|
||||||
|
@ -96,6 +99,13 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||||
*reinterpret_cast<llvm::support::little64_t *>(location) = result;
|
*reinterpret_cast<llvm::support::little64_t *>(location) = result;
|
||||||
}
|
}
|
||||||
break;
|
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.
|
// Runtime only relocations. Ignore here.
|
||||||
case R_X86_64_IRELATIVE:
|
case R_X86_64_IRELATIVE:
|
||||||
|
@ -143,9 +153,35 @@ public:
|
||||||
return ArrayRef<uint8_t>();
|
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
|
} // end anon namespace
|
||||||
|
|
||||||
void X86_64TargetHandler::addFiles(InputFiles &f) {
|
void X86_64TargetHandler::addFiles(InputFiles &f) {
|
||||||
_gotFile.addAtom(*new (_gotFile._alloc) GLOBAL_OFFSET_TABLEAtom(_gotFile));
|
_gotFile.addAtom(*new (_gotFile._alloc) GLOBAL_OFFSET_TABLEAtom(_gotFile));
|
||||||
|
_gotFile.addAtom(*new (_gotFile._alloc) TLSGETADDRAtom(_gotFile));
|
||||||
f.appendFile(_gotFile);
|
f.appendFile(_gotFile);
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,8 +137,12 @@ class GOTPLTPass LLVM_FINAL : public Pass {
|
||||||
const DefinedAtom *da = dyn_cast_or_null<const DefinedAtom>(ref.target());
|
const DefinedAtom *da = dyn_cast_or_null<const DefinedAtom>(ref.target());
|
||||||
switch (ref.kind()) {
|
switch (ref.kind()) {
|
||||||
case R_X86_64_PLT32:
|
case R_X86_64_PLT32:
|
||||||
// Static code doesn't need PLTs.
|
// __tls_get_addr is handled elsewhere.
|
||||||
const_cast<Reference &>(ref).setKind(R_X86_64_PC32);
|
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;
|
break;
|
||||||
case R_X86_64_PC32: // IFUNC
|
case R_X86_64_PC32: // IFUNC
|
||||||
if (da && da->contentType() == DefinedAtom::typeResolver)
|
if (da && da->contentType() == DefinedAtom::typeResolver)
|
||||||
|
|
|
@ -17,6 +17,15 @@ GOTTPOFF:
|
||||||
movl %fs:0(%rax), %eax
|
movl %fs:0(%rax), %eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl TLSLD
|
||||||
|
.type TLSLD,@function
|
||||||
|
TLSLD:
|
||||||
|
leaq tls0@tlsld(%rip), %rdi
|
||||||
|
call __tls_get_addr@plt
|
||||||
|
leaq tls0@dtpoff(%rax), %rax
|
||||||
|
ret
|
||||||
|
|
||||||
.type tls0,@object # @tls0
|
.type tls0,@object # @tls0
|
||||||
.section .tbss,"awT",@nobits
|
.section .tbss,"awT",@nobits
|
||||||
.globl tls0
|
.globl tls0
|
||||||
|
|
Binary file not shown.
|
@ -26,8 +26,14 @@ YAML: type: got
|
||||||
YAML: kind: R_X86_64_TPOFF64
|
YAML: kind: R_X86_64_TPOFF64
|
||||||
YAML: target: tls2
|
YAML: target: tls2
|
||||||
|
|
||||||
|
// main
|
||||||
CHECK: addl %fs:-4
|
CHECK: addl %fs:-4
|
||||||
CHECK: addl %fs:-8
|
CHECK: addl %fs:-8
|
||||||
CHECK: addl %fs:-12
|
CHECK: addl %fs:-12
|
||||||
|
|
||||||
|
// GOTTPOFF
|
||||||
CHECK: movq {{[0-9]+}}(%rip)
|
CHECK: movq {{[0-9]+}}(%rip)
|
||||||
|
|
||||||
|
// TLSLD
|
||||||
|
CHECK: movq %fs:0, %rax
|
||||||
|
CHECK: leaq -8(%rax), %rax
|
||||||
|
|
Loading…
Reference in New Issue