[lld] bd16ffb - [ELF] Merge Symbol::needs* into uint16_t flags. NFC

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 9 14:37:25 PDT 2022


Author: Fangrui Song
Date: 2022-09-09T14:37:18-07:00
New Revision: bd16ffb38981478ab116f431e0e4057b676bfff5

URL: https://github.com/llvm/llvm-project/commit/bd16ffb38981478ab116f431e0e4057b676bfff5
DIFF: https://github.com/llvm/llvm-project/commit/bd16ffb38981478ab116f431e0e4057b676bfff5.diff

LOG: [ELF] Merge Symbol::needs* into uint16_t flags. NFC

Split off from D133003 ([ELF] Parallelize relocation scanning) to make its diff smaller.

Added: 
    

Modified: 
    lld/ELF/Arch/AArch64.cpp
    lld/ELF/MapFile.cpp
    lld/ELF/Relocations.cpp
    lld/ELF/Symbols.cpp
    lld/ELF/Symbols.h
    lld/ELF/SyntheticSections.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 4547924d10904..c521a96d978ea 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -856,11 +856,11 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
   };
   const uint8_t nopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop
 
-  // needsCopy indicates a non-ifunc canonical PLT entry whose address may
+  // NEEDS_COPY indicates a non-ifunc canonical PLT entry whose address may
   // escape to shared objects. isInIplt indicates a non-preemptible ifunc. Its
   // address may escape if referenced by a direct relocation. The condition is
   // conservative.
-  bool hasBti = btiHeader && (sym.needsCopy || sym.isInIplt);
+  bool hasBti = btiHeader && (sym.hasFlag(NEEDS_COPY) || sym.isInIplt);
   if (hasBti) {
     memcpy(buf, btiData, sizeof(btiData));
     buf += sizeof(btiData);

diff  --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp
index 893511929a3a5..ec1c90ee89949 100644
--- a/lld/ELF/MapFile.cpp
+++ b/lld/ELF/MapFile.cpp
@@ -59,7 +59,7 @@ static std::vector<Defined *> getSymbols() {
     for (Symbol *b : file->getSymbols())
       if (auto *dr = dyn_cast<Defined>(b))
         if (!dr->isSection() && dr->section && dr->section->isLive() &&
-            (dr->file == file || dr->needsCopy || dr->section->bss))
+            (dr->file == file || dr->hasFlag(NEEDS_COPY) || dr->section->bss))
           v.push_back(dr);
   return v;
 }

diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index cab39c663f0de..ce819de7eb5fe 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -306,7 +306,8 @@ static void replaceWithDefined(Symbol &sym, SectionBase &sec, uint64_t value,
   sym.exportDynamic = true;
   sym.isUsedInRegularObj = true;
   // A copy relocated alias may need a GOT entry.
-  sym.needsGot = old.needsGot;
+  if (old.hasFlag(NEEDS_GOT))
+    sym.setFlags(NEEDS_GOT);
 }
 
 // Reserve space in .bss or .bss.rel.ro for copy relocation.
@@ -1100,7 +1101,7 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
                 " against symbol '" + toString(*ss) +
                 "'; recompile with -fPIC or remove '-z nocopyreloc'" +
                 getLocation(*sec, sym, offset));
-        sym.needsCopy = true;
+        sym.setFlags(NEEDS_COPY);
       }
       sec->relocations.push_back({expr, type, offset, addend, &sym});
       return;
@@ -1138,8 +1139,7 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
         errorOrWarn("symbol '" + toString(sym) +
                     "' cannot be preempted; recompile with -fPIE" +
                     getLocation(*sec, sym, offset));
-      sym.needsCopy = true;
-      sym.needsPlt = true;
+      sym.setFlags(NEEDS_COPY | NEEDS_PLT);
       sec->relocations.push_back({expr, type, offset, addend, &sym});
       return;
     }
