[lld] r174154 - [ELF][x86-84] Add static TLS support.
Michael J. Spencer
bigcheesegs at gmail.com
Thu Jan 31 23:13:49 PST 2013
Author: mspencer
Date: Fri Feb 1 01:13:49 2013
New Revision: 174154
URL: http://llvm.org/viewvc/llvm-project?rev=174154&view=rev
Log:
[ELF][x86-84] Add static TLS support.
Added:
lld/trunk/test/elf/Inputs/tls.c
lld/trunk/test/elf/Inputs/tls.x86-64
lld/trunk/test/elf/tls.test
Modified:
lld/trunk/lib/ReaderWriter/ELF/Atoms.h
lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
lld/trunk/lib/ReaderWriter/ELF/File.h
lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h
lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h
lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
Modified: lld/trunk/lib/ReaderWriter/ELF/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=174154&r1=174153&r2=174154&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Atoms.h Fri Feb 1 01:13:49 2013
@@ -253,6 +253,12 @@ public:
return elfAtomHandler.contentType(this);
}
+ if (_section->sh_flags ==
+ (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_TLS)) {
+ return _section->sh_type == llvm::ELF::SHT_NOBITS ? typeTLVInitialZeroFill
+ : typeTLVInitialData;
+ }
+
if (_symbol->getType() == llvm::ELF::STT_GNU_IFUNC)
return typeResolver;
Modified: lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h?rev=174154&r1=174153&r2=174154&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h Fri Feb 1 01:13:49 2013
@@ -291,7 +291,11 @@ Layout::SectionOrder DefaultLayout<ELFT>
return ORDER_GOT;
case DefinedAtom::typeStub:
return ORDER_PLT;
-
+
+ case DefinedAtom::typeTLVInitialData:
+ return ORDER_TDATA;
+ case DefinedAtom::typeTLVInitialZeroFill:
+ return ORDER_TBSS;
default:
// If we get passed in a section push it to OTHER
if (contentPermissions == DefinedAtom::perm___)
Modified: lld/trunk/lib/ReaderWriter/ELF/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/File.h?rev=174154&r1=174153&r2=174154&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/File.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/File.h Fri Feb 1 01:13:49 2013
@@ -231,7 +231,8 @@ public:
TargetHandler.targetAtomHandler();
c = elfAtomHandler.contentType(*si);
- if (c == DefinedAtom::typeZeroFill)
+ if (c == DefinedAtom::typeZeroFill ||
+ c == DefinedAtom::typeTLVInitialZeroFill)
isCommon = true;
}
Modified: lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h?rev=174154&r1=174153&r2=174154&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/HeaderChunks.h Fri Feb 1 01:13:49 2013
@@ -156,20 +156,11 @@ public:
}
private:
- std::vector<Elf_Phdr *> _ph;
- PhIterT _phi;
- llvm::BumpPtrAllocator _allocator;
-};
-
-template<class ELFT>
-bool
-ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
- Elf_Phdr *phdr = nullptr;
- bool ret = false;
-
- for (auto slice : segment->slices()) {
+ std::pair<Elf_Phdr *, bool> allocateProgramHeader() {
+ Elf_Phdr *phdr;
+ bool ret = false;
if (_phi == _ph.end()) {
- phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
+ phdr = new (_allocator) Elf_Phdr;
_ph.push_back(phdr);
_phi = _ph.end();
ret = true;
@@ -177,20 +168,50 @@ ProgramHeader<ELFT>::addSegment(Segment<
phdr = (*_phi);
++_phi;
}
- phdr->p_type = segment->segmentType();
- phdr->p_offset = slice->fileOffset();
- phdr->p_vaddr = slice->virtualAddr();
- phdr->p_paddr = slice->virtualAddr();
- phdr->p_filesz = slice->fileSize();
- phdr->p_memsz = slice->memSize();
- phdr->p_flags = segment->flags();
- phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
- segment->pageSize() : slice->align2();
+
+ return std::make_pair(phdr, ret);
+ }
+
+ std::vector<Elf_Phdr *> _ph;
+ PhIterT _phi;
+ llvm::BumpPtrAllocator _allocator;
+};
+
+template <class ELFT>
+bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
+ bool allocatedNew = false;
+ for (auto slice : segment->slices()) {
+ // If we have a TLS segment, emit a LOAD first.
+ if (segment->segmentType() == llvm::ELF::PT_TLS) {
+ auto phdr = allocateProgramHeader();
+ if (phdr.second)
+ allocatedNew = true;
+ phdr.first->p_type = llvm::ELF::PT_LOAD;
+ phdr.first->p_offset = slice->fileOffset();
+ phdr.first->p_vaddr = slice->virtualAddr();
+ phdr.first->p_paddr = slice->virtualAddr();
+ phdr.first->p_filesz = slice->fileSize();
+ phdr.first->p_memsz = slice->memSize();
+ phdr.first->p_flags = segment->flags();
+ phdr.first->p_align = slice->align2();
+ }
+ auto phdr = allocateProgramHeader();
+ if (phdr.second)
+ allocatedNew = true;
+ phdr.first->p_type = segment->segmentType();
+ phdr.first->p_offset = slice->fileOffset();
+ phdr.first->p_vaddr = slice->virtualAddr();
+ phdr.first->p_paddr = slice->virtualAddr();
+ phdr.first->p_filesz = slice->fileSize();
+ phdr.first->p_memsz = slice->memSize();
+ phdr.first->p_flags = segment->flags();
+ phdr.first->p_align = (phdr.first->p_type == llvm::ELF::PT_LOAD) ?
+ segment->pageSize() : slice->align2();
}
this->_fsize = fileSize();
this->_msize = this->_fsize;
- return ret;
+ return allocatedNew;
}
template <class ELFT>
Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=174154&r1=174153&r2=174154&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Fri Feb 1 01:13:49 2013
@@ -240,6 +240,7 @@ const AtomLayout &Section<ELFT>::appendA
case DefinedAtom::typeGOT:
case DefinedAtom::typeStub:
case DefinedAtom::typeResolver:
+ case DefinedAtom::typeTLVInitialData:
_atoms.push_back(new (_alloc) AtomLayout(atom, fOffset, 0));
this->_fsize = fOffset + definedAtom->size();
this->_msize = mOffset + definedAtom->size();
@@ -249,6 +250,7 @@ const AtomLayout &Section<ELFT>::appendA
<< fOffset << "\n");
break;
case DefinedAtom::typeZeroFill:
+ case DefinedAtom::typeTLVInitialZeroFill:
_atoms.push_back(new (_alloc) AtomLayout(atom, mOffset, 0));
this->_msize = mOffset + definedAtom->size();
break;
@@ -285,7 +287,10 @@ Section<ELFT>::flags() {
case DefinedAtom::permRW_:
case DefinedAtom::permRW_L:
- return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
+ if (_contentType == DefinedAtom::typeTLVInitialData ||
+ _contentType == DefinedAtom::typeTLVInitialZeroFill)
+ return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_TLS;
+ return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
case DefinedAtom::permRWX:
return llvm::ELF::SHF_ALLOC |
@@ -314,9 +319,11 @@ Section<ELFT>::type() {
case DefinedAtom::typeGOT:
case DefinedAtom::typeStub:
case DefinedAtom::typeResolver:
+ case DefinedAtom::typeTLVInitialData:
return llvm::ELF::SHT_PROGBITS;
case DefinedAtom::typeZeroFill:
+ case DefinedAtom::typeTLVInitialZeroFill:
return llvm::ELF::SHT_NOBITS;
// Case to handle section types
@@ -638,6 +645,11 @@ SymbolTable<ELFT>::addSymbol(const Atom
type = llvm::ELF::STT_OBJECT;
symbol->st_value = addr;
break;
+ case DefinedAtom::typeTLVInitialData:
+ case DefinedAtom::typeTLVInitialZeroFill:
+ type = llvm::ELF::STT_TLS;
+ symbol->st_value = addr;
+ break;
default:
type = llvm::ELF::STT_NOTYPE;
}
Modified: lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h?rev=174154&r1=174153&r2=174154&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h Fri Feb 1 01:13:49 2013
@@ -348,6 +348,8 @@ template <class ELFT> void Segment<ELFT>
else
s->assignVirtualAddress(addr);
}
+ if (isTLSSegment)
+ tlsStartAddr += section->memSize();
addr += section->memSize();
section->setMemSize(addr - section->virtualAddr());
}
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=174154&r1=174153&r2=174154&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp Fri Feb 1 01:13:49 2013
@@ -73,6 +73,24 @@ ErrorOr<void> X86_64TargetRelocationHand
case R_X86_64_32S:
reloc32S(location, relocVAddress, targetVAddress, ref.addend());
break;
+ case R_X86_64_TPOFF32: {
+ // Get the start and end of the TLS segment.
+ if (_tlsSize == 0) {
+ auto tdata = _targetInfo.getTargetHandler<X86_64ELFType>().targetLayout()
+ .findOutputSection(".tdata");
+ auto tbss = _targetInfo.getTargetHandler<X86_64ELFType>().targetLayout()
+ .findOutputSection(".tbss");
+ // HACK: The tdata and tbss sections end up together to from the TLS
+ // segment. This should actually use the TLS program header entry.
+ if (tdata)
+ _tlsSize = tdata->memSize();
+ if (tbss)
+ _tlsSize += tbss->memSize();
+ }
+ int32_t result = (int32_t)(targetVAddress - _tlsSize);
+ *reinterpret_cast<llvm::support::little32_t *>(location) = result;
+ break;
+ }
// Runtime only relocations. Ignore here.
case R_X86_64_IRELATIVE:
break;
Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h?rev=174154&r1=174153&r2=174154&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h Fri Feb 1 01:13:49 2013
@@ -23,13 +23,16 @@ class X86_64TargetInfo;
class X86_64TargetRelocationHandler LLVM_FINAL
: public TargetRelocationHandler<X86_64ELFType> {
public:
- X86_64TargetRelocationHandler(const X86_64TargetInfo &ti) : _targetInfo(ti) {}
+ X86_64TargetRelocationHandler(const X86_64TargetInfo &ti)
+ : _tlsSize(0), _targetInfo(ti) {}
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
const AtomLayout &,
const Reference &)const;
private:
+ // Cached size of the TLS segment.
+ mutable uint64_t _tlsSize;
const X86_64TargetInfo &_targetInfo;
};
Added: lld/trunk/test/elf/Inputs/tls.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Inputs/tls.c?rev=174154&view=auto
==============================================================================
--- lld/trunk/test/elf/Inputs/tls.c (added)
+++ lld/trunk/test/elf/Inputs/tls.c Fri Feb 1 01:13:49 2013
@@ -0,0 +1,11 @@
+extern __thread int tls0;
+extern __thread int tls1;
+extern __thread int tls2;
+
+__thread int tls0 = 0;
+__thread int tls1 = 0;
+__thread int tls2 = 1;
+
+int main() {
+ return tls0 + tls1 + tls2;
+}
Added: lld/trunk/test/elf/Inputs/tls.x86-64
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Inputs/tls.x86-64?rev=174154&view=auto
==============================================================================
Binary files lld/trunk/test/elf/Inputs/tls.x86-64 (added) and lld/trunk/test/elf/Inputs/tls.x86-64 Fri Feb 1 01:13:49 2013 differ
Added: lld/trunk/test/elf/tls.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/tls.test?rev=174154&view=auto
==============================================================================
--- lld/trunk/test/elf/tls.test (added)
+++ lld/trunk/test/elf/tls.test Fri Feb 1 01:13:49 2013
@@ -0,0 +1,8 @@
+RUN: lld -core -target x86_64-linux %p/Inputs/tls.x86-64 -output=%t \
+RUN: -noinhibit-exec -entry=main && llvm-objdump -d %t | FileCheck %s
+
+// Verify that the TLS accesses have the correct offsets.
+
+CHECK: movl %fs:-8
+CHECK: movl %fs:-4
+CHECK: movl %fs:-12
More information about the llvm-commits
mailing list