// in the Sections vector, and recalculate the InputSection output section
// offsets.
// This may invalidate any output section offsets stored outside of InputSection
-static void mergeThunks(OutputSection *OS,
- std::vector<ThunkSection *> &Thunks) {
+template <class ELFT>
+void ThunkCreator<ELFT>::mergeThunks(OutputSection *OS,
+ std::vector<ThunkSection *> &Thunks) {
// Order Thunks in ascending OutSecOff
auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) {
return A->OutSecOff < B->OutSecOff;
OS->assignOffsets();
}
+template <class ELFT>
+ThunkSection *ThunkCreator<ELFT>::getOSThunkSec(ThunkSection *&TS,
+ OutputSection *OS) {
+ if (TS == nullptr) {
+ uint32_t Off = 0;
+ for (auto *IS : OS->Sections) {
+ Off = IS->OutSecOff + IS->getSize();
+ if ((IS->Flags & SHF_EXECINSTR) == 0)
+ break;
+ }
+ TS = make<ThunkSection>(OS, Off);
+ ThunkSections[OS].push_back(TS);
+ }
+ return TS;
+}
+
+template <class ELFT>
+ThunkSection *ThunkCreator<ELFT>::getISThunkSec(InputSection *IS,
+ OutputSection *OS) {
+ ThunkSection *TS = ThunkedSections.lookup(IS);
+ if (TS)
+ return TS;
+ auto *TOS = cast<OutputSection>(IS->OutSec);
+ TS = make<ThunkSection>(TOS, IS->OutSecOff);
+ ThunkSections[TOS].push_back(TS);
+ ThunkedSections[IS] = TS;
+ return TS;
+}
+
+template <class ELFT>
+std::pair<Thunk *, bool> ThunkCreator<ELFT>::getThunk(SymbolBody &Body,
+ uint32_t Type) {
+ auto res = ThunkedSymbols.insert({&Body, nullptr});
+ if (res.second)
+ res.first->second = addThunk<ELFT>(Type, Body);
+ return std::make_pair(res.first->second, res.second);
+}
+
// Process all relocations from the InputSections that have been assigned
// to OutputSections and redirect through Thunks if needed.
//
// FIXME: All Thunks are assumed to be in range of the relocation. Range
// extension Thunks are not yet supported.
template <class ELFT>
-bool elf::createThunks(ArrayRef<OutputSection *> OutputSections) {
- // Track Symbols that already have a Thunk
- DenseMap<SymbolBody *, Thunk *> ThunkedSymbols;
- // Track InputSections that have a ThunkSection placed in front
- DenseMap<InputSection *, ThunkSection *> ThunkedSections;
- // Track the ThunksSections that need to be inserted into an OutputSection
- std::map<OutputSection *, std::vector<ThunkSection *>> ThunkSections;
-
- // Find or create a Thunk for Body for relocation Type
- auto GetThunk = [&](SymbolBody &Body, uint32_t Type) {
- auto res = ThunkedSymbols.insert({&Body, nullptr});
- if (res.second == true)
- res.first->second = addThunk<ELFT>(Type, Body);
- return std::make_pair(res.first->second, res.second);
- };
-
- // Find or create a ThunkSection to be placed immediately before IS
- auto GetISThunkSec = [&](InputSection *IS, OutputSection *OS) {
- ThunkSection *TS = ThunkedSections.lookup(IS);
- if (TS)
- return TS;
- auto *TOS = cast<OutputSection>(IS->OutSec);
- TS = make<ThunkSection>(TOS, IS->OutSecOff);
- ThunkSections[TOS].push_back(TS);
- ThunkedSections[IS] = TS;
- return TS;
- };
- // Find or create a ThunkSection to be placed as last executable section in
- // OS.
- auto GetOSThunkSec = [&](ThunkSection *&TS, OutputSection *OS) {
- if (TS == nullptr) {
- uint32_t Off = 0;
- for (auto *IS : OS->Sections) {
- Off = IS->OutSecOff + IS->getSize();
- if ((IS->Flags & SHF_EXECINSTR) == 0)
- break;
- }
- TS = make<ThunkSection>(OS, Off);
- ThunkSections[OS].push_back(TS);
- }
- return TS;
- };
+bool ThunkCreator<ELFT>::createThunks(
+ ArrayRef<OutputSection *> OutputSections) {
// Create all the Thunks and insert them into synthetic ThunkSections. The
// ThunkSections are later inserted back into the OutputSection.
for (InputSection *IS : OS->Sections) {
for (Relocation &Rel : IS->Relocations) {
SymbolBody &Body = *Rel.Sym;
- if (Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) {
- Thunk *T;
- bool IsNew;
- std::tie(T, IsNew) = GetThunk(Body, Rel.Type);
- if (IsNew) {
- // Find or create a ThunkSection for the new Thunk
- ThunkSection *TS;
- if (auto *TIS = T->getTargetInputSection())
- TS = GetISThunkSec(TIS, OS);
- else
- TS = GetOSThunkSec(OSTS, OS);
- TS->addThunk(T);
- }
- // Redirect relocation to Thunk, we never go via the PLT to a Thunk
- Rel.Sym = T->ThunkSym;
- Rel.Expr = fromPlt(Rel.Expr);
+ if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
+ continue;
+ Thunk *T;
+ bool IsNew;
+ std::tie(T, IsNew) = getThunk(Body, Rel.Type);
+ if (IsNew) {
+ // Find or create a ThunkSection for the new Thunk
+ ThunkSection *TS;
+ if (auto *TIS = T->getTargetInputSection())
+ TS = getISThunkSec(TIS, OS);
+ else
+ TS = getOSThunkSec(OSTS, OS);
+ TS->addThunk(T);
}
+ // Redirect relocation to Thunk, we never go via the PLT to a Thunk
+ Rel.Sym = T->ThunkSym;
+ Rel.Expr = fromPlt(Rel.Expr);
}
}
}
template void elf::scanRelocations<ELF64LE>(InputSectionBase &);
template void elf::scanRelocations<ELF64BE>(InputSectionBase &);
-template bool elf::createThunks<ELF32LE>(ArrayRef<OutputSection *>);
-template bool elf::createThunks<ELF32BE>(ArrayRef<OutputSection *>);
-template bool elf::createThunks<ELF64LE>(ArrayRef<OutputSection *>);
-template bool elf::createThunks<ELF64BE>(ArrayRef<OutputSection *>);
+template class elf::ThunkCreator<ELF32LE>;
+template class elf::ThunkCreator<ELF32BE>;
+template class elf::ThunkCreator<ELF64LE>;
+template class elf::ThunkCreator<ELF64BE>;
#define LLD_ELF_RELOCATIONS_H
#include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include <map>
+#include <vector>
namespace lld {
namespace elf {
template <class ELFT> void scanRelocations(InputSectionBase &);
-template <class ELFT>
-bool createThunks(ArrayRef<OutputSection *> OutputSections);
+class ThunkSection;
+class Thunk;
+
+template <class ELFT> class ThunkCreator {
+public:
+ // Return true if Thunks have been added to OutputSections
+ bool createThunks(ArrayRef<OutputSection *> OutputSections);
+
+private:
+ void mergeThunks(OutputSection *OS, std::vector<ThunkSection *> &Thunks);
+ ThunkSection *getOSThunkSec(ThunkSection *&TS, OutputSection *OS);
+ ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
+ std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
+
+ // Track Symbols that already have a Thunk
+ llvm::DenseMap<SymbolBody *, Thunk *> ThunkedSymbols;
+
+ // Track InputSections that have a ThunkSection placed in front
+ llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections;
+
+ // Track the ThunksSections that need to be inserted into an OutputSection
+ std::map<OutputSection *, std::vector<ThunkSection *>> ThunkSections;
+};
// Return a int64_t to make sure we get the sign extension out of the way as
// early as possible.