Newer
Older
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;
}
ThunkSection *ThunkCreator::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;
}
std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
uint32_t Type) {
auto res = ThunkedSymbols.insert({&Body, nullptr});
if (res.second)
res.first->second = addThunk(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.
//
// createThunks must be called after scanRelocs has created the Relocations for
// each InputSection. It must be called before the static symbol table is
// finalized. If any Thunks are added to an OutputSection the output section
// offsets of the InputSections will change.
//
// FIXME: All Thunks are assumed to be in range of the relocation. Range
// extension Thunks are not yet supported.
bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
// Create all the Thunks and insert them into synthetic ThunkSections. The
// ThunkSections are later inserted back into the OutputSection.
// We separate the creation of ThunkSections from the insertion of the
// ThunkSections back into the OutputSection as ThunkSections are not always
// inserted into the same OutputSection as the caller.
for (OutputSection *OS : OutputSections) {
ThunkSection *OSTS = nullptr;
for (InputSection *IS : OS->Sections) {
for (Relocation &Rel : IS->Relocations) {
SymbolBody &Body = *Rel.Sym;
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);
// Merge all created synthetic ThunkSections back into OutputSection
for (auto &KV : ThunkSections)
mergeThunks(KV.first, KV.second);
return !ThunkSections.empty();
template void elf::scanRelocations<ELF32LE>(InputSectionBase &);
template void elf::scanRelocations<ELF32BE>(InputSectionBase &);
template void elf::scanRelocations<ELF64LE>(InputSectionBase &);
template void elf::scanRelocations<ELF64BE>(InputSectionBase &);