summaryrefslogtreecommitdiffstats
path: root/lld/ELF/SyntheticSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/SyntheticSections.cpp')
-rw-r--r--lld/ELF/SyntheticSections.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2ceec55e84e..97fd8395f85 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3070,6 +3070,53 @@ bool ThunkSection::assignOffsets() {
return Changed;
}
+// If linking position-dependent code then the table will store the addresses
+// directly in the binary so the section has type SHT_PROGBITS. If linking
+// position-independent code the section has type SHT_NOBITS since it will be
+// allocated and filled in by the dynamic linker.
+PPC64LongBranchTargetSection::PPC64LongBranchTargetSection()
+ : SyntheticSection(SHF_ALLOC | SHF_WRITE,
+ Config->Pic ? SHT_NOBITS : SHT_PROGBITS, 8,
+ ".branch_lt") {}
+
+void PPC64LongBranchTargetSection::addEntry(Symbol &Sym) {
+ assert(Sym.PPC64BranchltIndex == 0xffff);
+ Sym.PPC64BranchltIndex = Entries.size();
+ Entries.push_back(&Sym);
+}
+
+size_t PPC64LongBranchTargetSection::getSize() const {
+ return Entries.size() * 8;
+}
+
+void PPC64LongBranchTargetSection::writeTo(uint8_t *Buf) {
+ assert(Target->GotPltEntrySize == 8);
+ // If linking non-pic we have the final addresses of the targets and they get
+ // written to the table directly. For pic the dynamic linker will allocate
+ // the section and fill it it.
+ if (Config->Pic)
+ return;
+
+ for (const Symbol *Sym : Entries) {
+ assert(Sym->getVA());
+ // Need calls to branch to the local entry-point since a long-branch
+ // must be a local-call.
+ write64(Buf,
+ Sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(Sym->StOther));
+ Buf += Target->GotPltEntrySize;
+ }
+}
+
+bool PPC64LongBranchTargetSection::empty() const {
+ // `removeUnusedSyntheticSections()` is called before thunk allocation which
+ // is too early to determine if this section will be empty or not. We need
+ // Finalized to keep the section alive until after thunk creation. Finalized
+ // only gets set to true once `finalizeSections()` is called after thunk
+ // creation. Becuase of this, if we don't create any long-branch thunks we end
+ // up with an empty .branch_lt section in the binary.
+ return Finalized && Entries.empty();
+}
+
InStruct elf::In;
template GdbIndexSection *GdbIndexSection::create<ELF32LE>();
OpenPOWER on IntegriCloud