diff options
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r-- | lld/ELF/InputSection.cpp | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index f8115a6eb4a..7503767ada9 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -99,6 +99,10 @@ template <class ELFT> size_t InputSectionBase<ELFT>::getSize() const { if (auto *S = dyn_cast<SyntheticSection<ELFT>>(this)) return S->getSize(); + if (auto *D = dyn_cast<InputSection<ELFT>>(this)) + if (D->getThunksSize() > 0) + return D->getThunkOff() + D->getThunksSize(); + return Data.size(); } @@ -210,6 +214,21 @@ InputSectionBase<ELFT> *InputSection<ELFT>::getRelocatedSection() { return Sections[this->Info]; } +template <class ELFT> void InputSection<ELFT>::addThunk(const Thunk<ELFT> *T) { + Thunks.push_back(T); +} + +template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const { + return this->Data.size(); +} + +template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const { + uint64_t Total = 0; + for (const Thunk<ELFT> *T : Thunks) + Total += T->size(); + return Total; +} + // This is used for -r. We can't use memcpy to copy relocations because we need // to update symbol table offset and section index for each relocation. So we // copy relocations one by one. @@ -283,6 +302,11 @@ getRelocTargetVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, return In<ELFT>::Got->getTlsIndexOff() + A - In<ELFT>::Got->getSize(); case R_TLSLD_PC: return In<ELFT>::Got->getTlsIndexVA() + A - P; + case R_THUNK_ABS: + return Body.getThunkVA<ELFT>() + A; + case R_THUNK_PC: + case R_THUNK_PLT_PC: + return Body.getThunkVA<ELFT>() + A - P; case R_PPC_TOC: return getPPC64TocBase() + A; case R_TLSGD: @@ -527,6 +551,19 @@ template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { // Iterate over all relocation sections that apply to this section. uint8_t *BufEnd = Buf + OutSecOff + Data.size(); this->relocate(Buf, BufEnd); + + // The section might have a data/code generated by the linker and need + // to be written after the section. Usually these are thunks - small piece + // of code used to jump between "incompatible" functions like PIC and non-PIC + // or if the jump target too far and its address does not fit to the short + // jump istruction. + if (!Thunks.empty()) { + Buf += OutSecOff + getThunkOff(); + for (const Thunk<ELFT> *T : Thunks) { + T->writeTo(Buf); + Buf += T->size(); + } + } } template <class ELFT> |