diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -560,7 +560,7 @@ if (!sec) return; for (const DynamicReloc &rel : sec->relocs) { - int64_t addend = rel.computeAddend(); + int64_t addend = rel.addend; const OutputSection *relOsec = rel.inputSec->getOutputSection(); assert(relOsec != nullptr && "missing output section for relocation"); const uint8_t *relocTarget = diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -425,7 +425,7 @@ class DynamicReloc { public: - enum Kind { + enum Kind : uint8_t { /// The resulting dynamic relocation does not reference a symbol (#sym must /// be nullptr) and uses #addend as the result of computeAddend(). AddendOnly, @@ -449,21 +449,21 @@ DynamicReloc(RelType type, const InputSectionBase *inputSec, 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) {} + : sym(&sym), inputSec(inputSec), offsetInSec(offsetInSec), type(type), + addend(addend), kind(kind), expr(expr) {} /// 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) {} + : 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) - : type(type), sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec), - kind(MipsMultiGotPage), expr(R_ADDEND), addend(addend), - outputSec(outputSec) {} + : sym(nullptr), outputSec(outputSec), inputSec(inputSec), + offsetInSec(offsetInSec), type(type), addend(addend), + kind(MipsMultiGotPage), expr(R_ADDEND) {} uint64_t getOffset() const; uint32_t getSymIndex(SymbolTableBaseSection *symTab) const; @@ -476,18 +476,22 @@ /// address/the address of the corresponding GOT entry/etc. int64_t computeAddend() const; + Symbol *sym; + const OutputSection *outputSec = nullptr; + const InputSectionBase *inputSec; + uint64_t offsetInSec; + uint64_t r_offset; + uint32_t r_sym; RelType type; - Symbol *sym; - const InputSectionBase *inputSec; - uint64_t offsetInSec; + // Initially input addend, then the output addend after + // RelocationSection::writeTo. + int64_t addend; 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 = nullptr; }; template class DynamicSection final : public SyntheticSection { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1653,13 +1653,12 @@ config->wordsize, ".relr.dyn") {} template -static void encodeDynamicReloc(SymbolTableBaseSection *symTab, - typename ELFT::Rela *p, +static void encodeDynamicReloc(typename ELFT::Rela *p, const DynamicReloc &rel) { + p->r_offset = rel.r_offset; + p->setSymbolAndType(rel.r_sym, rel.type, config->isMips64EL); if (config->isRela) - p->r_addend = rel.computeAddend(); - p->r_offset = rel.getOffset(); - p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL); + p->r_addend = rel.addend; } template @@ -1674,20 +1673,24 @@ template void RelocationSection::writeTo(uint8_t *buf) { SymbolTableBaseSection *symTab = getPartition().dynSymTab; + parallelForEach(relocs, [symTab](DynamicReloc &rel) { + rel.addend = rel.computeAddend(); + rel.r_offset = rel.getOffset(); + rel.r_sym = rel.getSymIndex(symTab); + }); // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset // is to make results easier to read. - if (sort) - parallelSort( - relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { - return std::make_tuple(a.type != target->relativeRel, - a.getSymIndex(symTab), a.getOffset()) < - std::make_tuple(b.type != target->relativeRel, - b.getSymIndex(symTab), b.getOffset()); - }); + if (sort) { + const RelType relativeRel = target->relativeRel; + parallelSort(relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { + return std::make_tuple(a.type != relativeRel, a.r_sym, a.r_offset) < + std::make_tuple(b.type != relativeRel, b.r_sym, b.r_offset); + }); + } for (const DynamicReloc &rel : relocs) { - encodeDynamicReloc(symTab, reinterpret_cast(buf), rel); + encodeDynamicReloc(reinterpret_cast(buf), rel); buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } } @@ -1765,7 +1768,11 @@ for (const DynamicReloc &rel : relocs) { Elf_Rela r; - encodeDynamicReloc(getPartition().dynSymTab, &r, rel); + r.r_offset = rel.getOffset(); + r.setSymbolAndType(rel.getSymIndex(getPartition().dynSymTab), rel.type, + false); + if (config->isRela) + r.r_addend = rel.computeAddend(); if (r.getType(config->isMips64EL) == target->relativeRel) relatives.push_back(r);