@@ -1193,7 +1193,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
             R_TLSDESC_GOTPLT>(expr) &&
       config->shared) {
     if (expr != R_TLSDESC_CALL) {
-      sym.needsTlsDesc = true;
+      sym.setFlags(NEEDS_TLSDESC);
       c.relocations.push_back({expr, type, offset, addend, &sym});
     }
     return 1;
@@ -1247,7 +1247,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
   // Local-Dynamic sequence where offset of tls variable relative to dynamic
   // thread pointer is stored in the got. This cannot be relaxed to Local-Exec.
   if (expr == R_TLSLD_GOT_OFF) {
-    sym.needsGotDtprel = true;
+    sym.setFlags(NEEDS_GOT_DTPREL);
     c.relocations.push_back({expr, type, offset, addend, &sym});
     return 1;
   }
@@ -1255,7 +1255,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
   if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
             R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC>(expr)) {
     if (!toExecRelax) {
-      sym.needsTlsGd = true;
+      sym.setFlags(NEEDS_TLSGD);
       c.relocations.push_back({expr, type, offset, addend, &sym});
       return 1;
     }
@@ -1263,7 +1263,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
     // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec
     // depending on the symbol being locally defined or not.
     if (sym.isPreemptible) {
-      sym.needsTlsGdToIe = true;
+      sym.setFlags(NEEDS_TLSGD_TO_IE);
       c.relocations.push_back(
           {target->adjustTlsExpr(type, R_RELAX_TLS_GD_TO_IE), type, offset,
            addend, &sym});
@@ -1283,7 +1283,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
       c.relocations.push_back(
           {R_RELAX_TLS_IE_TO_LE, type, offset, addend, &sym});
     } else if (expr != R_TLSIE_HINT) {
-      sym.needsTlsIe = true;
+      sym.setFlags(NEEDS_TLSIE);
       // R_GOT needs a relative relocation for PIC on i386 and Hexagon.
       if (expr == R_GOT && config->isPic && !target->usesOnlyLowPageBits(type))
         addRelativeReloc(c, offset, sym, addend, expr, type);
@@ -1438,12 +1438,12 @@ template <class ELFT, class RelTy> void RelocationScanner::scanOne(RelTy *&i) {
       // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
       in.mipsGot->addEntry(*sec->file, sym, addend, expr);
     } else {
-      sym.needsGot = true;
+      sym.setFlags(NEEDS_GOT);
     }
   } else if (needsPlt(expr)) {
-    sym.needsPlt = true;
+    sym.setFlags(NEEDS_PLT);
   } else if (LLVM_UNLIKELY(isIfunc)) {
-    sym.hasDirectReloc = true;
+    sym.setFlags(HAS_DIRECT_RELOC);
   }
 
   processAux(expr, type, offset, sym, addend);
@@ -1543,7 +1543,7 @@ template <class ELFT> void elf::scanRelocations() {
   }
 }
 
