[ELF] Detemplate ThunkSection and Thunk classes. NFC.

llvm-svn: 297939
This commit is contained in:
George Rimar 2017-03-16 10:40:50 +00:00
parent 49a47f2a6d
commit 7b8270424e
5 changed files with 67 additions and 83 deletions

View File

@ -863,9 +863,9 @@ template <class ELFT> void scanRelocations(InputSectionBase &S) {
// This may invalidate any output section offsets stored outside of InputSection
template <class ELFT>
static void mergeThunks(OutputSection *OS,
std::vector<ThunkSection<ELFT> *> &Thunks) {
std::vector<ThunkSection *> &Thunks) {
// Order Thunks in ascending OutSecOff
auto ThunkCmp = [](const ThunkSection<ELFT> *A, const ThunkSection<ELFT> *B) {
auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) {
return A->OutSecOff < B->OutSecOff;
};
std::stable_sort(Thunks.begin(), Thunks.end(), ThunkCmp);
@ -880,7 +880,7 @@ static void mergeThunks(OutputSection *OS,
if (A->OutSecOff == B->OutSecOff)
// Check if Thunk is immediately before any specific Target InputSection
// for example Mips LA25 Thunks.
if (auto *TA = dyn_cast<ThunkSection<ELFT>>(A))
if (auto *TA = dyn_cast<ThunkSection>(A))
if (TA && TA->getTargetInputSection() == B)
return true;
return false;
@ -904,11 +904,11 @@ static void mergeThunks(OutputSection *OS,
template <class ELFT>
bool createThunks(ArrayRef<OutputSection *> OutputSections) {
// Track Symbols that already have a Thunk
DenseMap<SymbolBody *, Thunk<ELFT> *> ThunkedSymbols;
DenseMap<SymbolBody *, Thunk *> ThunkedSymbols;
// Track InputSections that have a ThunkSection placed in front
DenseMap<InputSection *, ThunkSection<ELFT> *> ThunkedSections;
DenseMap<InputSection *, ThunkSection *> ThunkedSections;
// Track the ThunksSections that need to be inserted into an OutputSection
std::map<OutputSection *, std::vector<ThunkSection<ELFT> *>> ThunkSections;
std::map<OutputSection *, std::vector<ThunkSection *>> ThunkSections;
// Find or create a Thunk for Body for relocation Type
auto GetThunk = [&](SymbolBody &Body, uint32_t Type) {
@ -920,18 +920,18 @@ bool createThunks(ArrayRef<OutputSection *> OutputSections) {
// Find or create a ThunkSection to be placed immediately before IS
auto GetISThunkSec = [&](InputSection *IS, OutputSection *OS) {
ThunkSection<ELFT> *TS = ThunkedSections.lookup(IS);
ThunkSection *TS = ThunkedSections.lookup(IS);
if (TS)
return TS;
auto *TOS = cast<OutputSection>(IS->OutSec);
TS = make<ThunkSection<ELFT>>(TOS, IS->OutSecOff);
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<ELFT> *&TS, OutputSection *OS) {
auto GetOSThunkSec = [&](ThunkSection *&TS, OutputSection *OS) {
if (TS == nullptr) {
uint32_t Off = 0;
for (auto *IS : OS->Sections) {
@ -939,7 +939,7 @@ bool createThunks(ArrayRef<OutputSection *> OutputSections) {
if ((IS->Flags & SHF_EXECINSTR) == 0)
break;
}
TS = make<ThunkSection<ELFT>>(OS, Off);
TS = make<ThunkSection>(OS, Off);
ThunkSections[OS].push_back(TS);
}
return TS;
@ -955,18 +955,18 @@ bool createThunks(ArrayRef<OutputSection *> OutputSections) {
if (OS == nullptr)
continue;
ThunkSection<ELFT> *OSTS = nullptr;
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->template getFile<ELFT>(),
Body)) {
Thunk<ELFT> *T;
Thunk *T;
bool IsNew;
std::tie(T, IsNew) = GetThunk(Body, Rel.Type);
if (IsNew) {
// Find or create a ThunkSection for the new Thunk
ThunkSection<ELFT> *TS;
ThunkSection *TS;
if (auto *TIS = T->getTargetInputSection())
TS = GetISThunkSec(TIS, OS);
else

View File

@ -2234,15 +2234,14 @@ void ARMExidxSentinelSection<ELFT>::writeTo(uint8_t *Buf) {
write32le(Buf + 4, 0x1);
}
template <class ELFT>
ThunkSection<ELFT>::ThunkSection(OutputSection *OS, uint64_t Off)
ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
sizeof(typename ELFT::uint), ".text.thunk") {
Config->is64Bit() ? 8 : 4, ".text.thunk") {
this->OutSec = OS;
this->OutSecOff = Off;
}
template <class ELFT> void ThunkSection<ELFT>::addThunk(Thunk<ELFT> *T) {
void ThunkSection::addThunk(Thunk *T) {
uint64_t Off = alignTo(Size, T->alignment);
T->Offset = Off;
Thunks.push_back(T);
@ -2250,14 +2249,13 @@ template <class ELFT> void ThunkSection<ELFT>::addThunk(Thunk<ELFT> *T) {
Size = Off + T->size();
}
template <class ELFT> void ThunkSection<ELFT>::writeTo(uint8_t *Buf) {
for (const Thunk<ELFT> *T : Thunks)
void ThunkSection::writeTo(uint8_t *Buf) {
for (const Thunk *T : Thunks)
T->writeTo(Buf + T->Offset, *this);
}
template <class ELFT>
InputSection *ThunkSection<ELFT>::getTargetInputSection() const {
const Thunk<ELFT> *T = Thunks.front();
InputSection *ThunkSection::getTargetInputSection() const {
const Thunk *T = Thunks.front();
return T->getTargetInputSection();
}
@ -2389,11 +2387,6 @@ template class elf::ARMExidxSentinelSection<ELF32BE>;
template class elf::ARMExidxSentinelSection<ELF64LE>;
template class elf::ARMExidxSentinelSection<ELF64BE>;
template class elf::ThunkSection<ELF32LE>;
template class elf::ThunkSection<ELF32BE>;
template class elf::ThunkSection<ELF64LE>;
template class elf::ThunkSection<ELF64BE>;
template class elf::EhFrameSection<ELF32LE>;
template class elf::EhFrameSection<ELF32BE>;
template class elf::EhFrameSection<ELF64LE>;

View File

@ -727,7 +727,7 @@ public:
// A container for one or more linker generated thunks. Instances of these
// thunks including ARM interworking and Mips LA25 PI to non-PI thunks.
template <class ELFT> class ThunkSection : public SyntheticSection {
class ThunkSection : public SyntheticSection {
public:
// ThunkSection in OS, with desired OutSecOff of Off
ThunkSection(OutputSection *OS, uint64_t Off);
@ -736,13 +736,13 @@ public:
// Thunk is given offset from start of this InputSection
// Thunk defines a symbol in this InputSection that can be used as target
// of a relocation
void addThunk(Thunk<ELFT> *T);
void addThunk(Thunk *T);
size_t getSize() const override { return Size; }
void writeTo(uint8_t *Buf) override;
InputSection *getTargetInputSection() const;
private:
std::vector<const Thunk<ELFT> *> Thunks;
std::vector<const Thunk *> Thunks;
size_t Size = 0;
};

View File

@ -50,56 +50,54 @@ namespace {
// Specific ARM Thunk implementations. The naming convention is:
// Source State, TargetState, Target Requirement, ABS or PI, Range
template <class ELFT>
class ARMToThumbV7ABSLongThunk final : public Thunk<ELFT> {
template <class ELFT> class ARMToThumbV7ABSLongThunk final : public Thunk {
public:
ARMToThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {}
ARMToThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) {}
uint32_t size() const override { return 12; }
void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
void addSymbols(ThunkSection<ELFT> &IS) override;
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
void addSymbols(ThunkSection &IS) override;
};
template <class ELFT> class ARMToThumbV7PILongThunk final : public Thunk<ELFT> {
template <class ELFT> class ARMToThumbV7PILongThunk final : public Thunk {
public:
ARMToThumbV7PILongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {}
ARMToThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) {}
uint32_t size() const override { return 16; }
void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
void addSymbols(ThunkSection<ELFT> &IS) override;
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
void addSymbols(ThunkSection &IS) override;
};
template <class ELFT>
class ThumbToARMV7ABSLongThunk final : public Thunk<ELFT> {
template <class ELFT> class ThumbToARMV7ABSLongThunk final : public Thunk {
public:
ThumbToARMV7ABSLongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {
ThumbToARMV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) {
this->alignment = 2;
}
uint32_t size() const override { return 10; }
void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
void addSymbols(ThunkSection<ELFT> &IS) override;
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
void addSymbols(ThunkSection &IS) override;
};
template <class ELFT> class ThumbToARMV7PILongThunk final : public Thunk<ELFT> {
template <class ELFT> class ThumbToARMV7PILongThunk final : public Thunk {
public:
ThumbToARMV7PILongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {
ThumbToARMV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) {
this->alignment = 2;
}
uint32_t size() const override { return 12; }
void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
void addSymbols(ThunkSection<ELFT> &IS) override;
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
void addSymbols(ThunkSection &IS) override;
};
// MIPS LA25 thunk
template <class ELFT> class MipsThunk final : public Thunk<ELFT> {
template <class ELFT> class MipsThunk final : public Thunk {
public:
MipsThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {}
MipsThunk(const SymbolBody &Dest) : Thunk(Dest) {}
uint32_t size() const override { return 16; }
void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
void addSymbols(ThunkSection<ELFT> &IS) override;
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
void addSymbols(ThunkSection &IS) override;
InputSection *getTargetInputSection() const override;
};
@ -113,7 +111,7 @@ template <class ELFT> static uint64_t getARMThunkDestVA(const SymbolBody &S) {
template <class ELFT>
void ARMToThumbV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf,
ThunkSection<ELFT> &IS) const {
ThunkSection &IS) const {
const uint8_t Data[] = {
0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S
0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S
@ -126,7 +124,7 @@ void ARMToThumbV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf,
}
template <class ELFT>
void ARMToThumbV7ABSLongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
void ARMToThumbV7ABSLongThunk<ELFT>::addSymbols(ThunkSection &IS) {
this->ThunkSym = addSyntheticLocal<ELFT>(
Saver.save("__ARMToThumbv7ABSLongThunk_" + this->Destination.getName()),
STT_FUNC, this->Offset, size(), &IS);
@ -135,7 +133,7 @@ void ARMToThumbV7ABSLongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
template <class ELFT>
void ThumbToARMV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf,
ThunkSection<ELFT> &IS) const {
ThunkSection &IS) const {
const uint8_t Data[] = {
0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S
@ -148,7 +146,7 @@ void ThumbToARMV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf,
}
template <class ELFT>
void ThumbToARMV7ABSLongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
void ThumbToARMV7ABSLongThunk<ELFT>::addSymbols(ThunkSection &IS) {
this->ThunkSym = addSyntheticLocal<ELFT>(
Saver.save("__ThumbToARMv7ABSLongThunk_" + this->Destination.getName()),
STT_FUNC, this->Offset, size(), &IS);
@ -157,7 +155,7 @@ void ThumbToARMV7ABSLongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
template <class ELFT>
void ARMToThumbV7PILongThunk<ELFT>::writeTo(uint8_t *Buf,
ThunkSection<ELFT> &IS) const {
ThunkSection &IS) const {
const uint8_t Data[] = {
0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) +8)
0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P+4) +8)
@ -172,7 +170,7 @@ void ARMToThumbV7PILongThunk<ELFT>::writeTo(uint8_t *Buf,
}
template <class ELFT>
void ARMToThumbV7PILongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
void ARMToThumbV7PILongThunk<ELFT>::addSymbols(ThunkSection &IS) {
this->ThunkSym = addSyntheticLocal<ELFT>(
Saver.save("__ARMToThumbV7PILongThunk_" + this->Destination.getName()),
STT_FUNC, this->Offset, size(), &IS);
@ -181,7 +179,7 @@ void ARMToThumbV7PILongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
template <class ELFT>
void ThumbToARMV7PILongThunk<ELFT>::writeTo(uint8_t *Buf,
ThunkSection<ELFT> &IS) const {
ThunkSection &IS) const {
const uint8_t Data[] = {
0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P+4) + 4)
@ -196,7 +194,7 @@ void ThumbToARMV7PILongThunk<ELFT>::writeTo(uint8_t *Buf,
}
template <class ELFT>
void ThumbToARMV7PILongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
void ThumbToARMV7PILongThunk<ELFT>::addSymbols(ThunkSection &IS) {
this->ThunkSym = addSyntheticLocal<ELFT>(
Saver.save("__ThumbToARMV7PILongThunk_" + this->Destination.getName()),
STT_FUNC, this->Offset, size(), &IS);
@ -205,7 +203,7 @@ void ThumbToARMV7PILongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
template <class ELFT>
void MipsThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection<ELFT> &) const {
void MipsThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection &) const {
const endianness E = ELFT::TargetEndianness;
uint64_t S = this->Destination.template getVA<ELFT>();
@ -217,7 +215,7 @@ void MipsThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection<ELFT> &) const {
Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
}
template <class ELFT> void MipsThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
template <class ELFT> void MipsThunk<ELFT>::addSymbols(ThunkSection &IS) {
this->ThunkSym = addSyntheticLocal<ELFT>(
Saver.save("__LA25Thunk_" + this->Destination.getName()), STT_FUNC,
this->Offset, size(), &IS);
@ -229,14 +227,13 @@ InputSection *MipsThunk<ELFT>::getTargetInputSection() const {
return dyn_cast<InputSection>(DR->Section);
}
template <class ELFT>
Thunk<ELFT>::Thunk(const SymbolBody &D) : Destination(D), Offset(0) {}
Thunk::Thunk(const SymbolBody &D) : Destination(D), Offset(0) {}
template <class ELFT> Thunk<ELFT>::~Thunk() = default;
Thunk::~Thunk() = default;
// Creates a thunk for Thumb-ARM interworking.
template <class ELFT>
static Thunk<ELFT> *addThunkArm(uint32_t Reloc, SymbolBody &S) {
static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) {
// ARM relocations need ARM to Thumb interworking Thunks.
// Thumb relocations need Thumb to ARM relocations.
// Use position independent Thunks if we require position independent code.
@ -256,11 +253,11 @@ static Thunk<ELFT> *addThunkArm(uint32_t Reloc, SymbolBody &S) {
fatal("unrecognized relocation type");
}
template <class ELFT> static Thunk<ELFT> *addThunkMips(SymbolBody &S) {
template <class ELFT> static Thunk *addThunkMips(SymbolBody &S) {
return make<MipsThunk<ELFT>>(S);
}
template <class ELFT> Thunk<ELFT> *addThunk(uint32_t RelocType, SymbolBody &S) {
template <class ELFT> Thunk *addThunk(uint32_t RelocType, SymbolBody &S) {
if (Config->EMachine == EM_ARM)
return addThunkArm<ELFT>(RelocType, S);
else if (Config->EMachine == EM_MIPS)
@ -269,15 +266,9 @@ template <class ELFT> Thunk<ELFT> *addThunk(uint32_t RelocType, SymbolBody &S) {
return nullptr;
}
template Thunk<ELF32LE> *addThunk<ELF32LE>(uint32_t, SymbolBody &);
template Thunk<ELF32BE> *addThunk<ELF32BE>(uint32_t, SymbolBody &);
template Thunk<ELF64LE> *addThunk<ELF64LE>(uint32_t, SymbolBody &);
template Thunk<ELF64BE> *addThunk<ELF64BE>(uint32_t, SymbolBody &);
template class Thunk<ELF32LE>;
template class Thunk<ELF32BE>;
template class Thunk<ELF64LE>;
template class Thunk<ELF64BE>;
template Thunk *addThunk<ELF32LE>(uint32_t, SymbolBody &);
template Thunk *addThunk<ELF32BE>(uint32_t, SymbolBody &);
template Thunk *addThunk<ELF64LE>(uint32_t, SymbolBody &);
template Thunk *addThunk<ELF64BE>(uint32_t, SymbolBody &);
} // end namespace elf
} // end namespace lld

View File

@ -15,7 +15,7 @@
namespace lld {
namespace elf {
class SymbolBody;
template <class ELFT> class ThunkSection;
class ThunkSection;
// Class to describe an instance of a Thunk.
// A Thunk is a code-sequence inserted by the linker in between a caller and
// the callee. The relocation to the callee is redirected to the Thunk, which
@ -25,17 +25,17 @@ template <class ELFT> class ThunkSection;
//
// Thunks can be created for DefinedRegular, Shared and Undefined Symbols.
// Thunks are assigned to synthetic ThunkSections
template <class ELFT> class Thunk {
class Thunk {
public:
Thunk(const SymbolBody &Destination);
virtual ~Thunk();
virtual uint32_t size() const { return 0; }
virtual void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const {}
virtual void writeTo(uint8_t *Buf, ThunkSection &IS) const {}
// All Thunks must define at least one symbol ThunkSym so that we can
// redirect relocations to it.
virtual void addSymbols(ThunkSection<ELFT> &IS) {}
virtual void addSymbols(ThunkSection &IS) {}
// Some Thunks must be placed immediately before their Target as they elide
// a branch and fall through to the first Symbol in the Target.
@ -51,7 +51,7 @@ public:
// For a Relocation to symbol S create a Thunk to be added to a synthetic
// ThunkSection. At present there are implementations for ARM and Mips Thunks.
template <class ELFT> Thunk<ELFT> *addThunk(uint32_t RelocType, SymbolBody &S);
template <class ELFT> Thunk *addThunk(uint32_t RelocType, SymbolBody &S);
} // namespace elf
} // namespace lld