From 0171cdce2f11720a3349396d0673ff23fbe100ac Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Sun, 27 Jul 2025 02:17:36 +0100 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20change?= =?UTF-8?q?s=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.5 [skip ci] --- lld/ELF/Arch/Mips.cpp | 4 +++ lld/ELF/Config.h | 2 ++ lld/ELF/Driver.cpp | 1 + lld/ELF/InputSection.cpp | 5 ++++ lld/ELF/Relocations.cpp | 25 ++++++++++--------- lld/ELF/Relocations.h | 1 + lld/ELF/SyntheticSections.cpp | 42 ++++++++++++-------------------- lld/ELF/SyntheticSections.h | 46 +++++++++++++---------------------- lld/ELF/Target.cpp | 3 +-- lld/ELF/Target.h | 1 + lld/ELF/Writer.cpp | 3 +-- 11 files changed, 62 insertions(+), 71 deletions(-) diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp index 91c7f15ae1f1c..f88b021c8ba39 100644 --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -40,6 +40,10 @@ template class MIPS final : public TargetInfo { }; } // namespace +uint64_t elf::getMipsPageAddr(uint64_t addr) { + return (addr + 0x8000) & ~0xffff; +} + template MIPS::MIPS(Ctx &ctx) : TargetInfo(ctx) { gotPltHeaderEntriesNum = 2; defaultMaxPageSize = 65536; diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index d9639b06ca4bf..958e5caaf0dfa 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -701,6 +701,8 @@ struct Ctx : CommonLinkerContext { std::unique_ptr tar; // InputFile for linker created symbols with no source location. InputFile *internalFile = nullptr; + // Dummy Undefined for relocations without a symbol. + Undefined *dummySym = nullptr; // True if symbols can be exported (isExported) or preemptible. bool hasDynsym = false; // True if SHT_LLVM_SYMPART is used. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 21d228eda6470..4dcf577ebcb16 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -3138,6 +3138,7 @@ template void LinkerDriver::link(opt::InputArgList &args) { ctx.symtab->insert(arg->getValue())->traced = true; ctx.internalFile = createInternalFile(ctx, ""); + ctx.dummySym = make(ctx.internalFile, "", STB_LOCAL, 0, 0); // Handle -u/--undefined before input files. If both a.a and b.so define foo, // -u foo a.a b.so will extract a.a. diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 68e3feb1bd048..784ff7cc79912 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -861,6 +861,11 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, return ctx.in.mipsGot->getVA() + ctx.in.mipsGot->getPageEntryOffset(file, *r.sym, a) - ctx.in.mipsGot->getGp(file); + case RE_MIPS_OSEC_LOCAL_PAGE: + // This is used by the MIPS multi-GOT implementation. It relocates + // addresses of 64kb pages that lie inside the output section that sym is + // a representative for. + return getMipsPageAddr(r.sym->getOutputSection()->addr) + a; case RE_MIPS_GOT_OFF: case RE_MIPS_GOT_OFF32: // In case of MIPS if a GOT relocation has non-zero addend this addend diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index bd22fe2f1aa25..7579def5865bb 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -885,10 +885,12 @@ static void addPltEntry(Ctx &ctx, PltSection &plt, GotPltSection &gotPlt, RelocationBaseSection &rel, RelType type, Symbol &sym) { plt.addEntry(sym); gotPlt.addEntry(sym); - rel.addReloc({type, &gotPlt, sym.getGotPltOffset(ctx), - sym.isPreemptible ? DynamicReloc::AgainstSymbol - : DynamicReloc::AddendOnlyWithTargetVA, - sym, 0, R_ABS}); + if (sym.isPreemptible) + rel.addReloc({type, &gotPlt, sym.getGotPltOffset(ctx), + DynamicReloc::AgainstSymbol, sym, 0, R_ADDEND}); + else + rel.addReloc({type, &gotPlt, sym.getGotPltOffset(ctx), + DynamicReloc::AddendOnly, sym, 0, R_ABS}); } void elf::addGotEntry(Ctx &ctx, Symbol &sym) { @@ -899,7 +901,7 @@ void elf::addGotEntry(Ctx &ctx, Symbol &sym) { if (sym.isPreemptible) { ctx.mainPart->relaDyn->addReloc({ctx.target->gotRel, ctx.in.got.get(), off, DynamicReloc::AgainstSymbol, sym, 0, - R_ABS}); + R_ADDEND}); return; } @@ -921,14 +923,14 @@ static void addGotAuthEntry(Ctx &ctx, Symbol &sym) { if (sym.isPreemptible) { ctx.mainPart->relaDyn->addReloc({R_AARCH64_AUTH_GLOB_DAT, ctx.in.got.get(), off, DynamicReloc::AgainstSymbol, sym, 0, - R_ABS}); + R_ADDEND}); return; } // Signed GOT requires dynamic relocation. ctx.in.got->getPartition(ctx).relaDyn->addReloc( - {R_AARCH64_AUTH_RELATIVE, ctx.in.got.get(), off, - DynamicReloc::AddendOnlyWithTargetVA, sym, 0, R_ABS}); + {R_AARCH64_AUTH_RELATIVE, ctx.in.got.get(), off, DynamicReloc::AddendOnly, + sym, 0, R_ABS}); } static void addTpOffsetGotEntry(Ctx &ctx, Symbol &sym) { @@ -1160,8 +1162,8 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, part.relrAuthDyn->relocs.push_back({sec, sec->relocs().size() - 1}); } else { part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, - DynamicReloc::AddendOnlyWithTargetVA, sym, - addend, R_ABS}); + DynamicReloc::AddendOnly, sym, addend, + R_ABS}); } return; } @@ -1948,13 +1950,12 @@ void elf::postScanRelocations(Ctx &ctx) { GotSection *got = ctx.in.got.get(); if (ctx.needsTlsLd.load(std::memory_order_relaxed) && got->addTlsIndex()) { - static Undefined dummy(ctx.internalFile, "", STB_LOCAL, 0, 0); if (ctx.arg.shared) ctx.mainPart->relaDyn->addReloc( {ctx.target->tlsModuleIndexRel, got, got->getTlsIndexOff()}); else got->addConstant({R_ADDEND, ctx.target->symbolicRel, - got->getTlsIndexOff(), 1, &dummy}); + got->getTlsIndexOff(), 1, ctx.dummySym}); } assert(ctx.symAux.size() == 1); diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 02ddf707fd950..c1c4860ceaa92 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -110,6 +110,7 @@ enum RelExpr { RE_MIPS_GOT_LOCAL_PAGE, RE_MIPS_GOT_OFF, RE_MIPS_GOT_OFF32, + RE_MIPS_OSEC_LOCAL_PAGE, RE_MIPS_TLSGD, RE_MIPS_TLSLD, RE_PPC32_PLTREL, diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index efec41a737b62..0a8a52052c9c8 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -769,10 +769,6 @@ void GotSection::writeTo(uint8_t *buf) { } } -static uint64_t getMipsPageAddr(uint64_t addr) { - return (addr + 0x8000) & ~0xffff; -} - static uint64_t getMipsPageCount(uint64_t size) { return (size + 0xfffe) / 0xffff + 1; } @@ -786,7 +782,7 @@ void MipsGotSection::addEntry(InputFile &file, Symbol &sym, int64_t addend, FileGot &g = getGot(file); if (expr == RE_MIPS_GOT_LOCAL_PAGE) { if (const OutputSection *os = sym.getOutputSection()) - g.pagesMap.insert({os, {}}); + g.pagesMap.insert({os, {&sym}}); else g.local16.insert({{nullptr, getMipsPageAddr(sym.getVA(ctx, addend))}, 0}); } else if (sym.isTls()) @@ -1065,9 +1061,9 @@ void MipsGotSection::build() { // for the TP-relative offset as we don't know how much other data will // be allocated before us in the static TLS block. if (s->isPreemptible || ctx.arg.shared) - ctx.mainPart->relaDyn->addReloc( - {ctx.target->tlsGotRel, this, offset, - DynamicReloc::AgainstSymbolWithTargetVA, *s, 0, R_ABS}); + ctx.mainPart->relaDyn->addReloc({ctx.target->tlsGotRel, this, offset, + DynamicReloc::AgainstSymbol, *s, 0, + R_ABS}); } for (std::pair &p : got.dynTlsSymbols) { Symbol *s = p.first; @@ -1115,15 +1111,16 @@ void MipsGotSection::build() { size_t pageCount = l.second.count; for (size_t pi = 0; pi < pageCount; ++pi) { uint64_t offset = (l.second.firstIndex + pi) * ctx.arg.wordsize; - ctx.mainPart->relaDyn->addReloc({ctx.target->relativeRel, this, offset, - l.first, int64_t(pi * 0x10000)}); + ctx.mainPart->relaDyn->addReloc( + {ctx.target->relativeRel, this, offset, DynamicReloc::AddendOnly, + *l.second.repSym, int64_t(pi * 0x10000), RE_MIPS_OSEC_LOCAL_PAGE}); } } for (const std::pair &p : got.local16) { uint64_t offset = p.second * ctx.arg.wordsize; ctx.mainPart->relaDyn->addReloc({ctx.target->relativeRel, this, offset, - DynamicReloc::AddendOnlyWithTargetVA, - *p.first.first, p.first.second, R_ABS}); + DynamicReloc::AddendOnly, *p.first.first, + p.first.second, R_ABS}); } } } @@ -1647,21 +1644,14 @@ uint64_t DynamicReloc::getOffset() const { int64_t DynamicReloc::computeAddend(Ctx &ctx) const { switch (kind) { + case Computed: + llvm_unreachable("addend already computed"); case AddendOnly: - assert(sym == nullptr); - return addend; - case AgainstSymbol: - assert(sym != nullptr); - return addend; - case AddendOnlyWithTargetVA: - case AgainstSymbolWithTargetVA: { + case AgainstSymbol: { uint64_t ca = inputSec->getRelocTargetVA( ctx, Relocation{expr, type, 0, addend, sym}, getOffset()); return ctx.arg.is64 ? ca : SignExtend64<32>(ca); } - case MipsMultiGotPage: - assert(sym == nullptr); - return getMipsPageAddr(outputSec->addr) + addend; } llvm_unreachable("Unknown DynamicReloc::Kind enum"); } @@ -1701,10 +1691,10 @@ void RelocationBaseSection::addAddendOnlyRelocIfNonPreemptible( // No need to write an addend to the section for preemptible symbols. if (sym.isPreemptible) addReloc({dynType, &isec, offsetInSec, DynamicReloc::AgainstSymbol, sym, 0, - R_ABS}); + R_ADDEND}); else - addReloc(DynamicReloc::AddendOnlyWithTargetVA, dynType, isec, offsetInSec, - sym, 0, R_ABS, addendRelType); + addReloc(DynamicReloc::AddendOnly, dynType, isec, offsetInSec, sym, 0, + R_ABS, addendRelType); } void RelocationBaseSection::mergeRels() { @@ -1748,7 +1738,7 @@ void DynamicReloc::computeRaw(Ctx &ctx, SymbolTableBaseSection *symt) { r_offset = getOffset(); r_sym = getSymIndex(symt); addend = computeAddend(ctx); - kind = AddendOnly; // Catch errors + kind = Computed; // Catch errors } void RelocationBaseSection::computeRels() { diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 5f01513630597..2e7a3c3bc96d2 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -327,9 +327,11 @@ class MipsGotSection final : public SyntheticSection { size_t startIndex = 0; struct PageBlock { + Symbol *repSym; // Representative symbol for the OutputSection size_t firstIndex; size_t count; - PageBlock() : firstIndex(0), count(0) {} + PageBlock(Symbol *repSym = nullptr) + : repSym(repSym), firstIndex(0), count(0) {} }; // Map output sections referenced by MIPS GOT relocations @@ -419,26 +421,19 @@ class StringTableSection final : public SyntheticSection { 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(ctx). - AddendOnly, + /// The resulting dynamic relocation has already had its addend computed. + /// Calling computeAddend() is an error. Only for internal use. + Computed, /// 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, + AddendOnly, /// The resulting dynamic relocation references symbol #sym from the dynamic - /// symbol table and uses #addend as the value of computeAddend(ctx). + /// symbol table and uses InputSection::getRelocTargetVA() for the final + /// addend. 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. + /// This constructor records a normal relocation. DynamicReloc(RelType type, const InputSectionBase *inputSec, uint64_t offsetInSec, Kind kind, Symbol &sym, int64_t addend, RelExpr expr) @@ -447,21 +442,15 @@ class DynamicReloc { /// This constructor records a relative relocation with no symbol. DynamicReloc(RelType type, const InputSectionBase *inputSec, uint64_t offsetInSec, int64_t addend = 0) - : sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec), type(type), - addend(addend), kind(AddendOnly), expr(R_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) - : sym(nullptr), outputSec(outputSec), inputSec(inputSec), - offsetInSec(offsetInSec), type(type), addend(addend), - kind(MipsMultiGotPage), expr(R_ADDEND) {} + : sym(inputSec->getCtx().dummySym), inputSec(inputSec), + offsetInSec(offsetInSec), type(type), addend(addend), kind(AddendOnly), + expr(R_ADDEND) {} uint64_t getOffset() const; uint32_t getSymIndex(SymbolTableBaseSection *symTab) const; bool needsDynSymIndex() const { - return kind == AgainstSymbol || kind == AgainstSymbolWithTargetVA; + assert(kind != Computed && "cannot check kind after computeRaw"); + return kind == AgainstSymbol; } /// Computes the addend of the dynamic relocation. Note that this is not the @@ -472,7 +461,6 @@ class DynamicReloc { void computeRaw(Ctx &, SymbolTableBaseSection *symt); Symbol *sym; - const OutputSection *outputSec = nullptr; const InputSectionBase *inputSec; uint64_t offsetInSec; uint64_t r_offset; @@ -528,8 +516,8 @@ class RelocationBaseSection : public SyntheticSection { uint64_t offsetInSec, Symbol &sym, int64_t addend, RelType addendRelType, RelExpr expr) { assert(expr != R_ADDEND && "expected non-addend relocation expression"); - addReloc(DynamicReloc::AddendOnlyWithTargetVA, dynType, isec, - offsetInSec, sym, addend, expr, addendRelType); + addReloc(DynamicReloc::AddendOnly, dynType, isec, offsetInSec, sym, + addend, expr, addendRelType); } /// 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. diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index ad7d57d30668d..4946484074d05 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -105,10 +105,9 @@ ErrorPlace elf::getErrorPlace(Ctx &ctx, const uint8_t *loc) { if (isecLoc <= loc && loc < isecLoc + isec->getSize()) { std::string objLoc = isec->getLocation(loc - isecLoc); // Return object file location and source file location. - Undefined dummy(ctx.internalFile, "", STB_LOCAL, 0, 0); ELFSyncStream msg(ctx, DiagLevel::None); if (isec->file) - msg << isec->getSrcMsg(dummy, loc - isecLoc); + msg << isec->getSrcMsg(*ctx.dummySym, loc - isecLoc); return {isec, objLoc + ": ", std::string(msg.str())}; } } diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 93f15920bfedb..ceb23b3dc2b68 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -214,6 +214,7 @@ void processArmCmseSymbols(Ctx &); template uint32_t calcMipsEFlags(Ctx &); uint8_t getMipsFpAbiFlag(Ctx &, InputFile *file, uint8_t oldFlag, uint8_t newFlag); +uint64_t getMipsPageAddr(uint64_t addr); bool isMipsN32Abi(Ctx &, const InputFile &f); bool isMicroMips(Ctx &); bool isMipsR6(Ctx &); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 15909daf51ab6..3e66ce074fcdf 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1573,8 +1573,7 @@ template void Writer::finalizeAddressDependentContent() { if (isInt<32>(reloc.sym->getVA(ctx, reloc.addend))) return false; part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, elem.inputSec, - reloc.offset, - DynamicReloc::AddendOnlyWithTargetVA, + reloc.offset, DynamicReloc::AddendOnly, *reloc.sym, reloc.addend, R_ABS}); return true; });