From: Michael J. Spencer Date: Fri, 1 Feb 2013 07:13:49 +0000 (+0000) Subject: [ELF][x86-84] Add static TLS support. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b0ed8e80d82f40f7b35e50d551952e045660742f;p=platform%2Fupstream%2Fllvm.git [ELF][x86-84] Add static TLS support. llvm-svn: 174154 --- diff --git a/lld/lib/ReaderWriter/ELF/Atoms.h b/lld/lib/ReaderWriter/ELF/Atoms.h index cd6a1c9..a7534e3 100644 --- a/lld/lib/ReaderWriter/ELF/Atoms.h +++ b/lld/lib/ReaderWriter/ELF/Atoms.h @@ -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; diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h index 326019f..76e55e2 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h +++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h @@ -291,7 +291,11 @@ Layout::SectionOrder DefaultLayout::getSectionOrder( 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___) diff --git a/lld/lib/ReaderWriter/ELF/File.h b/lld/lib/ReaderWriter/ELF/File.h index 15abec8..6d297ed 100644 --- a/lld/lib/ReaderWriter/ELF/File.h +++ b/lld/lib/ReaderWriter/ELF/File.h @@ -231,7 +231,8 @@ public: TargetHandler.targetAtomHandler(); c = elfAtomHandler.contentType(*si); - if (c == DefinedAtom::typeZeroFill) + if (c == DefinedAtom::typeZeroFill || + c == DefinedAtom::typeTLVInitialZeroFill) isCommon = true; } diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h index e2512b5..f3660e8 100644 --- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h +++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h @@ -156,20 +156,11 @@ public: } private: - std::vector _ph; - PhIterT _phi; - llvm::BumpPtrAllocator _allocator; -}; - -template -bool -ProgramHeader::addSegment(Segment *segment) { - Elf_Phdr *phdr = nullptr; - bool ret = false; - - for (auto slice : segment->slices()) { + std::pair allocateProgramHeader() { + Elf_Phdr *phdr; + bool ret = false; if (_phi == _ph.end()) { - phdr = new(_allocator.Allocate()) Elf_Phdr; + phdr = new (_allocator) Elf_Phdr; _ph.push_back(phdr); _phi = _ph.end(); ret = true; @@ -177,20 +168,50 @@ ProgramHeader::addSegment(Segment *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 _ph; + PhIterT _phi; + llvm::BumpPtrAllocator _allocator; +}; + +template +bool ProgramHeader::addSegment(Segment *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 diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h index 101089d..6fea1bc 100644 --- a/lld/lib/ReaderWriter/ELF/SectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h @@ -240,6 +240,7 @@ const AtomLayout &Section::appendAtom(const Atom *atom) { 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::appendAtom(const Atom *atom) { << 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::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::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::addSymbol(const Atom *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; } diff --git a/lld/lib/ReaderWriter/ELF/SegmentChunks.h b/lld/lib/ReaderWriter/ELF/SegmentChunks.h index efdfc65..7db4913 100644 --- a/lld/lib/ReaderWriter/ELF/SegmentChunks.h +++ b/lld/lib/ReaderWriter/ELF/SegmentChunks.h @@ -348,6 +348,8 @@ template void Segment::assignVirtualAddress(uint64_t &addr) { else s->assignVirtualAddress(addr); } + if (isTLSSegment) + tlsStartAddr += section->memSize(); addr += section->memSize(); section->setMemSize(addr - section->virtualAddr()); } diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp index 398ff5f..ddd1a65 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp @@ -73,6 +73,24 @@ ErrorOr X86_64TargetRelocationHandler::applyRelocation( 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().targetLayout() + .findOutputSection(".tdata"); + auto tbss = _targetInfo.getTargetHandler().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(location) = result; + break; + } // Runtime only relocations. Ignore here. case R_X86_64_IRELATIVE: break; diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h index 9428478..c18e8f9 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h @@ -23,13 +23,16 @@ class X86_64TargetInfo; class X86_64TargetRelocationHandler LLVM_FINAL : public TargetRelocationHandler { public: - X86_64TargetRelocationHandler(const X86_64TargetInfo &ti) : _targetInfo(ti) {} + X86_64TargetRelocationHandler(const X86_64TargetInfo &ti) + : _tlsSize(0), _targetInfo(ti) {} virtual ErrorOr applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &, const Reference &)const; private: + // Cached size of the TLS segment. + mutable uint64_t _tlsSize; const X86_64TargetInfo &_targetInfo; }; diff --git a/lld/test/elf/Inputs/tls.c b/lld/test/elf/Inputs/tls.c new file mode 100644 index 0000000..6723507 --- /dev/null +++ b/lld/test/elf/Inputs/tls.c @@ -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; +} diff --git a/lld/test/elf/Inputs/tls.x86-64 b/lld/test/elf/Inputs/tls.x86-64 new file mode 100644 index 0000000..dba3907 Binary files /dev/null and b/lld/test/elf/Inputs/tls.x86-64 differ diff --git a/lld/test/elf/tls.test b/lld/test/elf/tls.test new file mode 100644 index 0000000..7a1281a --- /dev/null +++ b/lld/test/elf/tls.test @@ -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