diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2023-04-23 21:08:27 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2023-04-23 21:08:27 +0000 |
commit | 0d4c5be083434537a6fba3bcbad80673fb85ec57 (patch) | |
tree | b098d14248860905ed4cd1426a9a2fb7c5f06f1e /gnu/llvm/lld | |
parent | fbf64b8131cae6397926dada5f0e48c9442c92b6 (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.cpp | 2 | ||||
-rw-r--r-- | gnu/llvm/lld/ELF/SyntheticSections.h | 136 |
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; |