-static bool handleNonPreemptibleIfunc(Symbol &sym) {
+static bool handleNonPreemptibleIfunc(Symbol &sym, uint16_t flags) {
   // Handle a reference to a non-preemptible ifunc. These are special in a
   // few ways:
   //
@@ -1587,7 +1587,7 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) {
   if (!sym.isGnuIFunc() || sym.isPreemptible || config->zIfuncNoplt)
     return false;
   // Skip unreferenced non-preemptible ifunc.
-  if (!(sym.needsGot || sym.needsPlt || sym.hasDirectReloc))
+  if (!(flags & (NEEDS_GOT | NEEDS_PLT | HAS_DIRECT_RELOC)))
     return true;
 
   sym.isInIplt = true;
@@ -1603,7 +1603,7 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) {
   sym.allocateAux();
   symAux.back().pltIdx = symAux[directSym->auxIdx].pltIdx;
 
-  if (sym.hasDirectReloc) {
+  if (flags & HAS_DIRECT_RELOC) {
     // Change the value to the IPLT and redirect all references to it.
     auto &d = cast<Defined>(sym);
     d.section = in.iplt.get();
@@ -1613,9 +1613,9 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) {
     // don't try to call the PLT as if it were an ifunc resolver.
     d.type = STT_FUNC;
 
-    if (sym.needsGot)
+    if (flags & NEEDS_GOT)
       addGotEntry(sym);
-  } else if (sym.needsGot) {
+  } else if (flags & NEEDS_GOT) {
     // Redirect GOT accesses to point to the Igot.
     sym.gotInIgot = true;
   }
@@ -1624,30 +1624,31 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) {
 
 void elf::postScanRelocations() {
   auto fn = [](Symbol &sym) {
-    if (handleNonPreemptibleIfunc(sym))
+    auto flags = sym.flags;
+    if (handleNonPreemptibleIfunc(sym, flags))
       return;
     if (!sym.needsDynReloc())
       return;
     sym.allocateAux();
 
-    if (sym.needsGot)
+    if (flags & NEEDS_GOT)
       addGotEntry(sym);
-    if (sym.needsPlt)
+    if (flags & NEEDS_PLT)
       addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel, sym);
-    if (sym.needsCopy) {
+    if (flags & NEEDS_COPY) {
       if (sym.isObject()) {
         invokeELFT(addCopyRelSymbol, cast<SharedSymbol>(sym));
-        // needsCopy is cleared for sym and its aliases so that in later
-        // iterations aliases won't cause redundant copies.
-        assert(!sym.needsCopy);
+        // NEEDS_COPY is cleared for sym and its aliases so that in
+        // later iterations aliases won't cause redundant copies.
+        assert(!sym.hasFlag(NEEDS_COPY));
       } else {
-        assert(sym.isFunc() && sym.needsPlt);
+        assert(sym.isFunc() && sym.hasFlag(NEEDS_PLT));
         if (!sym.isDefined()) {
           replaceWithDefined(sym, *in.plt,
                              target->pltHeaderSize +
                                  target->pltEntrySize * sym.getPltIdx(),
                              0);
-          sym.needsCopy = true;
+          sym.setFlags(NEEDS_COPY);
           if (config->emachine == EM_PPC) {
             // PPC32 canonical PLT entries are at the beginning of .glink
             cast<Defined>(sym).value = in.plt->headerSize;
@@ -1662,13 +1663,13 @@ void elf::postScanRelocations() {
       return;
     bool isLocalInExecutable = !sym.isPreemptible && !config->shared;
 
-    if (sym.needsTlsDesc) {
+    if (flags & NEEDS_TLSDESC) {
       in.got->addTlsDescEntry(sym);
       mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
           target->tlsDescRel, *in.got, in.got->getTlsDescOffset(sym), sym,
           target->tlsDescRel);
     }
-    if (sym.needsTlsGd) {
+    if (flags & NEEDS_TLSGD) {
       in.got->addDynTlsEntry(sym);
       uint64_t off = in.got->getGlobalDynOffset(sym);
       if (isLocalInExecutable)
@@ -1689,18 +1690,18 @@ void elf::postScanRelocations() {
         in.got->relocations.push_back(
             {R_ABS, target->tlsOffsetRel, offsetOff, 0, &sym});
     }
-    if (sym.needsTlsGdToIe) {
+    if (flags & NEEDS_TLSGD_TO_IE) {
       in.got->addEntry(sym);
       mainPart->relaDyn->addSymbolReloc(target->tlsGotRel, *in.got,
                                         sym.getGotOffset(), sym);
     }
-    if (sym.needsGotDtprel) {
+    if (flags & NEEDS_GOT_DTPREL) {
       in.got->addEntry(sym);
       in.got->relocations.push_back(
           {R_ABS, target->tlsOffsetRel, sym.getGotOffset(), 0, &sym});
     }
 
-    if (sym.needsTlsIe && !sym.needsTlsGdToIe)
+    if ((flags & NEEDS_TLSIE) && !(flags & NEEDS_TLSGD_TO_IE))
       addTpOffsetGotEntry(sym);
   };
 

diff  --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 1eb482e690c51..787223bde20c2 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -122,7 +122,7 @@ static uint64_t getSymVA(const Symbol &sym, int64_t addend) {
     // field etc) do the same trick as compiler uses to mark microMIPS
     // for CPU - set the less-significant bit.
     if (config->emachine == EM_MIPS && isMicroMips() &&
-        ((sym.stOther & STO_MIPS_MICROMIPS) || sym.needsCopy))
+        ((sym.stOther & STO_MIPS_MICROMIPS) || sym.hasFlag(NEEDS_COPY)))
       va |= 1;
 
     if (d.isTls() && !config->relocatable) {

diff  --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 78a94a64b8be8..1c0a5f58d1cc9 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -39,6 +39,20 @@ class Undefined;
 class LazyObject;
 class InputFile;
 
+enum {
+  NEEDS_GOT = 1 << 0,
+  NEEDS_PLT = 1 << 1,
+  HAS_DIRECT_RELOC = 1 << 2,
+  // True if this symbol needs a canonical PLT entry, or (during
+  // postScanRelocations) a copy relocation.
+  NEEDS_COPY = 1 << 3,
+  NEEDS_TLSDESC = 1 << 4,
+  NEEDS_TLSGD = 1 << 5,
+  NEEDS_TLSGD_TO_IE = 1 << 6,
+  NEEDS_GOT_DTPREL = 1 << 7,
+  NEEDS_TLSIE = 1 << 8,
+};
+
 // Some index properties of a symbol are stored separately in this auxiliary
 // struct to decrease sizeof(SymbolUnion) in the majority of cases.
 struct SymbolAux {
@@ -252,10 +266,7 @@ class Symbol {
         inDynamicList(false), referenced(false), referencedAfterWrap(false),
         traced(false), hasVersionSuffix(false), isInIplt(false),
         gotInIgot(false), folded(false), needsTocRestore(false),
-        scriptDefined(false), dsoProtected(false), needsCopy(false),
-        needsGot(false), needsPlt(false), needsTlsDesc(false),
-        needsTlsGd(false), needsTlsGdToIe(false), needsGotDtprel(false),
-        needsTlsIe(false), hasDirectReloc(false) {}
+        scriptDefined(false), dsoProtected(false) {}
 
 public:
   // True if this symbol is in the Iplt sub-section of the Plt and the Igot
@@ -282,20 +293,9 @@ class Symbol {
   // True if defined in a DSO as protected visibility.
   uint8_t dsoProtected : 1;
 
-  // True if this symbol needs a canonical PLT entry, or (during
-  // postScanRelocations) a copy relocation.
-  uint8_t needsCopy : 1;
-
   // Temporary flags used to communicate which symbol entries need PLT and GOT
   // entries during postScanRelocations();
-  uint8_t needsGot : 1;
-  uint8_t needsPlt : 1;
-  uint8_t needsTlsDesc : 1;
-  uint8_t needsTlsGd : 1;
-  uint8_t needsTlsGdToIe : 1;
-  uint8_t needsGotDtprel : 1;
-  uint8_t needsTlsIe : 1;
-  uint8_t hasDirectReloc : 1;
+  uint16_t flags = 0;
 
   // A symAux index used to access GOT/PLT entry indexes. This is allocated in
   // postScanRelocations().
@@ -308,9 +308,18 @@ class Symbol {
   // Version definition index.
   uint16_t versionId;
 
+  void setFlags(uint16_t bits) {
+    flags |= bits;
+  }
+  bool hasFlag(uint16_t bit) const {
+    assert(bit && (bit & (bit - 1)) == 0 && "bit must be a power of 2");
+    return flags & bit;
+  }
+
   bool needsDynReloc() const {
-    return needsCopy || needsGot || needsPlt || needsTlsDesc || needsTlsGd ||
-           needsTlsGdToIe || needsGotDtprel || needsTlsIe;
+    return flags &
+           (NEEDS_COPY | NEEDS_GOT | NEEDS_PLT | NEEDS_TLSDESC | NEEDS_TLSGD |
+            NEEDS_TLSGD_TO_IE | NEEDS_GOT_DTPREL | NEEDS_TLSIE);
   }
   void allocateAux() {
     assert(auxIdx == uint32_t(-1));

diff  --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 4af2de5493a38..afd4038da1a67 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2175,8 +2175,8 @@ static BssSection *getCommonSec(Symbol *sym) {
 }
 
 static uint32_t getSymSectionIndex(Symbol *sym) {
-  assert(!(sym->needsCopy && sym->isObject()));
-  if (!isa<Defined>(sym) || sym->needsCopy)
+  assert(!(sym->hasFlag(NEEDS_COPY) && sym->isObject()));
+  if (!isa<Defined>(sym) || sym->hasFlag(NEEDS_COPY))
     return SHN_UNDEF;
   if (const OutputSection *os = sym->getOutputSection())
     return os->sectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX
@@ -2236,7 +2236,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
 
     for (SymbolTableEntry &ent : symbols) {
       Symbol *sym = ent.sym;
-      if (sym->isInPlt() && sym->needsCopy)
+      if (sym->isInPlt() && sym->hasFlag(NEEDS_COPY))
         eSym->st_other |= STO_MIPS_PLT;
       if (isMicroMips()) {
         // We already set the less-significant bit for symbols
@@ -2247,7 +2247,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
         // like `objdump` will be able to deal with a correct
         // symbol position.
         if (sym->isDefined() &&
-            ((sym->stOther & STO_MIPS_MICROMIPS) || sym->needsCopy)) {
+            ((sym->stOther & STO_MIPS_MICROMIPS) || sym->hasFlag(NEEDS_COPY))) {
           if (!strTabSec.isDynamic())
             eSym->st_value &= ~1;
           eSym->st_other |= STO_MIPS_MICROMIPS;


        


More information about the llvm-commits mailing list