summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Relocations.cpp85
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;
- }
}
}
OpenPOWER on IntegriCloud