diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -447,6 +447,36 @@ ArrayRef pieces; size_t i = 0; }; + +// This class encapsulates states needed to scan relocations for one +// InputSectionBase. +class RelocationScanner { +public: + explicit RelocationScanner(InputSectionBase &sec) + : sec(sec), getter(sec), config(elf::config.get()), target(*elf::target) { + } + template void scan(ArrayRef rels); + +private: + InputSectionBase &sec; + OffsetGetter getter; + const Configuration *const config; + const TargetInfo ⌖ + + // End of relocations, used by Mips/PPC64. + const void *end = nullptr; + + template RelType getMipsN32RelType(RelTy *&rel) const; + template + int64_t computeMipsAddend(const RelTy &rel, RelExpr expr, bool isLocal) const; + template + int64_t computeAddend(const RelTy &rel, RelExpr expr, bool isLocal) const; + bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym, + uint64_t relOff) const; + void processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, + int64_t addend) const; + template void scanOne(RelTy *&i); +}; } // namespace // MIPS has an odd notion of "paired" relocations to calculate addends. @@ -454,9 +484,8 @@ // R_MIPS_LO16 relocation after that, and an addend is calculated using // the two relocations. template -static int64_t computeMipsAddend(const RelTy &rel, const RelTy *end, - InputSectionBase &sec, RelExpr expr, - bool isLocal) { +int64_t RelocationScanner::computeMipsAddend(const RelTy &rel, RelExpr expr, + bool isLocal) const { if (expr == R_MIPS_GOTREL && isLocal) return sec.getFile()->mipsGp0; @@ -475,10 +504,10 @@ // To make things worse, paired relocations might not be contiguous in // the relocation table, so we need to do linear search. *sigh* - for (const RelTy *ri = &rel; ri != end; ++ri) + for (const RelTy *ri = &rel; ri != static_cast(end); ++ri) if (ri->getType(config->isMips64EL) == pairTy && ri->getSymbol(config->isMips64EL) == symIndex) - return target->getImplicitAddend(buf + ri->r_offset, pairTy); + return target.getImplicitAddend(buf + ri->r_offset, pairTy); warn("can't find matching " + toString(pairTy) + " relocation for " + toString(type)); @@ -489,9 +518,8 @@ // is in a relocation itself. If it is REL, we need to read it from an // input section. template -static int64_t computeAddend(const RelTy &rel, const RelTy *end, - InputSectionBase &sec, RelExpr expr, - bool isLocal) { +int64_t RelocationScanner::computeAddend(const RelTy &rel, RelExpr expr, + bool isLocal) const { int64_t addend; RelType type = rel.getType(config->isMips64EL); @@ -499,13 +527,13 @@ addend = getAddend(rel); } else { const uint8_t *buf = sec.data().data(); - addend = target->getImplicitAddend(buf + rel.r_offset, type); + addend = target.getImplicitAddend(buf + rel.r_offset, type); } if (config->emachine == EM_PPC64 && config->isPic && type == R_PPC64_TOC) addend += getPPC64TocBase(); if (config->emachine == EM_MIPS) - addend += computeMipsAddend(rel, end, sec, expr, isLocal); + addend += computeMipsAddend(rel, expr, isLocal); return addend; } @@ -822,12 +850,13 @@ // packs all relocations into the single relocation record. Here we emulate // this for the N32 ABI. Iterate over relocation with the same offset and put // theirs types into the single bit-set. -template static RelType getMipsN32RelType(RelTy *&rel, RelTy *end) { +template +RelType RelocationScanner::getMipsN32RelType(RelTy *&rel) const { RelType type = 0; uint64_t offset = rel->r_offset; int n = 0; - while (rel != end && rel->r_offset == offset) + while (rel != static_cast(end) && rel->r_offset == offset) type |= (rel++)->getType(config->isMips64EL) << (8 * n++); return type; } @@ -923,8 +952,9 @@ // // If this function returns false, that means we need to emit a // dynamic relocation so that the relocation will be fixed at load-time. -static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym, - InputSectionBase &s, uint64_t relOff) { +bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type, + const Symbol &sym, + uint64_t relOff) const { // These expressions always compute a constant if (oneofusesOnlyLowPageBits(type) || !config->isPic; + return target.usesOnlyLowPageBits(type) || !config->isPic; if (sym.isPreemptible) return false; @@ -956,7 +986,7 @@ if (!absVal && relE) return true; if (!absVal && !relE) - return target->usesOnlyLowPageBits(type); + return target.usesOnlyLowPageBits(type); assert(absVal && relE); @@ -974,7 +1004,7 @@ return true; error("relocation " + toString(type) + " cannot refer to absolute symbol: " + - toString(sym) + getLocation(s, sym, relOff)); + toString(sym) + getLocation(sec, sym, relOff)); return true; } @@ -991,9 +1021,8 @@ // sections. Given that it is ro, we will need an extra PT_LOAD. This // complicates things for the dynamic linker and means we would have to reserve // space for the extra PT_LOAD even if we end up not using it. -template -static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type, - uint64_t offset, Symbol &sym, int64_t addend) { +void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, + Symbol &sym, int64_t addend) const { // If the relocation is known to be a link-time constant, we know no dynamic // relocation will be created, pass the control to relocateAlloc() or // relocateNonAlloc() to resolve it. @@ -1008,7 +1037,7 @@ // -shared matches the spirit of its -z undefs default. -pie has freedom on // choices, and we choose dynamic relocations to be consistent with the // handling of GOT-generating relocations. - if (isStaticLinkTimeConstant(expr, type, sym, sec, offset) || + if (isStaticLinkTimeConstant(expr, type, sym, offset) || (!config->isPic && sym.isUndefWeak())) { sec.relocations.push_back({expr, type, offset, addend, &sym}); return; @@ -1016,13 +1045,13 @@ bool canWrite = (sec.flags & SHF_WRITE) || !config->zText; if (canWrite) { - RelType rel = target->getDynRel(type); - if (expr == R_GOT || (rel == target->symbolicRel && !sym.isPreemptible)) { + RelType rel = target.getDynRel(type); + if (expr == R_GOT || (rel == target.symbolicRel && !sym.isPreemptible)) { addRelativeReloc(sec, offset, sym, addend, expr, type); return; } else if (rel != 0) { - if (config->emachine == EM_MIPS && rel == target->symbolicRel) - rel = target->relativeRel; + if (config->emachine == EM_MIPS && rel == target.symbolicRel) + rel = target.relativeRel; sec.getPartition().relaDyn->addSymbolReloc(rel, sec, offset, sym, addend, type); @@ -1260,9 +1289,7 @@ return 0; } -template -static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i, - RelTy *end) { +template void RelocationScanner::scanOne(RelTy *&i) { const RelTy &rel = *i; uint32_t symIndex = rel.getSymbol(config->isMips64EL); Symbol &sym = sec.getFile()->getSymbol(symIndex); @@ -1270,14 +1297,14 @@ // Deal with MIPS oddity. if (config->mipsN32Abi) { - type = getMipsN32RelType(i, end); + type = getMipsN32RelType(i); } else { type = rel.getType(config->isMips64EL); ++i; } // Get an offset in an output section this relocation is applied to. - uint64_t offset = getOffset.get(rel.r_offset); + uint64_t offset = getter.get(rel.r_offset); if (offset == uint64_t(-1)) return; @@ -1288,14 +1315,14 @@ return; const uint8_t *relocatedAddr = sec.data().begin() + rel.r_offset; - RelExpr expr = target->getRelExpr(type, sym, relocatedAddr); + RelExpr expr = target.getRelExpr(type, sym, relocatedAddr); // Ignore R_*_NONE and other marker relocations. if (expr == R_NONE) return; // Read an addend. - int64_t addend = computeAddend(rel, end, sec, expr, sym.isLocal()); + int64_t addend = computeAddend(rel, expr, sym.isLocal()); if (config->emachine == EM_PPC64) { // We can separate the small code model relocations into 2 categories: @@ -1344,7 +1371,7 @@ } // Process TLS relocations, including relaxing TLS relocations. Note that - // R_TPREL and R_TPREL_NEG relocations are resolved in processRelocAux. + // R_TPREL and R_TPREL_NEG relocations are resolved in processAux. if (expr == R_TPREL || expr == R_TPREL_NEG) { if (config->shared) { errorOrWarn("relocation " + toString(type) + " against " + toString(sym) + @@ -1380,7 +1407,7 @@ type == R_HEX_GD_PLT_B32_PCREL_X))) expr = fromPlt(expr); } else if (!isAbsoluteValue(sym)) { - expr = target->adjustGotPcExpr(type, addend, relocatedAddr); + expr = target.adjustGotPcExpr(type, addend, relocatedAddr); } } @@ -1411,7 +1438,7 @@ sym.hasDirectReloc = true; } - processRelocAux(sec, expr, type, offset, sym, addend); + processAux(expr, type, offset, sym, addend); } // R_PPC64_TLSGD/R_PPC64_TLSLD is required to mark `bl __tls_get_addr` for @@ -1452,9 +1479,7 @@ } template -static void scanRelocs(InputSectionBase &sec, ArrayRef rels) { - OffsetGetter getOffset(sec); - +void RelocationScanner::scan(ArrayRef rels) { // Not all relocations end up in Sec.Relocations, but a lot do. sec.relocations.reserve(rels.size()); @@ -1468,8 +1493,9 @@ if (isa(sec)) rels = sortRels(rels, storage); - for (auto i = rels.begin(), end = rels.end(); i != end;) - scanReloc(sec, getOffset, i, end); + end = static_cast(rels.end()); + for (auto i = rels.begin(); i != end;) + scanOne(i); // Sort relocations by offset for more efficient searching for // R_RISCV_PCREL_HI20 and R_PPC64_ADDR64. @@ -1482,11 +1508,12 @@ } template void elf::scanRelocations(InputSectionBase &s) { + RelocationScanner scanner(s); const RelsOrRelas rels = s.template relsOrRelas(); if (rels.areRelocsRel()) - scanRelocs(s, rels.rels); + scanner.template scan(rels.rels); else - scanRelocs(s, rels.relas); + scanner.template scan(rels.relas); } static bool handleNonPreemptibleIfunc(Symbol &sym) {