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.cpp36
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>
OpenPOWER on IntegriCloud