diff options
| -rw-r--r-- | lld/ELF/Relocations.cpp | 85 |
1 files changed, 39 insertions, 46 deletions
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 715066c56d8..a0215e96894 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -81,9 +81,8 @@ static std::string getLocation(InputSectionBase &S, const SymbolBody &Sym, static bool refersToGotEntry(RelExpr Expr) { return isRelExprOneOf<R_GOT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF, - R_MIPS_GOT_OFF32, R_MIPS_TLSGD, R_MIPS_TLSLD, - R_GOT_PAGE_PC, R_GOT_PC, R_GOT_FROM_END, R_TLSGD, - R_TLSGD_PC, R_TLSDESC, R_TLSDESC_PAGE>(Expr); + R_MIPS_GOT_OFF32, R_GOT_PAGE_PC, R_GOT_PC, + R_GOT_FROM_END>(Expr); } static bool isPreemptible(const SymbolBody &Body, uint32_t Type) { @@ -250,6 +249,9 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, {R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Body}); return 1; } + + if (Expr == R_TLSDESC_CALL) + return 1; return 0; } @@ -817,18 +819,47 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { R_GOTREL_FROM_END, R_PPC_TOC>(Expr)) In<ELFT>::Got->HasGotOffRel = true; + // Read an addend. int64_t Addend = computeAddend<ELFT>(Rel, Sec.Data.data()); if (Config->EMachine == EM_MIPS) Addend += computeMipsAddend<ELFT>(Rel, Sec, Expr, Body, End); + // Process some TLS relocations, including relaxing TLS relocations. + // Note that this function does not handle all TLS relocations. if (unsigned Processed = handleTlsRelocation<ELFT>(Type, Body, Sec, Offset, Addend, Expr)) { I += (Processed - 1); continue; } - if (Expr == R_TLSDESC_CALL) - continue; + // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol. + if (needsPlt(Expr) && !Body.isInPlt()) { + if (Body.isGnuIFunc() && !Preemptible) + addPltEntry(InX::Iplt, In<ELFT>::IgotPlt, In<ELFT>::RelaIplt, + Target->IRelativeRel, Body, true); + else + addPltEntry(InX::Plt, In<ELFT>::GotPlt, In<ELFT>::RelaPlt, + Target->PltRel, Body, !Preemptible); + } + + // Create a GOT slot if a relocation needs GOT. + if (refersToGotEntry(Expr)) { + if (Config->EMachine == EM_MIPS) { + // MIPS ABI has special rules to process GOT entries and doesn't + // require relocation entries for them. A special case is TLS + // relocations. In that case dynamic loader applies dynamic + // relocations to initialize TLS 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 + In<ELFT>::MipsGot->addEntry(Body, Addend, Expr); + if (Body.isTls() && Body.isPreemptible()) + In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, In<ELFT>::MipsGot, + Body.getGotOffset(), false, &Body, 0}); + } else if (!Body.isInGot()) { + addGotEntry<ELFT>(Body, Preemptible); + } + } if (!needsPlt(Expr) && !refersToGotEntry(Expr) && isPreemptible(Body, Type)) { @@ -863,7 +894,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { } // If the relocation points to something in the file, we can process it. - bool Constant = + bool IsConstant = isStaticLinkTimeConstant<ELFT>(Expr, Type, Body, Sec, Rel.r_offset); // If the output being produced is position independent, the final value @@ -871,53 +902,15 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { // dynamic linker. We can however do better than just copying the incoming // relocation. We can process some of it and and just ask the dynamic // linker to add the load address. - if (!Constant) + if (!IsConstant) In<ELFT>::RelaDyn->addReloc( {Target->RelativeRel, &Sec, Offset, true, &Body, Addend}); // If the produced value is a constant, we just remember to write it // when outputting this section. We also have to do it if the format // uses Elf_Rel, since in that case the written value is the addend. - if (Constant || !RelTy::IsRela) + if (IsConstant || !RelTy::IsRela) Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); - - // At this point we are done with the relocated position. Some relocations - // also require us to create a got or plt entry. - - // If a relocation needs PLT, we create a PLT and a GOT slot for the symbol. - if (needsPlt(Expr)) { - if (Body.isInPlt()) - continue; - - if (Body.isGnuIFunc() && !Preemptible) - addPltEntry(InX::Iplt, In<ELFT>::IgotPlt, In<ELFT>::RelaIplt, - Target->IRelativeRel, Body, true); - else - addPltEntry(InX::Plt, In<ELFT>::GotPlt, In<ELFT>::RelaPlt, - Target->PltRel, Body, !Preemptible); - continue; - } - - if (refersToGotEntry(Expr)) { - if (Config->EMachine == EM_MIPS) { - // MIPS ABI has special rules to process GOT entries and doesn't - // require relocation entries for them. A special case is TLS - // relocations. In that case dynamic loader applies dynamic - // relocations to initialize TLS 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 - In<ELFT>::MipsGot->addEntry(Body, Addend, Expr); - if (Body.isTls() && Body.isPreemptible()) - In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, In<ELFT>::MipsGot, - Body.getGotOffset(), false, &Body, 0}); - continue; - } - - if (!Body.isInGot()) - addGotEntry<ELFT>(Body, Preemptible); - continue; - } } } |

