summaryrefslogtreecommitdiffstats
path: root/lld/ELF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Writer.cpp')
-rw-r--r--lld/ELF/Writer.cpp21
1 files changed, 18 insertions, 3 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index bc2c7ad43f9..ce334aa5e66 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -258,8 +258,13 @@ void Writer<ELFT>::scanRelocs(
}
bool NeedsGot = false;
+ bool NeedsMipsLocalGot = false;
bool NeedsPlt = false;
- if (Body) {
+ if (Config->EMachine == EM_MIPS && needsMipsLocalGot(Type, Body)) {
+ NeedsMipsLocalGot = true;
+ // FIXME (simon): Do not add so many redundant entries.
+ Out<ELFT>::Got->addMipsLocalEntry();
+ } else if (Body) {
if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
if (E->NeedsCopy)
continue;
@@ -294,13 +299,23 @@ void Writer<ELFT>::scanRelocs(
}
if (Config->EMachine == EM_MIPS) {
- if (NeedsGot) {
+ if (Type == R_MIPS_LO16)
+ // Ignore R_MIPS_LO16 relocation. If it is a pair for R_MIPS_GOT16 we
+ // already completed all required action (GOT entry allocation) when
+ // handle R_MIPS_GOT16a. If it is a pair for R_MIPS_HI16 against
+ // _gp_disp it does not require dynamic relocation. If its a pair for
+ // R_MIPS_HI16 against a regular symbol it does not require dynamic
+ // relocation too because that case is possible for executable file
+ // linking only.
+ continue;
+ if (NeedsGot || NeedsMipsLocalGot) {
// MIPS ABI has special rules to process GOT entries
// and doesn't require relocation entries for them.
// 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
- Body->setUsedInDynamicReloc();
+ if (NeedsGot)
+ Body->setUsedInDynamicReloc();
continue;
}
if (Body == Config->MipsGpDisp)
OpenPOWER on IntegriCloud