diff options
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
-rw-r--r-- | lld/ELF/OutputSections.cpp | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 5007ba003fa..c2310ca617f 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -72,11 +72,13 @@ template <class ELFT> GotSection<ELFT>::GotSection() : OutputSectionBase<ELFT>(".got", llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) { + if (Config->EMachine == EM_MIPS) + this->Header.sh_flags |= llvm::ELF::SHF_MIPS_GPREL; this->Header.sh_addralign = sizeof(uintX_t); } template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) { - Sym->GotIndex = Entries.size(); + Sym->GotIndex = Target->getGotHeaderEntriesNum() + Entries.size(); Entries.push_back(Sym); } @@ -86,11 +88,23 @@ GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const { return this->getVA() + B.GotIndex * sizeof(uintX_t); } +template <class ELFT> void GotSection<ELFT>::finalize() { + this->Header.sh_size = + (Target->getGotHeaderEntriesNum() + Entries.size()) * sizeof(uintX_t); +} + template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) { + Target->writeGotHeaderEntries(Buf); + Buf += Target->getGotHeaderEntriesNum() * sizeof(uintX_t); for (const SymbolBody *B : Entries) { uint8_t *Entry = Buf; Buf += sizeof(uintX_t); - if (canBePreempted(B, false)) + // MIPS has special rules to fill up GOT entries. + // See "Global Offset Table" in Chapter 5 in the following document + // for detailed description: + // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + // As the first approach, we can just store addresses for all symbols. + if (Config->EMachine != EM_MIPS && canBePreempted(B, false)) continue; // The dynamic linker will take care of it. uintX_t VA = getSymVA<ELFT>(*B); write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA); |