diff options
author | Simon Atanasyan <simon@atanasyan.com> | 2016-04-25 20:25:05 +0000 |
---|---|---|
committer | Simon Atanasyan <simon@atanasyan.com> | 2016-04-25 20:25:05 +0000 |
commit | 1ef1bf87dc8c26c61a2a51fea4c9d3aadda07d13 (patch) | |
tree | 89a8e80bfbd28dd4ac3f0315d3fcddcf4fe431fb /lld/ELF/OutputSections.cpp | |
parent | d60d96ffae95f32036819239457fd6a9243c69a3 (diff) | |
download | bcm5719-llvm-1ef1bf87dc8c26c61a2a51fea4c9d3aadda07d13.tar.gz bcm5719-llvm-1ef1bf87dc8c26c61a2a51fea4c9d3aadda07d13.zip |
[ELF][MIPS] Move MIPS GOT header generation to the GotSection
MIPS is the only target requires GOT header. We already have MIPS
specific code in the `GotSection` class, so move MIPS GOT header
generation there and delete redundant stuff like `GotHeaderEntriesNum`
field and `writeGotHeader` method.
Differential Revision: http://reviews.llvm.org/D19465
llvm-svn: 267460
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
-rw-r--r-- | lld/ELF/OutputSections.cpp | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index efcfcb30b9f..6eeaa3ffc8e 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -146,7 +146,7 @@ template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) { template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { if (Sym.hasGlobalDynIndex()) return false; - Sym.GlobalDynIndex = Target->GotHeaderEntriesNum + Entries.size(); + Sym.GlobalDynIndex = Entries.size(); // Global Dynamic TLS entries take two GOT slots. Entries.push_back(&Sym); Entries.push_back(nullptr); @@ -175,7 +175,9 @@ GotSection<ELFT>::getMipsLocalPageOffset(uintX_t EntryValue) { template <class ELFT> typename GotSection<ELFT>::uintX_t GotSection<ELFT>::getMipsLocalEntryOffset(uintX_t EntryValue) { - size_t NewIndex = Target->GotHeaderEntriesNum + MipsLocalGotPos.size(); + // Take into account MIPS GOT header. + // See comment in the GotSection::writeTo. + size_t NewIndex = MipsLocalGotPos.size() + 2; auto P = MipsLocalGotPos.insert(std::make_pair(EntryValue, NewIndex)); assert(!P.second || MipsLocalGotPos.size() <= MipsLocalEntries); return P.first->second * sizeof(uintX_t) - MipsGPOffset; @@ -200,10 +202,14 @@ const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const { template <class ELFT> unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const { - return Target->GotHeaderEntriesNum + MipsLocalEntries; + return MipsLocalEntries; } template <class ELFT> void GotSection<ELFT>::finalize() { + if (Config->EMachine == EM_MIPS) + // Take into account MIPS GOT header. + // See comment in the GotSection::writeTo. + MipsLocalEntries += 2; for (const OutputSectionBase<ELFT> *OutSec : MipsOutSections) { // Calculate an upper bound of MIPS GOT entries required to store page // addresses of local symbols. We assume the worst case - each 64kb @@ -212,18 +218,32 @@ template <class ELFT> void GotSection<ELFT>::finalize() { // in the GOT entry is calculated as (value + 0x8000) & ~0xffff. MipsLocalEntries += (OutSec->getSize() + 0x8000 + 0xfffe) / 0xffff; } - this->Header.sh_size = - (Target->GotHeaderEntriesNum + MipsLocalEntries + Entries.size()) * - sizeof(uintX_t); + this->Header.sh_size = (MipsLocalEntries + Entries.size()) * sizeof(uintX_t); } template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) { - Target->writeGotHeader(Buf); + if (Config->EMachine == EM_MIPS) { + // Set the MSB of the second GOT slot. This is not required by any + // MIPS ABI documentation, though. + // + // There is a comment in glibc saying that "The MSB of got[1] of a + // gnu object is set to identify gnu objects," and in GNU gold it + // says "the second entry will be used by some runtime loaders". + // But how this field is being used is unclear. + // + // We are not really willing to mimic other linkers behaviors + // without understanding why they do that, but because all files + // generated by GNU tools have this special GOT value, and because + // we've been doing this for years, it is probably a safe bet to + // keep doing this for now. We really need to revisit this to see + // if we had to do this. + auto *P = reinterpret_cast<typename ELFT::Off *>(Buf); + P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31); + } for (std::pair<uintX_t, size_t> &L : MipsLocalGotPos) { uint8_t *Entry = Buf + L.second * sizeof(uintX_t); write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, L.first); } - Buf += Target->GotHeaderEntriesNum * sizeof(uintX_t); Buf += MipsLocalEntries * sizeof(uintX_t); for (const SymbolBody *B : Entries) { uint8_t *Entry = Buf; |