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 added; SmallVector *, 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..33c526f59bfc41 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 sectionCommands; @@ -433,6 +433,8 @@ class LinkerScript final { // // then provideMap should contain the mapping: 'v' -> ['a', 'b', 'c'] llvm::MapVector> provideMap; + // Store defined symbols that should ignore PROVIDE commands. + llvm::DenseSet 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); }