summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Writer.cpp27
1 files changed, 18 insertions, 9 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c99d1ed207b..a09a570384f 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -306,6 +306,24 @@ void Writer<ELFT>::scanRelocs(
}
}
+ // An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
+ // to the symbol go through the PLT. This is true even for a local
+ // symbol, although local symbols normally do not require PLT entries.
+ if (Body && isGnuIFunc<ELFT>(*Body)) {
+ Body->setUsedInDynamicReloc();
+ if (Body->isInGot())
+ continue;
+ Out<ELFT>::Plt->addEntry(Body);
+ if (Target->UseLazyBinding) {
+ Out<ELFT>::GotPlt->addEntry(Body);
+ Out<ELFT>::RelaPlt->addReloc({&C, &RI});
+ } else {
+ Out<ELFT>::Got->addEntry(Body);
+ Out<ELFT>::RelaDyn->addReloc({&C, &RI});
+ }
+ continue;
+ }
+
bool NeedsGot = false;
bool NeedsPlt = false;
@@ -328,15 +346,6 @@ void Writer<ELFT>::scanRelocs(
}
}
- // An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
- // to the symbol go through the PLT. This is true even for a local
- // symbol, although local symbols normally do not require PLT entries.
- if (Body && isGnuIFunc<ELFT>(*Body)) {
- Body->setUsedInDynamicReloc();
- Out<ELFT>::RelaPlt->addReloc({&C, &RI});
- continue;
- }
-
if (Config->EMachine == EM_MIPS) {
if (Type == R_MIPS_LO16)
// Ignore R_MIPS_LO16 relocation. If it is a pair for R_MIPS_GOT16 we
OpenPOWER on IntegriCloud