[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