[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