Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -130,8 +130,9 @@ ThunkSection *getOSThunkSec(OutputSection *OS, InputSection *IS, uint32_t Type, uint64_t Src); ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS); - std::pair getThunk(SymbolBody &Body, uint32_t Type, + std::pair getThunk(SymbolBody *Body, uint32_t Type, uint64_t SrcAddr); + Thunk *getThunkAtSymbol(SymbolBody *Body); ThunkSection *addThunkSection(OutputSection *OS, uint64_t Off); uint32_t Pass = 0; Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -1050,11 +1050,11 @@ } template -std::pair ThunkCreator::getThunk(SymbolBody &Body, +std::pair ThunkCreator::getThunk(SymbolBody *Body, uint32_t Type, uint64_t SrcAddr) { Thunk *T = nullptr; - auto Res = ThunkedSymbols.insert({&Body, std::vector()}); + auto Res = ThunkedSymbols.insert({Body, std::vector()}); if (!Res.second) { // Check existing Thunks for Body to see if they can be reused for (Thunk *ET : Res.first->second) @@ -1065,11 +1065,21 @@ } } // No existing compatible Thunk in range, create a new one - T = addThunk(Type, Body); + T = addThunk(Type, *Body); Res.first->second.push_back(T); return std::make_pair(T, true); } +// Given a relocation to a symbol, check to see if that symbol is an existing +// Thunk and if it is return it. +template +Thunk *ThunkCreator::getThunkAtSymbol(SymbolBody *Sym) { + auto Res = Thunks.find(Sym); + if (Res != Thunks.end()) + return Res->second; + return nullptr; +} + // Make a new ThunkSection at offset Off and it to the persistent and per pass // records per OutputSection. template @@ -1113,14 +1123,24 @@ // Do not create Thunks for relocations from Thunks continue; for (Relocation &Rel : IS->Relocations) { - SymbolBody &Body = *Rel.Sym; uint64_t SrcAddr = OS->Addr + IS->OutSecOff + Rel.Offset; - if (Thunks.find(&Body) != Thunks.end() || - !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, SrcAddr, Body)) + + // If this Relocation is using a Thunk, use it if it hasn't gone out + // of range. If it has we revert back to the original Target. + if (Thunk *ET = getThunkAtSymbol(Rel.Sym)) { + if (Target->inBranchRange(Rel.Type, SrcAddr, Rel.Sym->getVA())) + continue; + Rel.Sym = &ET->Destination; + if (Rel.Sym->isInPlt()) + Rel.Expr = toPlt(Rel.Expr); + } + + if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, SrcAddr, + *Rel.Sym)) continue; Thunk *T; bool IsNew; - std::tie(T, IsNew) = getThunk(Body, Rel.Type, SrcAddr); + std::tie(T, IsNew) = getThunk(Rel.Sym, Rel.Type, SrcAddr); if (IsNew) { AddressesChanged = true; // Find or create a ThunkSection for the new Thunk Index: ELF/Thunks.h =================================================================== --- ELF/Thunks.h +++ ELF/Thunks.h @@ -27,7 +27,7 @@ // Thunks are assigned to synthetic ThunkSections class Thunk { public: - Thunk(const SymbolBody &Destination); + Thunk(SymbolBody &Destination); virtual ~Thunk(); virtual uint32_t size() const { return 0; } @@ -47,7 +47,7 @@ // The alignment requirement for this Thunk, defaults to the size of the // typical code section alignment. - const SymbolBody &Destination; + SymbolBody &Destination; SymbolBody *ThunkSym; uint64_t Offset; uint32_t alignment = 4; Index: ELF/Thunks.cpp =================================================================== --- ELF/Thunks.cpp +++ ELF/Thunks.cpp @@ -52,7 +52,7 @@ // Source State, TargetState, Target Requirement, ABS or PI, Range template class ARMV7ABSLongThunk final : public Thunk { public: - ARMV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) {} + ARMV7ABSLongThunk(SymbolBody &Dest) : Thunk(Dest) {} uint32_t size() const override { return 12; } void writeTo(uint8_t *Buf, ThunkSection &IS) const override; @@ -62,7 +62,7 @@ template class ARMV7PILongThunk final : public Thunk { public: - ARMV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) {} + ARMV7PILongThunk(SymbolBody &Dest) : Thunk(Dest) {} uint32_t size() const override { return 16; } void writeTo(uint8_t *Buf, ThunkSection &IS) const override; @@ -72,9 +72,7 @@ template class ThumbV7ABSLongThunk final : public Thunk { public: - ThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) { - this->alignment = 2; - } + ThumbV7ABSLongThunk(SymbolBody &Dest) : Thunk(Dest) { this->alignment = 2; } uint32_t size() const override { return 10; } void writeTo(uint8_t *Buf, ThunkSection &IS) const override; @@ -84,9 +82,7 @@ template class ThumbV7PILongThunk final : public Thunk { public: - ThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) { - this->alignment = 2; - } + ThumbV7PILongThunk(SymbolBody &Dest) : Thunk(Dest) { this->alignment = 2; } uint32_t size() const override { return 12; } void writeTo(uint8_t *Buf, ThunkSection &IS) const override; @@ -97,7 +93,7 @@ // MIPS LA25 thunk template class MipsThunk final : public Thunk { public: - MipsThunk(const SymbolBody &Dest) : Thunk(Dest) {} + MipsThunk(SymbolBody &Dest) : Thunk(Dest) {} uint32_t size() const override { return 16; } void writeTo(uint8_t *Buf, ThunkSection &IS) const override; @@ -253,7 +249,7 @@ return dyn_cast(DR->Section); } -Thunk::Thunk(const SymbolBody &D) : Destination(D), Offset(0) {} +Thunk::Thunk(SymbolBody &D) : Destination(D), Offset(0) {} Thunk::~Thunk() = default;