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

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 15 09:18:40 PDT 2024


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

>From 8bddfc0b0c4b8d5e418209a605792bd872976b33 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Tue, 15 Oct 2024 09:04:18 -0700
Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6-beta.1
---
 lld/ELF/LinkerScript.cpp                    | 23 +++++++++--------
 lld/ELF/LinkerScript.h                      |  3 ++-
 lld/test/ELF/linkerscript/provide-defined.s | 28 +++++++++++++++++++--
 3 files changed, 41 insertions(+), 13 deletions(-)

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);
 }

>From 333e12a5bd25d981de05dae71bafc7ad1c0990d8 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Tue, 15 Oct 2024 09:18:23 -0700
Subject: [PATCH 2/2] add comment

Created using spr 1.3.6-beta.1
---
 lld/ELF/LinkerScript.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index f5c418d1f6af52..33c526f59bfc41 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -433,6 +433,7 @@ class LinkerScript final {
   //
   // then provideMap should contain the mapping: 'v' -> ['a', 'b', 'c']
   llvm::MapVector<StringRef, SmallVector<StringRef, 0>> provideMap;
+  // Store defined symbols that should ignore PROVIDE commands.
   llvm::DenseSet<Symbol *> unusedProvideSyms;
 
   // List of potential spill locations (PotentialSpillSection) for an input



More information about the llvm-commits mailing list