[lld] [ELF] Fix PROVIDE_HIDDEN -shared regression with bitcode file references (PR #112386)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 15 09:05:08 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

The inaccurate #<!-- -->111945 condition fixes a PROVIDE regression (#<!-- -->111478)
but introduces another regression: in a DSO link, if a symbol referenced
only by bitcode files is defined as PROVIDE_HIDDEN, lld would not set
the visibility correctly, leading to an assertion failure in
DynamicReloc::getSymIndex (https://reviews.llvm.org/D123985).

Fix this by making the condition accurate: use a map to track defined
symbols.


---
Full diff: https://github.com/llvm/llvm-project/pull/112386.diff


3 Files Affected:

- (modified) lld/ELF/LinkerScript.cpp (+13-10) 
- (modified) lld/ELF/LinkerScript.h (+2-1) 
- (modified) lld/test/ELF/linkerscript/provide-defined.s (+26-2) 


``````````diff
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 418f689cee2167..0560065ffa4780 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -200,7 +200,7 @@ static bool shouldDefineSym(Ctx &ctx, SymbolAssignment *cmd) {
   if (cmd->name == ".")
     return false;
 
-  return !cmd->provide || LinkerScript::shouldAddProvideSym(ctx, cmd->name);
+  return !cmd->provide || ctx.script->shouldAddProvideSym(cmd->name);
 }
 
 // Called by processSymbolAssignments() to assign definitions to
@@ -1798,7 +1798,7 @@ void LinkerScript::addScriptReferencedSymbolsToSymTable() {
   DenseSet<StringRef> added;
   SmallVector<const SmallVector<StringRef, 0> *, 0> symRefsVec;
   for (const auto &[name, symRefs] : provideMap)
-    if (shouldAddProvideSym(ctx, name) && added.insert(name).second)
+    if (shouldAddProvideSym(name) && added.insert(name).second)
       symRefsVec.push_back(&symRefs);
   while (symRefsVec.size()) {
     for (StringRef name : *symRefsVec.pop_back_val()) {
@@ -1806,7 +1806,7 @@ void LinkerScript::addScriptReferencedSymbolsToSymTable() {
       // Prevent the symbol from being discarded by --gc-sections.
       referencedSymbols.push_back(name);
       auto it = provideMap.find(name);
-      if (it != provideMap.end() && shouldAddProvideSym(ctx, name) &&
+      if (it != provideMap.end() && shouldAddProvideSym(name) &&
           added.insert(name).second) {
         symRefsVec.push_back(&it->second);
       }
@@ -1814,14 +1814,17 @@ void LinkerScript::addScriptReferencedSymbolsToSymTable() {
   }
 }
 
-bool LinkerScript::shouldAddProvideSym(Ctx &ctx, StringRef symName) {
+bool LinkerScript::shouldAddProvideSym(StringRef symName) {
   // This function is called before and after garbage collection. To prevent
   // undefined references from the RHS, the result of this function for a
-  // symbol must be the same for each call. We use isUsedInRegularObj to not
-  // change the return value of a demoted symbol. The exportDynamic condition,
-  // while not so accurate, allows PROVIDE to define a symbol referenced by a
-  // DSO.
+  // symbol must be the same for each call. We use unusedProvideSyms to not
+  // change the return value of a demoted symbol.
   Symbol *sym = ctx.symtab->find(symName);
-  return sym && !sym->isDefined() && !sym->isCommon() &&
-         (sym->isUsedInRegularObj || sym->exportDynamic);
+  if (!sym)
+    return false;
+  if (sym->isDefined() || sym->isCommon()) {
+    unusedProvideSyms.insert(sym);
+    return false;
+  }
+  return !unusedProvideSyms.count(sym);
 }
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index eda152dd3582ab..f5c418d1f6af52 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -389,7 +389,7 @@ class LinkerScript final {
   // Returns true if the PROVIDE symbol should be added to the link.
   // A PROVIDE symbol is added to the link only if it satisfies an
   // undefined reference.
-  static bool shouldAddProvideSym(Ctx &, StringRef symName);
+  bool shouldAddProvideSym(StringRef symName);
 
   // SECTIONS command list.
   SmallVector<SectionCommand *, 0> sectionCommands;
@@ -433,6 +433,7 @@ class LinkerScript final {
   //
   // then provideMap should contain the mapping: 'v' -> ['a', 'b', 'c']
   llvm::MapVector<StringRef, SmallVector<StringRef, 0>> provideMap;
+  llvm::DenseSet<Symbol *> unusedProvideSyms;
 
   // List of potential spill locations (PotentialSpillSection) for an input
   // section.
diff --git a/lld/test/ELF/linkerscript/provide-defined.s b/lld/test/ELF/linkerscript/provide-defined.s
index 1d44bef3d4068d..650925cac4051f 100644
--- a/lld/test/ELF/linkerscript/provide-defined.s
+++ b/lld/test/ELF/linkerscript/provide-defined.s
@@ -4,15 +4,27 @@
 # RUN: rm -rf %t && split-file %s %t && cd %t
 # RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o
+# RUN: llvm-as c.ll -o c.bc
 # RUN: ld.lld -T a.t --gc-sections a.o b.o -o a
 # RUN: llvm-readelf -s a | FileCheck %s
 
+# RUN: ld.lld -T a.t -shared a.o b.o c.bc -o a.so
+# RUN: llvm-readelf -s -r a.so | FileCheck %s --check-prefix=DSO
+
 # CHECK:     1: {{.*}}               0 NOTYPE  GLOBAL DEFAULT     1 _start
-# CHECK-NEXT:2: {{.*}}               0 NOTYPE  GLOBAL DEFAULT     2 f3
+# CHECK-NEXT:2: {{.*}}               0 NOTYPE  WEAK   DEFAULT     2 f3
 # CHECK-NOT: {{.}}
 
+# DSO:     .rela.plt
+# DSO-NOT: f5
+# DSO:     Symbol table '.dynsym'
+# DSO-NOT: f5
+# DSO:     Symbol table '.symtab'
+# DSO:     {{.*}}               0 NOTYPE  LOCAL  HIDDEN  [[#]] f5
+
 #--- a.s
-.global _start, f1, f2, f3, bar
+.global _start, f1, f2, bar
+.weak f3
 _start:
   call f3
 
@@ -26,6 +38,17 @@ _start:
 #--- b.s
   call f2
 
+#--- c.ll
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @f5()
+
+define void @f3() {
+  call void @f5()
+  ret void
+}
+
 #--- a.t
 SECTIONS {
   . = . + SIZEOF_HEADERS;
@@ -33,4 +56,5 @@ SECTIONS {
   PROVIDE(f2 = bar+2);
   PROVIDE(f3 = bar+3);
   PROVIDE(f4 = comm+4);
+  PROVIDE_HIDDEN(f5 = bar+5);
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/112386


More information about the llvm-commits mailing list