[lld] 37a1291 - [ELF] Add RelocationScanner. NFC
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 11 09:54:58 PST 2022
Author: Fangrui Song
Date: 2022-01-11T09:54:53-08:00
New Revision: 37a1291885c1056721f20cf63dd2df42bb9a0574
URL: https://github.com/llvm/llvm-project/commit/37a1291885c1056721f20cf63dd2df42bb9a0574
DIFF: https://github.com/llvm/llvm-project/commit/37a1291885c1056721f20cf63dd2df42bb9a0574.diff
LOG: [ELF] Add RelocationScanner. NFC
Currently the way some relocation-related static functions pass around
states is clumsy. Add a Resolver class to store some states as member
variables.
Advantages:
* Avoid the parameter `InputSectionBase &sec` (this offsets the cost passing around `this` paramemter)
* Avoid the parameter `end` (Mips and PowerPC hacks)
* `config` and `target` can be cached as member variables to reduce global state accesses. (potential speedup because the compiler didn't know `config`/`target` were not changed across function calls)
* If we ever want to reduce if-else costs (e.g. `config->emachine==EM_MIPS` for non-Mips) or introduce parallel relocation scan not handling some tricky arches (PPC/Mips), we can templatize Resolver
`target` isn't used as much as `config`, so I change it to a const reference
during the migration.
There is a minor performance inprovement for elf::scanRelocations.
Reviewed By: ikudrin, peter.smith
Differential Revision: https://reviews.llvm.org/D116881
Added:
Modified:
lld/ELF/Relocations.cpp
Removed:
################################################################################
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index c3161a793a420..6e336822279cf 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -447,6 +447,36 @@ class OffsetGetter {
ArrayRef<EhSectionPiece> 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 <class ELFT, class RelTy> void scan(ArrayRef<RelTy> rels);
+
+private:
+ InputSectionBase &sec;
+ OffsetGetter getter;
+ const Configuration *const config;
+ const TargetInfo ⌖
+
+ // End of relocations, used by Mips/PPC64.
+ const void *end = nullptr;
+
+ template <class RelTy> RelType getMipsN32RelType(RelTy *&rel) const;
+ template <class ELFT, class RelTy>
+ int64_t computeMipsAddend(const RelTy &rel, RelExpr expr, bool isLocal) const;
+ template <class ELFT, class RelTy>
+ 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 <class ELFT, class RelTy> void scanOne(RelTy *&i);
+};
} // namespace
// MIPS has an odd notion of "paired" relocations to calculate addends.
@@ -454,9 +484,8 @@ class OffsetGetter {
// R_MIPS_LO16 relocation after that, and an addend is calculated using
// the two relocations.
template <class ELFT, class RelTy>
-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<ELFT>()->mipsGp0;
@@ -475,10 +504,10 @@ static int64_t computeMipsAddend(const RelTy &rel, const RelTy *end,
// 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<const RelTy *>(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 @@ static int64_t computeMipsAddend(const RelTy &rel, const RelTy *end,
// is in a relocation itself. If it is REL, we need to read it from an
// input section.
template <class ELFT, class RelTy>
-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 @@ static int64_t computeAddend(const RelTy &rel, const RelTy *end,
addend = getAddend<ELFT>(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<ELFT>(rel, end, sec, expr, isLocal);
+ addend += computeMipsAddend<ELFT>(rel, expr, isLocal);
return addend;
}
@@ -822,12 +850,13 @@ static bool maybeReportUndefined(Symbol &sym, InputSectionBase &sec,
// 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 <class RelTy> static RelType getMipsN32RelType(RelTy *&rel, RelTy *end) {
+template <class RelTy>
+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<const RelTy *>(end) && rel->r_offset == offset)
type |= (rel++)->getType(config->isMips64EL) << (8 * n++);
return type;
}
@@ -923,8 +952,9 @@ static bool canDefineSymbolInExecutable(Symbol &sym) {
//
// 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 (oneof<R_GOTPLT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL,
R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
@@ -936,7 +966,7 @@ static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym,
// These never do, except if the entire file is position dependent or if
// only the low bits are used.
if (e == R_GOT || e == R_PLT)
- return target->usesOnlyLowPageBits(type) || !config->isPic;
+ return target.usesOnlyLowPageBits(type) || !config->isPic;
if (sym.isPreemptible)
return false;
@@ -956,7 +986,7 @@ static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym,
if (!absVal && relE)
return true;
if (!absVal && !relE)
- return target->usesOnlyLowPageBits(type);
+ return target.usesOnlyLowPageBits(type);
assert(absVal && relE);
@@ -974,7 +1004,7 @@ static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym,
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 @@ static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym,
// 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 <class ELFT>
-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 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
// -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 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
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 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
return 0;
}
-template <class ELFT, class RelTy>
-static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
- RelTy *end) {
+template <class ELFT, class RelTy> void RelocationScanner::scanOne(RelTy *&i) {
const RelTy &rel = *i;
uint32_t symIndex = rel.getSymbol(config->isMips64EL);
Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIndex);
@@ -1270,14 +1297,14 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
// 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 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
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<ELFT>(rel, end, sec, expr, sym.isLocal());
+ int64_t addend = computeAddend<ELFT>(rel, expr, sym.isLocal());
if (config->emachine == EM_PPC64) {
// We can separate the small code model relocations into 2 categories:
@@ -1344,7 +1371,7 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
}
// 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 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
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 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
sym.hasDirectReloc = true;
}
- processRelocAux<ELFT>(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 @@ static void checkPPC64TLSRelax(InputSectionBase &sec, ArrayRef<RelTy> rels) {
}
template <class ELFT, class RelTy>
-static void scanRelocs(InputSectionBase &sec, ArrayRef<RelTy> rels) {
- OffsetGetter getOffset(sec);
-
+void RelocationScanner::scan(ArrayRef<RelTy> rels) {
// Not all relocations end up in Sec.Relocations, but a lot do.
sec.relocations.reserve(rels.size());
@@ -1468,8 +1493,9 @@ static void scanRelocs(InputSectionBase &sec, ArrayRef<RelTy> rels) {
if (isa<EhInputSection>(sec))
rels = sortRels(rels, storage);
- for (auto i = rels.begin(), end = rels.end(); i != end;)
- scanReloc<ELFT>(sec, getOffset, i, end);
+ end = static_cast<const void *>(rels.end());
+ for (auto i = rels.begin(); i != end;)
+ scanOne<ELFT>(i);
// Sort relocations by offset for more efficient searching for
// R_RISCV_PCREL_HI20 and R_PPC64_ADDR64.
@@ -1482,11 +1508,12 @@ static void scanRelocs(InputSectionBase &sec, ArrayRef<RelTy> rels) {
}
template <class ELFT> void elf::scanRelocations(InputSectionBase &s) {
+ RelocationScanner scanner(s);
const RelsOrRelas<ELFT> rels = s.template relsOrRelas<ELFT>();
if (rels.areRelocsRel())
- scanRelocs<ELFT>(s, rels.rels);
+ scanner.template scan<ELFT>(rels.rels);
else
- scanRelocs<ELFT>(s, rels.relas);
+ scanner.template scan<ELFT>(rels.relas);
}
static bool handleNonPreemptibleIfunc(Symbol &sym) {
More information about the llvm-commits
mailing list