https://github.com/llvmbot updated https://github.com/llvm/llvm-project/pull/101844
>From f27537a5d033642347a8a45a7d6265dd9f94ccea Mon Sep 17 00:00:00 2001 From: Fangrui Song <i...@maskray.me> Date: Sun, 28 Jul 2024 15:32:22 -0700 Subject: [PATCH 1/4] [ELF] Move TarWriter into Ctx. NFC Similar to e980f16d52196fb2bc672ecb87e0f622253addec. (cherry picked from commit fd791f0fe562a41d8569fcb4d1e84b4c1e5719c7) --- lld/ELF/Config.h | 4 ++++ lld/ELF/Driver.cpp | 13 +++++++------ lld/ELF/InputFiles.cpp | 7 ++----- lld/ELF/InputFiles.h | 3 --- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 0173be396163e..2f6758743c0d6 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -27,6 +27,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/GlobPattern.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/TarWriter.h" #include <atomic> #include <memory> #include <optional> @@ -489,6 +490,9 @@ struct Ctx { std::pair<const InputFile *, const InputFile *>> backwardReferences; llvm::SmallSet<llvm::StringRef, 0> auxiliaryFiles; + // If --reproduce is specified, all input files are written to this tar + // archive. + std::unique_ptr<llvm::TarWriter> tar; // InputFile for linker created symbols with no source location. InputFile *internalFile; // True if SHT_LLVM_SYMPART is used. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 40e095a133d95..810d9b0377adf 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -106,6 +106,7 @@ void Ctx::reset() { whyExtractRecords.clear(); backwardReferences.clear(); auxiliaryFiles.clear(); + tar.reset(); internalFile = nullptr; hasSympart.store(false, std::memory_order_relaxed); hasTlsIe.store(false, std::memory_order_relaxed); @@ -138,7 +139,6 @@ bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS, outputSections.clear(); symAux.clear(); - tar = nullptr; in.reset(); partitions.clear(); @@ -224,14 +224,15 @@ std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers( std::vector<std::pair<MemoryBufferRef, uint64_t>> v; Error err = Error::success(); - bool addToTar = file->isThin() && tar; + bool addToTar = file->isThin() && ctx.tar; for (const Archive::Child &c : file->children(err)) { MemoryBufferRef mbref = CHECK(c.getMemoryBufferRef(), mb.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); if (addToTar) - tar->append(relativeToRoot(check(c.getFullName())), mbref.getBuffer()); + ctx.tar->append(relativeToRoot(check(c.getFullName())), + mbref.getBuffer()); v.push_back(std::make_pair(mbref, c.getChildOffset())); } if (err) @@ -640,9 +641,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { Expected<std::unique_ptr<TarWriter>> errOrWriter = TarWriter::create(path, path::stem(path)); if (errOrWriter) { - tar = std::move(*errOrWriter); - tar->append("response.txt", createResponseFile(args)); - tar->append("version.txt", getLLDVersion() + "\n"); + ctx.tar = std::move(*errOrWriter); + ctx.tar->append("response.txt", createResponseFile(args)); + ctx.tar->append("version.txt", getLLDVersion() + "\n"); StringRef ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile); if (!ltoSampleProfile.empty()) readFile(ltoSampleProfile); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index f1c0eb292361b..0e4ba06e9b780 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -28,7 +28,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/RISCVAttributeParser.h" -#include "llvm/Support/TarWriter.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include <optional> @@ -52,8 +51,6 @@ extern template void ObjFile<ELF64BE>::importCmseSymbols(); bool InputFile::isInGroup; uint32_t InputFile::nextGroupId; -std::unique_ptr<TarWriter> elf::tar; - // Returns "<internal>", "foo.a(bar.o)" or "baz.o". std::string lld::toString(const InputFile *f) { static std::mutex mu; @@ -261,8 +258,8 @@ std::optional<MemoryBufferRef> elf::readFile(StringRef path) { MemoryBufferRef mbref = (*mbOrErr)->getMemBufferRef(); ctx.memoryBuffers.push_back(std::move(*mbOrErr)); // take MB ownership - if (tar) - tar->append(relativeToRoot(path), mbref.getBuffer()); + if (ctx.tar) + ctx.tar->append(relativeToRoot(path), mbref.getBuffer()); return mbref; } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 8566baf61e1ab..b0a74877d0aae 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -39,9 +39,6 @@ namespace elf { class InputSection; class Symbol; -// If --reproduce is specified, all input files are written to this tar archive. -extern std::unique_ptr<llvm::TarWriter> tar; - // Opens a given file. std::optional<MemoryBufferRef> readFile(StringRef path); >From 34e70988a0aa5ec336126a0d141c058e833e7792 Mon Sep 17 00:00:00 2001 From: Fangrui Song <i...@maskray.me> Date: Sun, 28 Jul 2024 20:51:33 -0700 Subject: [PATCH 2/4] [ELF] Move SymbolAux into Ctx. NFC The number of uses is modest. (cherry picked from commit 8e2476e102e8ce3ae496b293bacccb248787404d) --- lld/ELF/Config.h | 11 +++++++++++ lld/ELF/Driver.cpp | 5 +++-- lld/ELF/Relocations.cpp | 4 ++-- lld/ELF/Symbols.cpp | 1 - lld/ELF/Symbols.h | 27 ++++++++------------------- lld/ELF/SyntheticSections.cpp | 30 +++++++++++++++--------------- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 2f6758743c0d6..6abd929d2343d 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -459,6 +459,15 @@ struct ConfigWrapper { LLVM_LIBRARY_VISIBILITY extern ConfigWrapper config; +// Some index properties of a symbol are stored separately in this auxiliary +// struct to decrease sizeof(SymbolUnion) in the majority of cases. +struct SymbolAux { + uint32_t gotIdx = -1; + uint32_t pltIdx = -1; + uint32_t tlsDescIdx = -1; + uint32_t tlsGdIdx = -1; +}; + struct DuplicateSymbol { const Symbol *sym; const InputFile *file; @@ -476,6 +485,8 @@ struct Ctx { SmallVector<BitcodeFile *, 0> lazyBitcodeFiles; SmallVector<InputSectionBase *, 0> inputSections; SmallVector<EhInputSection *, 0> ehInputSections; + + SmallVector<SymbolAux, 0> symAux; // Duplicate symbol candidates. SmallVector<DuplicateSymbol, 0> duplicates; // Symbols in a non-prevailing COMDAT group which should be changed to an diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 810d9b0377adf..8f6ca2a98484d 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -101,6 +101,8 @@ void Ctx::reset() { lazyBitcodeFiles.clear(); inputSections.clear(); ehInputSections.clear(); + + symAux.clear(); duplicates.clear(); nonPrevailingSyms.clear(); whyExtractRecords.clear(); @@ -137,7 +139,6 @@ bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS, symtab = SymbolTable(); outputSections.clear(); - symAux.clear(); in.reset(); @@ -153,7 +154,7 @@ bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS, config = ConfigWrapper(); script = ScriptWrapper(); - symAux.emplace_back(); + elf::ctx.symAux.emplace_back(); partitions.clear(); partitions.emplace_back(); diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index e19b1e6c8efb8..1c0dd97ed3910 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1728,7 +1728,7 @@ static bool handleNonPreemptibleIfunc(Symbol &sym, uint16_t flags) { auto &dyn = config->androidPackDynRelocs ? *in.relaPlt : *mainPart->relaDyn; addPltEntry(*in.iplt, *in.igotPlt, dyn, target->iRelativeRel, *directSym); sym.allocateAux(); - symAux.back().pltIdx = symAux[directSym->auxIdx].pltIdx; + ctx.symAux.back().pltIdx = ctx.symAux[directSym->auxIdx].pltIdx; if (flags & HAS_DIRECT_RELOC) { // Change the value to the IPLT and redirect all references to it. @@ -1846,7 +1846,7 @@ void elf::postScanRelocations() { {R_ADDEND, target->symbolicRel, got->getTlsIndexOff(), 1, &dummy}); } - assert(symAux.size() == 1); + assert(ctx.symAux.size() == 1); for (Symbol *sym : symtab.getSymbols()) fn(*sym); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 93653def328f8..263d4f35c5b9a 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -73,7 +73,6 @@ Defined *ElfSym::riscvGlobalPointer; Defined *ElfSym::relaIpltStart; Defined *ElfSym::relaIpltEnd; Defined *ElfSym::tlsModuleBase; -SmallVector<SymbolAux, 0> elf::symAux; static uint64_t getSymVA(const Symbol &sym, int64_t addend) { switch (sym.kind()) { diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index e764fe8d73633..ff825615658eb 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -56,17 +56,6 @@ enum { NEEDS_TLSIE = 1 << 8, }; -// Some index properties of a symbol are stored separately in this auxiliary -// struct to decrease sizeof(SymbolUnion) in the majority of cases. -struct SymbolAux { - uint32_t gotIdx = -1; - uint32_t pltIdx = -1; - uint32_t tlsDescIdx = -1; - uint32_t tlsGdIdx = -1; -}; - -LLVM_LIBRARY_VISIBILITY extern SmallVector<SymbolAux, 0> symAux; - // The base class for real symbol classes. class Symbol { public: @@ -211,10 +200,10 @@ class Symbol { // truncated by Symbol::parseSymbolVersion(). const char *getVersionSuffix() const { return nameData + nameSize; } - uint32_t getGotIdx() const { return symAux[auxIdx].gotIdx; } - uint32_t getPltIdx() const { return symAux[auxIdx].pltIdx; } - uint32_t getTlsDescIdx() const { return symAux[auxIdx].tlsDescIdx; } - uint32_t getTlsGdIdx() const { return symAux[auxIdx].tlsGdIdx; } + uint32_t getGotIdx() const { return ctx.symAux[auxIdx].gotIdx; } + uint32_t getPltIdx() const { return ctx.symAux[auxIdx].pltIdx; } + uint32_t getTlsDescIdx() const { return ctx.symAux[auxIdx].tlsDescIdx; } + uint32_t getTlsGdIdx() const { return ctx.symAux[auxIdx].tlsGdIdx; } bool isInGot() const { return getGotIdx() != uint32_t(-1); } bool isInPlt() const { return getPltIdx() != uint32_t(-1); } @@ -325,8 +314,8 @@ class Symbol { // entries during postScanRelocations(); std::atomic<uint16_t> flags; - // A symAux index used to access GOT/PLT entry indexes. This is allocated in - // postScanRelocations(). + // A ctx.symAux index used to access GOT/PLT entry indexes. This is allocated + // in postScanRelocations(). uint32_t auxIdx; uint32_t dynsymIndex; @@ -357,8 +346,8 @@ class Symbol { } void allocateAux() { assert(auxIdx == 0); - auxIdx = symAux.size(); - symAux.emplace_back(); + auxIdx = ctx.symAux.size(); + ctx.symAux.emplace_back(); } bool isSection() const { return type == llvm::ELF::STT_SECTION; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 41053c6472751..78962a0f012f8 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -655,20 +655,20 @@ GotSection::GotSection() void GotSection::addConstant(const Relocation &r) { relocations.push_back(r); } void GotSection::addEntry(const Symbol &sym) { - assert(sym.auxIdx == symAux.size() - 1); - symAux.back().gotIdx = numEntries++; + assert(sym.auxIdx == ctx.symAux.size() - 1); + ctx.symAux.back().gotIdx = numEntries++; } bool GotSection::addTlsDescEntry(const Symbol &sym) { - assert(sym.auxIdx == symAux.size() - 1); - symAux.back().tlsDescIdx = numEntries; + assert(sym.auxIdx == ctx.symAux.size() - 1); + ctx.symAux.back().tlsDescIdx = numEntries; numEntries += 2; return true; } bool GotSection::addDynTlsEntry(const Symbol &sym) { - assert(sym.auxIdx == symAux.size() - 1); - symAux.back().tlsGdIdx = numEntries; + assert(sym.auxIdx == ctx.symAux.size() - 1); + ctx.symAux.back().tlsGdIdx = numEntries; // Global Dynamic TLS entries take two GOT slots. numEntries += 2; return true; @@ -999,12 +999,12 @@ void MipsGotSection::build() { for (auto &p : primGot->global) { if (p.first->auxIdx == 0) p.first->allocateAux(); - symAux.back().gotIdx = p.second; + ctx.symAux.back().gotIdx = p.second; } for (auto &p : primGot->relocs) { if (p.first->auxIdx == 0) p.first->allocateAux(); - symAux.back().gotIdx = p.second; + ctx.symAux.back().gotIdx = p.second; } // Create dynamic relocations. @@ -1173,8 +1173,8 @@ GotPltSection::GotPltSection() } void GotPltSection::addEntry(Symbol &sym) { - assert(sym.auxIdx == symAux.size() - 1 && - symAux.back().pltIdx == entries.size()); + assert(sym.auxIdx == ctx.symAux.size() - 1 && + ctx.symAux.back().pltIdx == entries.size()); entries.push_back(&sym); } @@ -1219,7 +1219,7 @@ IgotPltSection::IgotPltSection() target->gotEntrySize, getIgotPltName()) {} void IgotPltSection::addEntry(Symbol &sym) { - assert(symAux.back().pltIdx == entries.size()); + assert(ctx.symAux.back().pltIdx == entries.size()); entries.push_back(&sym); } @@ -2568,8 +2568,8 @@ void PltSection::writeTo(uint8_t *buf) { } void PltSection::addEntry(Symbol &sym) { - assert(sym.auxIdx == symAux.size() - 1); - symAux.back().pltIdx = entries.size(); + assert(sym.auxIdx == ctx.symAux.size() - 1); + ctx.symAux.back().pltIdx = entries.size(); entries.push_back(&sym); } @@ -2615,8 +2615,8 @@ size_t IpltSection::getSize() const { } void IpltSection::addEntry(Symbol &sym) { - assert(sym.auxIdx == symAux.size() - 1); - symAux.back().pltIdx = entries.size(); + assert(sym.auxIdx == ctx.symAux.size() - 1); + ctx.symAux.back().pltIdx = entries.size(); entries.push_back(&sym); } >From f530b3a7fc8a299f449277791c0f1c348d8ea965 Mon Sep 17 00:00:00 2001 From: Fangrui Song <i...@maskray.me> Date: Sat, 3 Aug 2024 11:00:11 -0700 Subject: [PATCH 3/4] [ELF] Move Out into Ctx. NFC Ctx was introduced in March 2022 as a more suitable place for such singletons. ctx's hidden visibility optimizes generated instructions. bufferStart and tlsPhdr, which are not OutputSection, can now be moved outside of `Out`. (cherry picked from commit 09dd0febbbd59a0c470b3909690cae6618a2416a) --- lld/ELF/Config.h | 16 ++++++ lld/ELF/Driver.cpp | 7 ++- lld/ELF/InputSection.cpp | 2 +- lld/ELF/LinkerScript.cpp | 16 +++--- lld/ELF/OutputSections.cpp | 10 +--- lld/ELF/OutputSections.h | 13 ----- lld/ELF/Symbols.cpp | 4 +- lld/ELF/SyntheticSections.cpp | 33 +++++------- lld/ELF/Target.cpp | 4 +- lld/ELF/Writer.cpp | 97 +++++++++++++++++------------------ 10 files changed, 97 insertions(+), 105 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 6abd929d2343d..699a2d966aab3 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -44,6 +44,8 @@ class InputSectionBase; class EhInputSection; class Symbol; class BitcodeCompiler; +class OutputSection; +struct PhdrEntry; enum ELFKind : uint8_t { ELFNoneKind, @@ -477,6 +479,20 @@ struct DuplicateSymbol { struct Ctx { LinkerDriver driver; + + // These variables are initialized by Writer and should not be used before + // Writer is initialized. + uint8_t *bufferStart; + PhdrEntry *tlsPhdr; + struct OutSections { + OutputSection *elfHeader; + OutputSection *programHeaders; + OutputSection *preinitArray; + OutputSection *initArray; + OutputSection *finiArray; + }; + OutSections out; + SmallVector<std::unique_ptr<MemoryBuffer>> memoryBuffers; SmallVector<ELFFileBase *, 0> objectFiles; SmallVector<SharedFile *, 0> sharedFiles; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 8f6ca2a98484d..2bebd068a1008 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -93,6 +93,11 @@ void elf::errorOrWarn(const Twine &msg) { void Ctx::reset() { driver = LinkerDriver(); + + bufferStart = nullptr; + tlsPhdr = nullptr; + out = OutSections{}; + memoryBuffers.clear(); objectFiles.clear(); sharedFiles.clear(); @@ -2934,7 +2939,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) { // Create elfHeader early. We need a dummy section in // addReservedSymbols to mark the created symbols as not absolute. - Out::elfHeader = make<OutputSection>("", 0, SHF_ALLOC); + ctx.out.elfHeader = make<OutputSection>("", 0, SHF_ALLOC); // We need to create some reserved symbols such as _end. Create them. if (!config->relocatable) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 570e485455bad..7f8dded51fdab 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -679,7 +679,7 @@ static int64_t getTlsTpOffset(const Symbol &s) { // Variant 2. Static TLS blocks, followed by alignment padding are placed // before TP. The alignment padding is added so that (TP - padding - // p_memsz) is congruent to p_vaddr modulo p_align. - PhdrEntry *tls = Out::tlsPhdr; + PhdrEntry *tls = ctx.tlsPhdr; switch (config->emachine) { // Variant 1. case EM_ARM: diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 055fa21d44ca6..bf7491f11eff5 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -1359,8 +1359,8 @@ void LinkerScript::allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs) { if ((paged || hasExplicitHeaders) && headerSize <= min - computeBase(min, hasExplicitHeaders)) { min = alignDown(min - headerSize, config->maxPageSize); - Out::elfHeader->addr = min; - Out::programHeaders->addr = min + Out::elfHeader->size; + ctx.out.elfHeader->addr = min; + ctx.out.programHeaders->addr = min + ctx.out.elfHeader->size; return; } @@ -1368,8 +1368,8 @@ void LinkerScript::allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs) { if (hasExplicitHeaders) error("could not allocate headers"); - Out::elfHeader->ptLoad = nullptr; - Out::programHeaders->ptLoad = nullptr; + ctx.out.elfHeader->ptLoad = nullptr; + ctx.out.programHeaders->ptLoad = nullptr; firstPTLoad->firstSec = findFirstSection(firstPTLoad); llvm::erase_if(phdrs, @@ -1397,8 +1397,8 @@ LinkerScript::assignAddresses() { } else { // Assign addresses to headers right now. dot = target->getImageBase(); - Out::elfHeader->addr = dot; - Out::programHeaders->addr = dot + Out::elfHeader->size; + ctx.out.elfHeader->addr = dot; + ctx.out.programHeaders->addr = dot + ctx.out.elfHeader->size; dot += getHeaderSize(); } @@ -1543,9 +1543,9 @@ SmallVector<PhdrEntry *, 0> LinkerScript::createPhdrs() { PhdrEntry *phdr = make<PhdrEntry>(cmd.type, cmd.flags.value_or(PF_R)); if (cmd.hasFilehdr) - phdr->add(Out::elfHeader); + phdr->add(ctx.out.elfHeader); if (cmd.hasPhdrs) - phdr->add(Out::programHeaders); + phdr->add(ctx.out.programHeaders); if (cmd.lmaExpr) { phdr->p_paddr = cmd.lmaExpr().getValue(); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 29f18f89274f3..509098eed2b83 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -39,14 +39,6 @@ using namespace llvm::ELF; using namespace lld; using namespace lld::elf; -uint8_t *Out::bufferStart; -PhdrEntry *Out::tlsPhdr; -OutputSection *Out::elfHeader; -OutputSection *Out::programHeaders; -OutputSection *Out::preinitArray; -OutputSection *Out::initArray; -OutputSection *Out::finiArray; - SmallVector<OutputSection *, 0> elf::outputSections; uint32_t OutputSection::getPhdrFlags() const { @@ -272,7 +264,7 @@ static void sortByOrder(MutableArrayRef<InputSection *> in, uint64_t elf::getHeaderSize() { if (config->oFormatBinary) return 0; - return Out::elfHeader->size + Out::programHeaders->size; + return ctx.out.elfHeader->size + ctx.out.programHeaders->size; } void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) { diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 8c0c52f34ac9f..6ced44be47e46 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -150,19 +150,6 @@ llvm::ArrayRef<InputSection *> getInputSections(const OutputSection &os, SmallVector<InputSection *, 0> &storage); -// All output sections that are handled by the linker specially are -// globally accessible. Writer initializes them, so don't use them -// until Writer is initialized. -struct Out { - static uint8_t *bufferStart; - static PhdrEntry *tlsPhdr; - static OutputSection *elfHeader; - static OutputSection *programHeaders; - static OutputSection *preinitArray; - static OutputSection *initArray; - static OutputSection *finiArray; -}; - uint64_t getHeaderSize(); LLVM_LIBRARY_VISIBILITY extern llvm::SmallVector<OutputSection *, 0> diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 263d4f35c5b9a..9cab824c37c3c 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -135,10 +135,10 @@ static uint64_t getSymVA(const Symbol &sym, int64_t addend) { // after sections are finalized. (e.g. Measuring the size of .rela.dyn // for Android relocation packing requires knowing TLS symbol addresses // during section finalization.) - if (!Out::tlsPhdr || !Out::tlsPhdr->firstSec) + if (!ctx.tlsPhdr || !ctx.tlsPhdr->firstSec) fatal(toString(d.file) + " has an STT_TLS symbol but doesn't have an SHF_TLS section"); - return va - Out::tlsPhdr->firstSec->addr; + return va - ctx.tlsPhdr->firstSec->addr; } return va; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 78962a0f012f8..97e0d84a371b5 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -553,7 +553,7 @@ void EhFrameSection::finalizeContents() { // to get an FDE from an address to which FDE is applied. This function // returns a list of such pairs. SmallVector<EhFrameSection::FdeData, 0> EhFrameSection::getFdeData() const { - uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff; + uint8_t *buf = ctx.bufferStart + getParent()->offset + outSecOff; SmallVector<FdeData, 0> ret; uint64_t va = getPartition().ehFrameHdr->getVA(); @@ -1493,17 +1493,17 @@ DynamicSection<ELFT>::computeContents() { addInSec(DT_HASH, *part.hashTab); if (isMain) { - if (Out::preinitArray) { - addInt(DT_PREINIT_ARRAY, Out::preinitArray->addr); - addInt(DT_PREINIT_ARRAYSZ, Out::preinitArray->size); + if (ctx.out.preinitArray) { + addInt(DT_PREINIT_ARRAY, ctx.out.preinitArray->addr); + addInt(DT_PREINIT_ARRAYSZ, ctx.out.preinitArray->size); } - if (Out::initArray) { - addInt(DT_INIT_ARRAY, Out::initArray->addr); - addInt(DT_INIT_ARRAYSZ, Out::initArray->size); + if (ctx.out.initArray) { + addInt(DT_INIT_ARRAY, ctx.out.initArray->addr); + addInt(DT_INIT_ARRAYSZ, ctx.out.initArray->size); } - if (Out::finiArray) { - addInt(DT_FINI_ARRAY, Out::finiArray->addr); - addInt(DT_FINI_ARRAYSZ, Out::finiArray->size); + if (ctx.out.finiArray) { + addInt(DT_FINI_ARRAY, ctx.out.finiArray->addr); + addInt(DT_FINI_ARRAYSZ, ctx.out.finiArray->size); } if (Symbol *b = symtab.find(config->init)) @@ -3631,7 +3631,7 @@ void EhFrameHeader::writeTo(uint8_t *buf) { // the starting PC from where FDEs covers, and the FDE's address. // It is sorted by PC. void EhFrameHeader::write() { - uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff; + uint8_t *buf = ctx.bufferStart + getParent()->offset + outSecOff; using FdeData = EhFrameSection::FdeData; SmallVector<FdeData, 0> fdes = getPartition().ehFrame->getFdeData(); @@ -4647,13 +4647,6 @@ static Defined *addOptionalRegular(StringRef name, SectionBase *sec, } template <class ELFT> void elf::createSyntheticSections() { - // Initialize all pointers with NULL. This is needed because - // you can call lld::elf::main more than once as a library. - Out::tlsPhdr = nullptr; - Out::preinitArray = nullptr; - Out::initArray = nullptr; - Out::finiArray = nullptr; - // Add the .interp section first because it is not a SyntheticSection. // The removeUnusedSyntheticSections() function relies on the // SyntheticSections coming last. @@ -4669,8 +4662,8 @@ template <class ELFT> void elf::createSyntheticSections() { in.shStrTab = std::make_unique<StringTableSection>(".shstrtab", false); - Out::programHeaders = make<OutputSection>("", 0, SHF_ALLOC); - Out::programHeaders->addralign = config->wordsize; + ctx.out.programHeaders = make<OutputSection>("", 0, SHF_ALLOC); + ctx.out.programHeaders->addralign = config->wordsize; if (config->strip != StripPolicy::All) { in.strTab = std::make_unique<StringTableSection>(".strtab", false); diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 3e221646ce247..584e9270469d0 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -104,8 +104,8 @@ ErrorPlace elf::getErrorPlace(const uint8_t *loc) { continue; const uint8_t *isecLoc = - Out::bufferStart - ? (Out::bufferStart + isec->getParent()->offset + isec->outSecOff) + ctx.bufferStart + ? (ctx.bufferStart + isec->getParent()->offset + isec->outSecOff) : isec->contentMaybeDecompress().data(); if (isecLoc == nullptr) { assert(isa<SyntheticSection>(isec) && "No data but not synthetic?"); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 8e3a746a08eb2..0c5990351e59e 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -211,7 +211,7 @@ void elf::addReservedSymbols() { gotOff = 0x8000; s->resolve(Defined{ctx.internalFile, StringRef(), STB_GLOBAL, STV_HIDDEN, - STT_NOTYPE, gotOff, /*size=*/0, Out::elfHeader}); + STT_NOTYPE, gotOff, /*size=*/0, ctx.out.elfHeader}); ElfSym::globalOffsetTable = cast<Defined>(s); } @@ -219,23 +219,23 @@ void elf::addReservedSymbols() { // this symbol unconditionally even when using a linker script, which // differs from the behavior implemented by GNU linker which only define // this symbol if ELF headers are in the memory mapped segment. - addOptionalRegular("__ehdr_start", Out::elfHeader, 0, STV_HIDDEN); + addOptionalRegular("__ehdr_start", ctx.out.elfHeader, 0, STV_HIDDEN); // __executable_start is not documented, but the expectation of at // least the Android libc is that it points to the ELF header. - addOptionalRegular("__executable_start", Out::elfHeader, 0, STV_HIDDEN); + addOptionalRegular("__executable_start", ctx.out.elfHeader, 0, STV_HIDDEN); // __dso_handle symbol is passed to cxa_finalize as a marker to identify // each DSO. The address of the symbol doesn't matter as long as they are // different in different DSOs, so we chose the start address of the DSO. - addOptionalRegular("__dso_handle", Out::elfHeader, 0, STV_HIDDEN); + addOptionalRegular("__dso_handle", ctx.out.elfHeader, 0, STV_HIDDEN); // If linker script do layout we do not need to create any standard symbols. if (script->hasSectionsCommand) return; auto add = [](StringRef s, int64_t pos) { - return addOptionalRegular(s, Out::elfHeader, pos, STV_DEFAULT); + return addOptionalRegular(s, ctx.out.elfHeader, pos, STV_DEFAULT); }; ElfSym::bss = add("__bss_start", 0); @@ -796,13 +796,14 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { return; // __rela_iplt_{start,end} are initially defined relative to dummy section 0. - // We'll override Out::elfHeader with relaDyn later when we are sure that + // We'll override ctx.out.elfHeader with relaDyn later when we are sure that // .rela.dyn will be present in the output. std::string name = config->isRela ? "__rela_iplt_start" : "__rel_iplt_start"; ElfSym::relaIpltStart = - addOptionalRegular(name, Out::elfHeader, 0, STV_HIDDEN); + addOptionalRegular(name, ctx.out.elfHeader, 0, STV_HIDDEN); name.replace(name.size() - 5, 5, "end"); - ElfSym::relaIpltEnd = addOptionalRegular(name, Out::elfHeader, 0, STV_HIDDEN); + ElfSym::relaIpltEnd = + addOptionalRegular(name, ctx.out.elfHeader, 0, STV_HIDDEN); } // This function generates assignments for predefined symbols (e.g. _end or @@ -1693,9 +1694,9 @@ static void removeUnusedSyntheticSections() { // Create output section objects and add them to OutputSections. template <class ELFT> void Writer<ELFT>::finalizeSections() { if (!config->relocatable) { - Out::preinitArray = findSection(".preinit_array"); - Out::initArray = findSection(".init_array"); - Out::finiArray = findSection(".fini_array"); + ctx.out.preinitArray = findSection(".preinit_array"); + ctx.out.initArray = findSection(".init_array"); + ctx.out.finiArray = findSection(".fini_array"); // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop // symbols for sections, so that the runtime can get the start and end @@ -1722,13 +1723,13 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800. This symbol // should only be defined in an executable. If .sdata does not exist, its // value/section does not matter but it has to be relative, so set its - // st_shndx arbitrarily to 1 (Out::elfHeader). + // st_shndx arbitrarily to 1 (ctx.out.elfHeader). if (config->emachine == EM_RISCV) { ElfSym::riscvGlobalPointer = nullptr; if (!config->shared) { OutputSection *sec = findSection(".sdata"); - addOptionalRegular( - "__global_pointer$", sec ? sec : Out::elfHeader, 0x800, STV_DEFAULT); + addOptionalRegular("__global_pointer$", sec ? sec : ctx.out.elfHeader, + 0x800, STV_DEFAULT); // Set riscvGlobalPointer to be used by the optional global pointer // relaxation. if (config->relaxGP) { @@ -1913,8 +1914,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // This is a bit of a hack. A value of 0 means undef, so we set it // to 1 to make __ehdr_start defined. The section number is not // particularly relevant. - Out::elfHeader->sectionIndex = 1; - Out::elfHeader->size = sizeof(typename ELFT::Ehdr); + ctx.out.elfHeader->sectionIndex = 1; + ctx.out.elfHeader->size = sizeof(typename ELFT::Ehdr); // Binary and relocatable output does not have PHDRS. // The headers have to be created before finalize as that can influence the @@ -1937,7 +1938,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { addPhdrForSection(part, SHT_RISCV_ATTRIBUTES, PT_RISCV_ATTRIBUTES, PF_R); } - Out::programHeaders->size = sizeof(Elf_Phdr) * mainPart->phdrs.size(); + ctx.out.programHeaders->size = sizeof(Elf_Phdr) * mainPart->phdrs.size(); // Find the TLS segment. This happens before the section layout loop so that // Android relocation packing can look up TLS symbol addresses. We only need @@ -1945,7 +1946,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // to the main partition (see MarkLive.cpp). for (PhdrEntry *p : mainPart->phdrs) if (p->p_type == PT_TLS) - Out::tlsPhdr = p; + ctx.tlsPhdr = p; } // Some symbols are defined in term of program headers. Now that we @@ -2097,14 +2098,14 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { if (startSym || stopSym) os->usedInExpression = true; } else { - addOptionalRegular(start, Out::elfHeader, 0); - addOptionalRegular(end, Out::elfHeader, 0); + addOptionalRegular(start, ctx.out.elfHeader, 0); + addOptionalRegular(end, ctx.out.elfHeader, 0); } }; - define("__preinit_array_start", "__preinit_array_end", Out::preinitArray); - define("__init_array_start", "__init_array_end", Out::initArray); - define("__fini_array_start", "__fini_array_end", Out::finiArray); + define("__preinit_array_start", "__preinit_array_end", ctx.out.preinitArray); + define("__init_array_start", "__init_array_end", ctx.out.initArray); + define("__fini_array_start", "__fini_array_end", ctx.out.finiArray); // As a special case, don't unnecessarily retain .ARM.exidx, which would // create an empty PT_ARM_EXIDX. @@ -2174,7 +2175,7 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) { // The first phdr entry is PT_PHDR which describes the program header // itself. if (isMain) - addHdr(PT_PHDR, PF_R)->add(Out::programHeaders); + addHdr(PT_PHDR, PF_R)->add(ctx.out.programHeaders); else addHdr(PT_PHDR, PF_R)->add(part.programHeaders->getParent()); @@ -2187,8 +2188,8 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) { // need to be added here. if (isMain) { load = addHdr(PT_LOAD, flags); - load->add(Out::elfHeader); - load->add(Out::programHeaders); + load->add(ctx.out.elfHeader); + load->add(ctx.out.programHeaders); } } @@ -2260,7 +2261,7 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) { load && !sec->lmaExpr && sec->lmaRegion == load->firstSec->lmaRegion; if (load && sec != relroEnd && sec->memRegion == load->firstSec->memRegion && - (sameLMARegion || load->lastSec == Out::programHeaders) && + (sameLMARegion || load->lastSec == ctx.out.programHeaders) && (script->hasSectionsCommand || sec->type == SHT_NOBITS || load->lastSec->type != SHT_NOBITS)) { load->p_flags |= newFlags; @@ -2407,11 +2408,11 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { // p_align for dynamic TLS blocks (PR/24606), FreeBSD rtld has the same // bug, musl (TLS Variant 1 architectures) before 1.1.23 handled TLS // blocks correctly. We need to keep the workaround for a while. - else if (Out::tlsPhdr && Out::tlsPhdr->firstSec == p->firstSec) + else if (ctx.tlsPhdr && ctx.tlsPhdr->firstSec == p->firstSec) cmd->addrExpr = [] { return alignToPowerOf2(script->getDot(), config->maxPageSize) + alignToPowerOf2(script->getDot() % config->maxPageSize, - Out::tlsPhdr->p_align); + ctx.tlsPhdr->p_align); }; else cmd->addrExpr = [] { @@ -2443,9 +2444,8 @@ static uint64_t computeFileOffset(OutputSection *os, uint64_t off) { // File offsets are not significant for .bss sections other than the first one // in a PT_LOAD/PT_TLS. By convention, we keep section offsets monotonically // increasing rather than setting to zero. - if (os->type == SHT_NOBITS && - (!Out::tlsPhdr || Out::tlsPhdr->firstSec != os)) - return off; + if (os->type == SHT_NOBITS && (!ctx.tlsPhdr || ctx.tlsPhdr->firstSec != os)) + return off; // If the section is not in a PT_LOAD, we just have to align it. if (!os->ptLoad) @@ -2484,8 +2484,8 @@ static std::string rangeToString(uint64_t addr, uint64_t len) { // Assign file offsets to output sections. template <class ELFT> void Writer<ELFT>::assignFileOffsets() { - Out::programHeaders->offset = Out::elfHeader->size; - uint64_t off = Out::elfHeader->size + Out::programHeaders->size; + ctx.out.programHeaders->offset = ctx.out.elfHeader->size; + uint64_t off = ctx.out.elfHeader->size + ctx.out.programHeaders->size; PhdrEntry *lastRX = nullptr; for (Partition &part : partitions) @@ -2706,10 +2706,10 @@ static uint16_t getELFType() { } template <class ELFT> void Writer<ELFT>::writeHeader() { - writeEhdr<ELFT>(Out::bufferStart, *mainPart); - writePhdrs<ELFT>(Out::bufferStart + sizeof(Elf_Ehdr), *mainPart); + writeEhdr<ELFT>(ctx.bufferStart, *mainPart); + writePhdrs<ELFT>(ctx.bufferStart + sizeof(Elf_Ehdr), *mainPart); - auto *eHdr = reinterpret_cast<Elf_Ehdr *>(Out::bufferStart); + auto *eHdr = reinterpret_cast<Elf_Ehdr *>(ctx.bufferStart); eHdr->e_type = getELFType(); eHdr->e_entry = getEntryAddr(); eHdr->e_shoff = sectionHeaderOff; @@ -2723,7 +2723,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { // the value. The sentinel values and fields are: // e_shnum = 0, SHdrs[0].sh_size = number of sections. // e_shstrndx = SHN_XINDEX, SHdrs[0].sh_link = .shstrtab section index. - auto *sHdrs = reinterpret_cast<Elf_Shdr *>(Out::bufferStart + eHdr->e_shoff); + auto *sHdrs = reinterpret_cast<Elf_Shdr *>(ctx.bufferStart + eHdr->e_shoff); size_t num = outputSections.size() + 1; if (num >= SHN_LORESERVE) sHdrs->sh_size = num; @@ -2771,14 +2771,14 @@ template <class ELFT> void Writer<ELFT>::openFile() { return; } buffer = std::move(*bufferOrErr); - Out::bufferStart = buffer->getBufferStart(); + ctx.bufferStart = buffer->getBufferStart(); } template <class ELFT> void Writer<ELFT>::writeSectionsBinary() { parallel::TaskGroup tg; for (OutputSection *sec : outputSections) if (sec->flags & SHF_ALLOC) - sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg); + sec->writeTo<ELFT>(ctx.bufferStart + sec->offset, tg); } static void fillTrap(uint8_t *i, uint8_t *end) { @@ -2797,11 +2797,10 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() { // Fill the last page. for (PhdrEntry *p : part.phdrs) if (p->p_type == PT_LOAD && (p->p_flags & PF_X)) - fillTrap(Out::bufferStart + - alignDown(p->firstSec->offset + p->p_filesz, 4), - Out::bufferStart + - alignToPowerOf2(p->firstSec->offset + p->p_filesz, - config->maxPageSize)); + fillTrap( + ctx.bufferStart + alignDown(p->firstSec->offset + p->p_filesz, 4), + ctx.bufferStart + alignToPowerOf2(p->firstSec->offset + p->p_filesz, + config->maxPageSize)); // Round up the file size of the last segment to the page boundary iff it is // an executable segment to ensure that other tools don't accidentally @@ -2828,20 +2827,20 @@ template <class ELFT> void Writer<ELFT>::writeSections() { parallel::TaskGroup tg; for (OutputSection *sec : outputSections) if (isStaticRelSecType(sec->type)) - sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg); + sec->writeTo<ELFT>(ctx.bufferStart + sec->offset, tg); } { parallel::TaskGroup tg; for (OutputSection *sec : outputSections) if (!isStaticRelSecType(sec->type)) - sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg); + sec->writeTo<ELFT>(ctx.bufferStart + sec->offset, tg); } // Finally, check that all dynamic relocation addends were written correctly. if (config->checkDynamicRelocs && config->writeAddends) { for (OutputSection *sec : outputSections) if (isStaticRelSecType(sec->type)) - sec->checkDynRelAddends(Out::bufferStart); + sec->checkDynRelAddends(ctx.bufferStart); } } @@ -2880,7 +2879,7 @@ template <class ELFT> void Writer<ELFT>::writeBuildId() { size_t hashSize = mainPart->buildId->hashSize; std::unique_ptr<uint8_t[]> buildId(new uint8_t[hashSize]); MutableArrayRef<uint8_t> output(buildId.get(), hashSize); - llvm::ArrayRef<uint8_t> input{Out::bufferStart, size_t(fileSize)}; + llvm::ArrayRef<uint8_t> input{ctx.bufferStart, size_t(fileSize)}; // Fedora introduced build ID as "approximation of true uniqueness across all // binaries that might be used by overlapping sets of people". It does not >From 17017aad2b66859a7fbae99248ce0ce284512126 Mon Sep 17 00:00:00 2001 From: Fangrui Song <i...@maskray.me> Date: Sat, 3 Aug 2024 11:20:32 -0700 Subject: [PATCH 4/4] [ELF] Move ElfSym into Ctx. NFC Ctx was introduced in March 2022 as a more suitable place for such singletons. ctx's hidden visibility optimizes generated instructions. This change fixes a pitfall: certain ElfSym members (e.g. globalOffsetTable, tlsModuleBase) were not zeroed and might be stale when lld::elf::link was invoked the second time. (cherry picked from commit 03be619d9434de0a9616660a2119675635239a5b) --- lld/ELF/Arch/Mips.cpp | 4 +- lld/ELF/Arch/RISCV.cpp | 4 +- lld/ELF/Config.h | 41 +++++++++++++++++++ lld/ELF/Driver.cpp | 2 + lld/ELF/InputSection.cpp | 2 +- lld/ELF/Symbols.cpp | 16 -------- lld/ELF/Symbols.h | 39 ------------------ lld/ELF/SyntheticSections.cpp | 6 +-- lld/ELF/Writer.cpp | 77 +++++++++++++++++------------------ 9 files changed, 89 insertions(+), 102 deletions(-) diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp index e36e9d59a7401..7c7137117d78e 100644 --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -121,9 +121,9 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType type, const Symbol &s, // offset between start of function and 'gp' value which by default // equal to the start of .got section. In that case we consider these // relocations as relative. - if (&s == ElfSym::mipsGpDisp) + if (&s == ctx.sym.mipsGpDisp) return R_MIPS_GOT_GP_PC; - if (&s == ElfSym::mipsLocalGp) + if (&s == ctx.sym.mipsLocalGp) return R_MIPS_GOT_GP; [[fallthrough]]; case R_MIPS_32: diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 56759c28dcf41..8c2db2145f305 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -466,7 +466,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { case INTERNAL_R_RISCV_GPREL_I: case INTERNAL_R_RISCV_GPREL_S: { - Defined *gp = ElfSym::riscvGlobalPointer; + Defined *gp = ctx.sym.riscvGlobalPointer; int64_t displace = SignExtend64(val - gp->getVA(), bits); checkInt(loc, displace, 12, rel); uint32_t insn = (read32le(loc) & ~(31 << 15)) | (X_GP << 15); @@ -789,7 +789,7 @@ static void relaxTlsLe(const InputSection &sec, size_t i, uint64_t loc, static void relaxHi20Lo12(const InputSection &sec, size_t i, uint64_t loc, Relocation &r, uint32_t &remove) { - const Defined *gp = ElfSym::riscvGlobalPointer; + const Defined *gp = ctx.sym.riscvGlobalPointer; if (!gp) return; diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 699a2d966aab3..f562985630be4 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -42,6 +42,7 @@ class ELFFileBase; class SharedFile; class InputSectionBase; class EhInputSection; +class Defined; class Symbol; class BitcodeCompiler; class OutputSection; @@ -493,6 +494,46 @@ struct Ctx { }; OutSections out; + // Some linker-generated symbols need to be created as + // Defined symbols. + struct ElfSym { + // __bss_start + Defined *bss; + + // etext and _etext + Defined *etext1; + Defined *etext2; + + // edata and _edata + Defined *edata1; + Defined *edata2; + + // end and _end + Defined *end1; + Defined *end2; + + // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to + // be at some offset from the base of the .got section, usually 0 or + // the end of the .got. + Defined *globalOffsetTable; + + // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS. + Defined *mipsGp; + Defined *mipsGpDisp; + Defined *mipsLocalGp; + + // __global_pointer$ for RISC-V. + Defined *riscvGlobalPointer; + + // __rel{,a}_iplt_{start,end} symbols. + Defined *relaIpltStart; + Defined *relaIpltEnd; + + // _TLS_MODULE_BASE_ on targets that support TLSDESC. + Defined *tlsModuleBase; + }; + ElfSym sym; + SmallVector<std::unique_ptr<MemoryBuffer>> memoryBuffers; SmallVector<ELFFileBase *, 0> objectFiles; SmallVector<SharedFile *, 0> sharedFiles; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 2bebd068a1008..806f1e52e7244 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -98,6 +98,8 @@ void Ctx::reset() { tlsPhdr = nullptr; out = OutSections{}; + sym = ElfSym{}; + memoryBuffers.clear(); objectFiles.clear(); sharedFiles.clear(); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 7f8dded51fdab..da4c90516ec30 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -665,7 +665,7 @@ static Relocation *getRISCVPCRelHi20(const Symbol *sym, uint64_t addend) { // target-specific adjustment to produce a thread-pointer-relative offset. static int64_t getTlsTpOffset(const Symbol &s) { // On targets that support TLSDESC, _TLS_MODULE_BASE_@tpoff = 0. - if (&s == ElfSym::tlsModuleBase) + if (&s == ctx.sym.tlsModuleBase) return 0; // There are 2 TLS layouts. Among targets we support, x86 uses TLS Variant 2 diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 9cab824c37c3c..4e1ae819b86fa 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -58,22 +58,6 @@ std::string lld::toString(const elf::Symbol &sym) { return ret; } -Defined *ElfSym::bss; -Defined *ElfSym::etext1; -Defined *ElfSym::etext2; -Defined *ElfSym::edata1; -Defined *ElfSym::edata2; -Defined *ElfSym::end1; -Defined *ElfSym::end2; -Defined *ElfSym::globalOffsetTable; -Defined *ElfSym::mipsGp; -Defined *ElfSym::mipsGpDisp; -Defined *ElfSym::mipsLocalGp; -Defined *ElfSym::riscvGlobalPointer; -Defined *ElfSym::relaIpltStart; -Defined *ElfSym::relaIpltEnd; -Defined *ElfSym::tlsModuleBase; - static uint64_t getSymVA(const Symbol &sym, int64_t addend) { switch (sym.kind()) { case Symbol::DefinedKind: { diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index ff825615658eb..05aed16bfb0dc 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -501,45 +501,6 @@ class LazySymbol : public Symbol { static bool classof(const Symbol *s) { return s->kind() == LazyKind; } }; -// Some linker-generated symbols need to be created as -// Defined symbols. -struct ElfSym { - // __bss_start - static Defined *bss; - - // etext and _etext - static Defined *etext1; - static Defined *etext2; - - // edata and _edata - static Defined *edata1; - static Defined *edata2; - - // end and _end - static Defined *end1; - static Defined *end2; - - // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to - // be at some offset from the base of the .got section, usually 0 or - // the end of the .got. - static Defined *globalOffsetTable; - - // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS. - static Defined *mipsGp; - static Defined *mipsGpDisp; - static Defined *mipsLocalGp; - - // __global_pointer$ for RISC-V. - static Defined *riscvGlobalPointer; - - // __rel{,a}_iplt_{start,end} symbols. - static Defined *relaIpltStart; - static Defined *relaIpltEnd; - - // _TLS_MODULE_BASE_ on targets that support TLSDESC. - static Defined *tlsModuleBase; -}; - // A buffer class that is large enough to hold any Symbol-derived // object. We allocate memory using this class and instantiate a symbol // using the placement new. diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 97e0d84a371b5..da372370ccfeb 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -702,7 +702,7 @@ uint64_t GotSection::getGlobalDynOffset(const Symbol &b) const { void GotSection::finalizeContents() { if (config->emachine == EM_PPC64 && - numEntries <= target->gotHeaderEntriesNum && !ElfSym::globalOffsetTable) + numEntries <= target->gotHeaderEntriesNum && !ctx.sym.globalOffsetTable) size = 0; else size = numEntries * config->wordsize; @@ -1090,7 +1090,7 @@ uint64_t MipsGotSection::getGp(const InputFile *f) const { // returns "common" _gp value. For secondary GOTs calculate // individual _gp values. if (!f || f->mipsGotIndex == uint32_t(-1) || f->mipsGotIndex == 0) - return ElfSym::mipsGp->getVA(0); + return ctx.sym.mipsGp->getVA(0); return getVA() + gots[f->mipsGotIndex].startIndex * config->wordsize + 0x7ff0; } @@ -4859,7 +4859,7 @@ template <class ELFT> void elf::createSyntheticSections() { // _GLOBAL_OFFSET_TABLE_ is defined relative to either .got.plt or .got. Treat // it as a relocation and ensure the referenced section is created. - if (ElfSym::globalOffsetTable && config->emachine != EM_MIPS) { + if (ctx.sym.globalOffsetTable && config->emachine != EM_MIPS) { if (target->gotBaseSymInGotPlt) in.gotPlt->hasGotPltOffRel = true; else diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 0c5990351e59e..7f6ec49274c6a 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -167,19 +167,19 @@ void elf::addReservedSymbols() { // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - ElfSym::mipsGp = addAbsolute("_gp"); + ctx.sym.mipsGp = addAbsolute("_gp"); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. if (symtab.find("_gp_disp")) - ElfSym::mipsGpDisp = addAbsolute("_gp_disp"); + ctx.sym.mipsGpDisp = addAbsolute("_gp_disp"); // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' // pointer. This symbol is used in the code generated by .cpload pseudo-op // in case of using -mno-shared option. // https://sourceware.org/ml/binutils/2004-12/msg00094.html if (symtab.find("__gnu_local_gp")) - ElfSym::mipsLocalGp = addAbsolute("__gnu_local_gp"); + ctx.sym.mipsLocalGp = addAbsolute("__gnu_local_gp"); } else if (config->emachine == EM_PPC) { // glibc *crt1.o has a undefined reference to _SDA_BASE_. Since we don't // support Small Data Area, define it arbitrarily as 0. @@ -212,7 +212,7 @@ void elf::addReservedSymbols() { s->resolve(Defined{ctx.internalFile, StringRef(), STB_GLOBAL, STV_HIDDEN, STT_NOTYPE, gotOff, /*size=*/0, ctx.out.elfHeader}); - ElfSym::globalOffsetTable = cast<Defined>(s); + ctx.sym.globalOffsetTable = cast<Defined>(s); } // __ehdr_start is the location of ELF file headers. Note that we define @@ -238,13 +238,13 @@ void elf::addReservedSymbols() { return addOptionalRegular(s, ctx.out.elfHeader, pos, STV_DEFAULT); }; - ElfSym::bss = add("__bss_start", 0); - ElfSym::end1 = add("end", -1); - ElfSym::end2 = add("_end", -1); - ElfSym::etext1 = add("etext", -1); - ElfSym::etext2 = add("_etext", -1); - ElfSym::edata1 = add("edata", -1); - ElfSym::edata2 = add("_edata", -1); + ctx.sym.bss = add("__bss_start", 0); + ctx.sym.end1 = add("end", -1); + ctx.sym.end2 = add("_end", -1); + ctx.sym.etext1 = add("etext", -1); + ctx.sym.etext2 = add("_etext", -1); + ctx.sym.edata1 = add("edata", -1); + ctx.sym.edata2 = add("_edata", -1); } static void demoteDefined(Defined &sym, DenseMap<SectionBase *, size_t> &map) { @@ -799,10 +799,10 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { // We'll override ctx.out.elfHeader with relaDyn later when we are sure that // .rela.dyn will be present in the output. std::string name = config->isRela ? "__rela_iplt_start" : "__rel_iplt_start"; - ElfSym::relaIpltStart = + ctx.sym.relaIpltStart = addOptionalRegular(name, ctx.out.elfHeader, 0, STV_HIDDEN); name.replace(name.size() - 5, 5, "end"); - ElfSym::relaIpltEnd = + ctx.sym.relaIpltEnd = addOptionalRegular(name, ctx.out.elfHeader, 0, STV_HIDDEN); } @@ -812,21 +812,21 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { // time any references to these symbols are processed and is equivalent to // defining these symbols explicitly in the linker script. template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { - if (ElfSym::globalOffsetTable) { + if (ctx.sym.globalOffsetTable) { // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually // to the start of the .got or .got.plt section. InputSection *sec = in.gotPlt.get(); if (!target->gotBaseSymInGotPlt) sec = in.mipsGot ? cast<InputSection>(in.mipsGot.get()) : cast<InputSection>(in.got.get()); - ElfSym::globalOffsetTable->section = sec; + ctx.sym.globalOffsetTable->section = sec; } // .rela_iplt_{start,end} mark the start and the end of .rel[a].dyn. - if (ElfSym::relaIpltStart && mainPart->relaDyn->isNeeded()) { - ElfSym::relaIpltStart->section = mainPart->relaDyn.get(); - ElfSym::relaIpltEnd->section = mainPart->relaDyn.get(); - ElfSym::relaIpltEnd->value = mainPart->relaDyn->getSize(); + if (ctx.sym.relaIpltStart && mainPart->relaDyn->isNeeded()) { + ctx.sym.relaIpltStart->section = mainPart->relaDyn.get(); + ctx.sym.relaIpltEnd->section = mainPart->relaDyn.get(); + ctx.sym.relaIpltEnd->value = mainPart->relaDyn->getSize(); } PhdrEntry *last = nullptr; @@ -847,10 +847,10 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { if (lastRO) { // _etext is the first location after the last read-only loadable segment // that does not contain large sections. - if (ElfSym::etext1) - ElfSym::etext1->section = lastRO; - if (ElfSym::etext2) - ElfSym::etext2->section = lastRO; + if (ctx.sym.etext1) + ctx.sym.etext1->section = lastRO; + if (ctx.sym.etext2) + ctx.sym.etext2->section = lastRO; } if (last) { @@ -864,34 +864,34 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { break; } - if (ElfSym::edata1) - ElfSym::edata1->section = edata; - if (ElfSym::edata2) - ElfSym::edata2->section = edata; + if (ctx.sym.edata1) + ctx.sym.edata1->section = edata; + if (ctx.sym.edata2) + ctx.sym.edata2->section = edata; // _end is the first location after the uninitialized data region. - if (ElfSym::end1) - ElfSym::end1->section = last->lastSec; - if (ElfSym::end2) - ElfSym::end2->section = last->lastSec; + if (ctx.sym.end1) + ctx.sym.end1->section = last->lastSec; + if (ctx.sym.end2) + ctx.sym.end2->section = last->lastSec; } - if (ElfSym::bss) { + if (ctx.sym.bss) { // On RISC-V, set __bss_start to the start of .sbss if present. OutputSection *sbss = config->emachine == EM_RISCV ? findSection(".sbss") : nullptr; - ElfSym::bss->section = sbss ? sbss : findSection(".bss"); + ctx.sym.bss->section = sbss ? sbss : findSection(".bss"); } // Setup MIPS _gp_disp/__gnu_local_gp symbols which should // be equal to the _gp symbol's value. - if (ElfSym::mipsGp) { + if (ctx.sym.mipsGp) { // Find GP-relative section with the lowest address // and use this address to calculate default _gp value. for (OutputSection *os : outputSections) { if (os->flags & SHF_MIPS_GPREL) { - ElfSym::mipsGp->section = os; - ElfSym::mipsGp->value = 0x7ff0; + ctx.sym.mipsGp->section = os; + ctx.sym.mipsGp->value = 0x7ff0; break; } } @@ -1725,7 +1725,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // value/section does not matter but it has to be relative, so set its // st_shndx arbitrarily to 1 (ctx.out.elfHeader). if (config->emachine == EM_RISCV) { - ElfSym::riscvGlobalPointer = nullptr; if (!config->shared) { OutputSection *sec = findSection(".sdata"); addOptionalRegular("__global_pointer$", sec ? sec : ctx.out.elfHeader, @@ -1735,7 +1734,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (config->relaxGP) { Symbol *s = symtab.find("__global_pointer$"); if (s && s->isDefined()) - ElfSym::riscvGlobalPointer = cast<Defined>(s); + ctx.sym.riscvGlobalPointer = cast<Defined>(s); } } } @@ -1757,7 +1756,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { s->resolve(Defined{ctx.internalFile, StringRef(), STB_GLOBAL, STV_HIDDEN, STT_TLS, /*value=*/0, 0, /*section=*/nullptr}); - ElfSym::tlsModuleBase = cast<Defined>(s); + ctx.sym.tlsModuleBase = cast<Defined>(s); } } _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits