[lld] 3733ed6 - [ELF] Introduce Symbol::isExported to cache includeInDynsym

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 8 22:40:19 PST 2024


Author: Fangrui Song
Date: 2024-12-08T22:40:14-08:00
New Revision: 3733ed6f1c6b0eef1e13e175ac81ad309fc0b080

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

LOG: [ELF] Introduce Symbol::isExported to cache includeInDynsym

isExported, intended to replace exportDynamic, is primarily set in two
locations, (a) after parseSymbolVersion and (b) during demoteSymbols.

In the future, we should try removing exportDynamic. Currently,
merging exportDynamic/isExported would cause
riscv-gp.s to fail:

* The first isExported computation considers the undefined symbol exported
* Defined as a linker-synthesized symbol
* isExported remains true, while it should be false

Added: 
    

Modified: 
    lld/ELF/Driver.cpp
    lld/ELF/LTO.cpp
    lld/ELF/MarkLive.cpp
    lld/ELF/Relocations.cpp
    lld/ELF/Symbols.cpp
    lld/ELF/Symbols.h
    lld/ELF/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 1f90ecccb96f23..3c553e5043180b 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2452,7 +2452,7 @@ static void readSymbolPartitionSection(Ctx &ctx, InputSectionBase *s) {
     sym = readEntry(s->file, rels.rels);
   else
     sym = readEntry(s->file, rels.relas);
-  if (!isa_and_nonnull<Defined>(sym) || !sym->includeInDynsym(ctx))
+  if (!isa_and_nonnull<Defined>(sym) || !sym->isExported)
     return;
 
   StringRef partName = reinterpret_cast<const char *>(s->content().data());

diff  --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 3973c0546b340f..195526bf390d2c 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -250,12 +250,12 @@ void BitcodeCompiler::add(BitcodeFile &f) {
     // 5) Symbols that will be referenced after linker wrapping is performed.
     r.VisibleToRegularObj = ctx.arg.relocatable || sym->isUsedInRegularObj ||
                             sym->referencedAfterWrap ||
-                            (r.Prevailing && sym->includeInDynsym(ctx)) ||
+                            (r.Prevailing && sym->isExported) ||
                             usedStartStop.count(objSym.getSectionName());
     // Identify symbols exported dynamically, and that therefore could be
     // referenced by a shared library not visible to the linker.
     r.ExportDynamic = sym->computeBinding(ctx) != STB_LOCAL &&
-                      (ctx.arg.exportDynamic || sym->exportDynamic);
+                      (ctx.arg.exportDynamic || sym->isExported);
     const auto *dr = dyn_cast<Defined>(sym);
     r.FinalDefinitionInLinkageUnit =
         (isExec || sym->visibility() != STV_DEFAULT) && dr &&

diff  --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index 08d9ecedf2cc07..b6c22884d91769 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -221,7 +221,7 @@ template <class ELFT> void MarkLive<ELFT>::run() {
   // Preserve externally-visible symbols if the symbols defined by this
   // file can interpose other ELF file's symbols at runtime.
   for (Symbol *sym : ctx.symtab->getSymbols())
-    if (sym->includeInDynsym(ctx) && sym->partition == partition)
+    if (sym->isExported && sym->partition == partition)
       markSymbol(sym);
 
   // If this isn't the main partition, that's all that we need to preserve.

diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index b47682857b398c..41c04b29034563 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1056,7 +1056,7 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
   // direct relocation on through.
   if (LLVM_UNLIKELY(isIfunc) && ctx.arg.zIfuncNoplt) {
     std::lock_guard<std::mutex> lock(ctx.relocMutex);
-    sym.exportDynamic = true;
+    sym.isExported = true;
     ctx.mainPart->relaDyn->addSymbolReloc(type, *sec, offset, sym, addend,
                                           type);
     return;

diff  --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index b19381fe439c79..ce1e89f2d08011 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -379,9 +379,9 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) {
   for (Symbol *sym : ctx.symtab->getSymbols()) {
     if (sym->hasVersionSuffix)
       sym->parseSymbolVersion(ctx);
+    sym->isExported = sym->includeInDynsym(ctx);
     if (hasDynSymTab)
-      sym->isPreemptible =
-          sym->includeInDynsym(ctx) && computeIsPreemptible(ctx, *sym);
+      sym->isPreemptible = sym->isExported && computeIsPreemptible(ctx, *sym);
   }
 }
 

diff  --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 1a53f3a1e15261..fac957a7248856 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -127,23 +127,18 @@ class Symbol {
   // - If -shared or --export-dynamic is specified, any symbol in an object
   //   file/bitcode sets this property, unless suppressed by LTO
   //   canBeOmittedFromSymbolTable().
+  //
+  // Primarily set in two locations, (a) after parseSymbolVersion and
+  // (b) during demoteSymbols.
   LLVM_PREFERRED_TYPE(bool)
-  uint8_t exportDynamic : 1;
+  uint8_t isExported : 1;
 
+  // Used to compute isExported. Set when defined or referenced by a SharedFile.
   LLVM_PREFERRED_TYPE(bool)
-  uint8_t ltoCanOmit : 1;
-
-  // Used to track if there has been at least one undefined reference to the
-  // symbol. For Undefined and SharedSymbol, the binding may change to STB_WEAK
-  // if the first undefined reference from a non-shared object is weak.
-  LLVM_PREFERRED_TYPE(bool)
-  uint8_t referenced : 1;
+  uint8_t exportDynamic : 1;
 
-  // Used to track if this symbol will be referenced after wrapping is performed
-  // (i.e. this will be true for foo if __real_foo is referenced, and will be
-  // true for __wrap_foo if foo is referenced).
   LLVM_PREFERRED_TYPE(bool)
-  uint8_t referencedAfterWrap : 1;
+  uint8_t ltoCanOmit : 1;
 
   // True if this symbol is specified by --trace-symbol option.
   LLVM_PREFERRED_TYPE(bool)
@@ -333,6 +328,18 @@ class Symbol {
   LLVM_PREFERRED_TYPE(bool)
   uint8_t inDynamicList : 1;
 
+  // Used to track if there has been at least one undefined reference to the
+  // symbol. For Undefined and SharedSymbol, the binding may change to STB_WEAK
+  // if the first undefined reference from a non-shared object is weak.
+  LLVM_PREFERRED_TYPE(bool)
+  uint8_t referenced : 1;
+
+  // Used to track if this symbol will be referenced after wrapping is performed
+  // (i.e. this will be true for foo if __real_foo is referenced, and will be
+  // true for __wrap_foo if foo is referenced).
+  LLVM_PREFERRED_TYPE(bool)
+  uint8_t referencedAfterWrap : 1;
+
   void setFlags(uint16_t bits) {
     flags.fetch_or(bits, std::memory_order_relaxed);
   }

diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index ea9692a2f731b2..6c16549bfa6c04 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -297,11 +297,9 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) {
       }
     }
 
-    if (ctx.arg.hasDynSymTab) {
-      sym->exportDynamic = sym->includeInDynsym(ctx);
-      sym->isPreemptible =
-          sym->exportDynamic && computeIsPreemptible(ctx, *sym);
-    }
+    sym->isExported = sym->includeInDynsym(ctx);
+    if (ctx.arg.hasDynSymTab)
+      sym->isPreemptible = sym->isExported && computeIsPreemptible(ctx, *sym);
   }
 }
 
@@ -1891,7 +1889,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
       if (ctx.in.symTab)
         ctx.in.symTab->addSymbol(sym);
 
-      if (sym->exportDynamic) {
+      // computeBinding might localize a linker-synthesized hidden symbol
+      // (e.g. __global_pointer$) that was considered exported.
+      if (sym->isExported && !sym->isLocal()) {
         ctx.partitions[sym->partition - 1].dynSymTab->addSymbol(sym);
         if (auto *file = dyn_cast<SharedFile>(sym->file))
           if (file->isNeeded && !sym->isUndefined())


        


More information about the llvm-commits mailing list