diff options
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r-- | lld/ELF/InputSection.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index d26c7400563..b5448aca373 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -38,6 +38,13 @@ InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File, Align = std::max<uintX_t>(Header->sh_addralign, 1); } +template <class ELFT> size_t InputSectionBase<ELFT>::getSize() const { + if (auto *D = dyn_cast<InputSection<ELFT>>(this)) + if (D->getThunksSize() > 0) + return D->getThunkOff() + D->getThunksSize(); + return Header->sh_size; +} + template <class ELFT> StringRef InputSectionBase<ELFT>::getSectionName() const { return check(File->getObj().getSectionName(this->Header)); } @@ -105,6 +112,19 @@ InputSectionBase<ELFT> *InputSection<ELFT>::getRelocatedSection() { return Sections[this->Header->sh_info]; } +template <class ELFT> void InputSection<ELFT>::addThunk(SymbolBody &Body) { + Body.ThunkIndex = Thunks.size(); + Thunks.push_back(&Body); +} + +template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const { + return this->Header->sh_size; +} + +template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const { + return Thunks.size() * Target->ThunkSize; +} + // 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. @@ -293,6 +313,9 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd, // If that's the case, we leave the field alone rather than filling it // with a possibly incorrect value. continue; + } else if (Target->needsThunk(Type, *this->getFile(), Body)) { + // Get address of a thunk code related to the symbol. + SymVA = Body.getThunkVA<ELFT>(); } else if (Config->EMachine == EM_MIPS) { SymVA = adjustMipsSymVA<ELFT>(Type, *File, Body, AddrLoc, SymVA); } else if (!Target->needsCopyRel<ELFT>(Type, Body) && @@ -333,6 +356,19 @@ template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { else this->relocate(Buf, BufEnd, EObj.rels(RelSec)); } + + // 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 SymbolBody *S : Thunks) { + Target->writeThunk(Buf, S->getVA<ELFT>()); + Buf += Target->ThunkSize; + } + } } template <class ELFT> |