summaryrefslogtreecommitdiffstats
path: root/lld/ELF/OutputSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
-rw-r--r--lld/ELF/OutputSections.cpp18
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);
OpenPOWER on IntegriCloud