summaryrefslogtreecommitdiffstats
path: root/lld/ELF/InputSection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r--lld/ELF/InputSection.cpp37
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>
OpenPOWER on IntegriCloud