summaryrefslogtreecommitdiff
path: root/gnu/llvm/lld
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2023-04-23 21:08:27 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2023-04-23 21:08:27 +0000
commit0d4c5be083434537a6fba3bcbad80673fb85ec57 (patch)
treeb098d14248860905ed4cd1426a9a2fb7c5f06f1e /gnu/llvm/lld
parentfbf64b8131cae6397926dada5f0e48c9442c92b6 (diff)
Don't create IBT .plt if there are no PLT entries. Cherry picked from
upstream. Fixes several issues including problems with ld.bfd when it sees such a .plt in an object file that is getting linked into a binary. ok deraadt@
Diffstat (limited to 'gnu/llvm/lld')
-rw-r--r--gnu/llvm/lld/ELF/SyntheticSections.cpp2
-rw-r--r--gnu/llvm/lld/ELF/SyntheticSections.h136
2 files changed, 100 insertions, 38 deletions
diff --git a/gnu/llvm/lld/ELF/SyntheticSections.cpp b/gnu/llvm/lld/ELF/SyntheticSections.cpp
index 187b2ac90c2..32248aac70d 100644
--- a/gnu/llvm/lld/ELF/SyntheticSections.cpp
+++ b/gnu/llvm/lld/ELF/SyntheticSections.cpp
@@ -2729,6 +2729,8 @@ size_t IBTPltSection::getSize() const {
return 16 + in.plt->getNumEntries() * target->pltEntrySize;
}
+bool IBTPltSection::isNeeded() const { return in.plt->getNumEntries() > 0; }
+
// The string hash function for .gdb_index.
static uint32_t computeGdbHash(StringRef s) {
uint32_t h = 0;
diff --git a/gnu/llvm/lld/ELF/SyntheticSections.h b/gnu/llvm/lld/ELF/SyntheticSections.h
index 5f59178fb54..bc79fcdd49f 100644
--- a/gnu/llvm/lld/ELF/SyntheticSections.h
+++ b/gnu/llvm/lld/ELF/SyntheticSections.h
@@ -23,6 +23,7 @@
#include "DWARF.h"
#include "EhFrame.h"
#include "InputSection.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/Endian.h"
@@ -88,6 +89,8 @@ public:
std::vector<FdeData> getFdeData() const;
ArrayRef<CieRecord *> getCieRecords() const { return cieRecords; }
+ template <class ELFT>
+ void iterateFDEWithLSDA(llvm::function_ref<void(InputSection &)> fn);
private:
// This is used only when parsing EhInputSection. We keep it here to avoid
@@ -98,14 +101,17 @@ private:
template <class ELFT, class RelTy>
void addRecords(EhInputSection *s, llvm::ArrayRef<RelTy> rels);
- template <class ELFT>
- void addSectionAux(EhInputSection *s);
+ template <class ELFT> void addSectionAux(EhInputSection *s);
+ template <class ELFT, class RelTy>
+ void iterateFDEWithLSDAAux(EhInputSection &sec, ArrayRef<RelTy> rels,
+ llvm::DenseSet<size_t> &ciesWithLSDA,
+ llvm::function_ref<void(InputSection &)> fn);
template <class ELFT, class RelTy>
CieRecord *addCie(EhSectionPiece &piece, ArrayRef<RelTy> rels);
template <class ELFT, class RelTy>
- bool isFdeLive(EhSectionPiece &piece, ArrayRef<RelTy> rels);
+ Defined *isFdeLive(EhSectionPiece &piece, ArrayRef<RelTy> rels);
uint64_t getFdePc(uint8_t *buf, size_t off, uint8_t enc) const;
@@ -364,7 +370,7 @@ private:
// Try to merge two GOTs. In case of success the `Dst` contains
// result of merging and the function returns true. In case of
- // ovwerflow the `Dst` is unchanged and the function returns false.
+ // overflow the `Dst` is unchanged and the function returns false.
bool tryMergeGots(FileGot & dst, FileGot & src, bool isPrimary);
};
@@ -419,48 +425,73 @@ private:
class DynamicReloc {
public:
+ enum Kind {
+ /// The resulting dynamic relocation does not reference a symbol (#sym must
+ /// be nullptr) and uses #addend as the result of computeAddend().
+ AddendOnly,
+ /// The resulting dynamic relocation will not reference a symbol: #sym is
+ /// only used to compute the addend with InputSection::getRelocTargetVA().
+ /// Useful for various relative and TLS relocations (e.g. R_X86_64_TPOFF64).
+ AddendOnlyWithTargetVA,
+ /// The resulting dynamic relocation references symbol #sym from the dynamic
+ /// symbol table and uses #addend as the value of computeAddend().
+ AgainstSymbol,
+ /// The resulting dynamic relocation references symbol #sym from the dynamic
+ /// symbol table and uses InputSection::getRelocTargetVA() + #addend for the
+ /// final addend. It can be used for relocations that write the symbol VA as
+ // the addend (e.g. R_MIPS_TLS_TPREL64) but still reference the symbol.
+ AgainstSymbolWithTargetVA,
+ /// This is used by the MIPS multi-GOT implementation. It relocates
+ /// addresses of 64kb pages that lie inside the output section.
+ MipsMultiGotPage,
+ };
+ /// This constructor records a relocation against a symbol.
DynamicReloc(RelType type, const InputSectionBase *inputSec,
- uint64_t offsetInSec, bool useSymVA, Symbol *sym, int64_t addend)
- : type(type), sym(sym), inputSec(inputSec), offsetInSec(offsetInSec),
- useSymVA(useSymVA), addend(addend), outputSec(nullptr) {}
- // This constructor records dynamic relocation settings used by MIPS
- // multi-GOT implementation. It's to relocate addresses of 64kb pages
- // lie inside the output section.
+ uint64_t offsetInSec, Kind kind, Symbol &sym, int64_t addend,
+ RelExpr expr)
+ : type(type), sym(&sym), inputSec(inputSec), offsetInSec(offsetInSec),
+ kind(kind), expr(expr), addend(addend) {}
+ /// This constructor records a relative relocation with no symbol.
+ DynamicReloc(RelType type, const InputSectionBase *inputSec,
+ uint64_t offsetInSec, int64_t addend = 0)
+ : type(type), sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec),
+ kind(AddendOnly), expr(R_ADDEND), addend(addend) {}
+ /// This constructor records dynamic relocation settings used by the MIPS
+ /// multi-GOT implementation.
DynamicReloc(RelType type, const InputSectionBase *inputSec,
uint64_t offsetInSec, const OutputSection *outputSec,
int64_t addend)
: type(type), sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec),
- useSymVA(false), addend(addend), outputSec(outputSec) {}
+ kind(MipsMultiGotPage), expr(R_ADDEND), addend(addend),
+ outputSec(outputSec) {}
uint64_t getOffset() const;
uint32_t getSymIndex(SymbolTableBaseSection *symTab) const;
+ bool needsDynSymIndex() const {
+ return kind == AgainstSymbol || kind == AgainstSymbolWithTargetVA;
+ }
- // Computes the addend of the dynamic relocation. Note that this is not the
- // same as the addend member variable as it also includes the symbol address
- // if useSymVA is true.
+ /// Computes the addend of the dynamic relocation. Note that this is not the
+ /// same as the #addend member variable as it may also include the symbol
+ /// address/the address of the corresponding GOT entry/etc.
int64_t computeAddend() const;
RelType type;
-
Symbol *sym;
- const InputSectionBase *inputSec = nullptr;
+ const InputSectionBase *inputSec;
uint64_t offsetInSec;
- // If this member is true, the dynamic relocation will not be against the
- // symbol but will instead be a relative relocation that simply adds the
- // load address. This means we need to write the symbol virtual address
- // plus the original addend as the final relocation addend.
- bool useSymVA;
+
+private:
+ Kind kind;
+ // The kind of expression used to calculate the added (required e.g. for
+ // relative GOT relocations).
+ RelExpr expr;
int64_t addend;
- const OutputSection *outputSec;
+ const OutputSection *outputSec = nullptr;
};
template <class ELFT> class DynamicSection final : public SyntheticSection {
- using Elf_Dyn = typename ELFT::Dyn;
- using Elf_Rel = typename ELFT::Rel;
- using Elf_Rela = typename ELFT::Rela;
- using Elf_Relr = typename ELFT::Relr;
- using Elf_Shdr = typename ELFT::Shdr;
- using Elf_Sym = typename ELFT::Sym;
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
// finalizeContents() fills this vector with the section contents.
std::vector<std::pair<int32_t, std::function<uint64_t()>>> entries;
@@ -487,18 +518,37 @@ class RelocationBaseSection : public SyntheticSection {
public:
RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag,
int32_t sizeDynamicTag);
- void addReloc(RelType dynType, InputSectionBase *isec, uint64_t offsetInSec,
- Symbol *sym);
- // Add a dynamic relocation that might need an addend. This takes care of
- // writing the addend to the output section if needed.
- void addReloc(RelType dynType, InputSectionBase *inputSec,
- uint64_t offsetInSec, Symbol *sym, int64_t addend, RelExpr expr,
- RelType type);
+ /// Add a dynamic relocation without writing an addend to the output section.
+ /// This overload can be used if the addends are written directly instead of
+ /// using relocations on the input section (e.g. MipsGotSection::writeTo()).
void addReloc(const DynamicReloc &reloc);
+ /// Add a dynamic relocation against \p sym with an optional addend.
+ void addSymbolReloc(RelType dynType, InputSectionBase *isec,
+ uint64_t offsetInSec, Symbol &sym, int64_t addend = 0,
+ llvm::Optional<RelType> addendRelType = llvm::None);
+ /// Add a relative dynamic relocation that uses the target address of \p sym
+ /// (i.e. InputSection::getRelocTargetVA()) + \p addend as the addend.
+ void addRelativeReloc(RelType dynType, InputSectionBase *isec,
+ uint64_t offsetInSec, Symbol &sym, int64_t addend,
+ RelType addendRelType, RelExpr expr);
+ /// Add a dynamic relocation using the target address of \p sym as the addend
+ /// if \p sym is non-preemptible. Otherwise add a relocation against \p sym.
+ void addAddendOnlyRelocIfNonPreemptible(RelType dynType,
+ InputSectionBase *isec,
+ uint64_t offsetInSec, Symbol &sym,
+ RelType addendRelType);
+ void addReloc(DynamicReloc::Kind kind, RelType dynType,
+ InputSectionBase *inputSec, uint64_t offsetInSec, Symbol &sym,
+ int64_t addend, RelExpr expr, RelType addendRelType);
bool isNeeded() const override { return !relocs.empty(); }
size_t getSize() const override { return relocs.size() * this->entsize; }
size_t getRelativeRelocCount() const { return numRelativeRelocs; }
void finalizeContents() override;
+ static bool classof(const SectionBase *d) {
+ return SyntheticSection::classof(d) &&
+ (d->type == llvm::ELF::SHT_RELA || d->type == llvm::ELF::SHT_REL ||
+ d->type == llvm::ELF::SHT_RELR);
+ }
int32_t dynamicTag, sizeDynamicTag;
std::vector<DynamicReloc> relocs;
@@ -684,7 +734,6 @@ public:
size_t getNumEntries() const { return entries.size(); }
size_t headerSize;
- size_t footerSize = 0;
std::vector<const Symbol *> entries;
};
@@ -705,11 +754,22 @@ public:
void addEntry(Symbol &sym);
};
+class PPC32GlinkSection : public PltSection {
+public:
+ PPC32GlinkSection();
+ void writeTo(uint8_t *buf) override;
+ size_t getSize() const override;
+
+ std::vector<const Symbol *> canonical_plts;
+ static constexpr size_t footerSize = 64;
+};
+
// This is x86-only.
class IBTPltSection : public SyntheticSection {
public:
IBTPltSection();
void writeTo(uint8_t *Buf) override;
+ bool isNeeded() const override;
size_t getSize() const override;
};
@@ -1037,7 +1097,7 @@ public:
std::vector<InputSection *> exidxSections;
private:
- size_t size;
+ size_t size = 0;
// Instead of storing pointers to the .ARM.exidx InputSections from
// InputObjects, we store pointers to the executable sections that need
@@ -1185,7 +1245,7 @@ inline Partition &SectionBase::getPartition() const {
// Linker generated sections which can be used as inputs and are not specific to
// a partition.
struct InStruct {
- InputSection *armAttributes;
+ InputSection *attributes;
BssSection *bss;
BssSection *bssRelRo;
GotSection *got;