diff options
Diffstat (limited to 'lld/ELF/Writer.cpp')
| -rw-r--r-- | lld/ELF/Writer.cpp | 21 |
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) |

