summaryrefslogtreecommitdiffstats
path: root/lld/ELF/OutputSections.cpp
diff options
context:
space:
mode:
authorSimon Atanasyan <simon@atanasyan.com>2016-04-25 20:25:05 +0000
committerSimon Atanasyan <simon@atanasyan.com>2016-04-25 20:25:05 +0000
commit1ef1bf87dc8c26c61a2a51fea4c9d3aadda07d13 (patch)
tree89a8e80bfbd28dd4ac3f0315d3fcddcf4fe431fb /lld/ELF/OutputSections.cpp
parentd60d96ffae95f32036819239457fd6a9243c69a3 (diff)
downloadbcm5719-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.cpp36
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;
OpenPOWER on IntegriCloud