diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -945,7 +945,15 @@ // Returns true if the undefined symbol will produce an error message. static bool maybeReportUndefined(Symbol &sym, InputSectionBase &sec, uint64_t offset) { - if (!sym.isUndefined() || sym.isWeak()) + if (!sym.isUndefined()) + return false; + // If versioned, issue an error (even if the symbol is weak) because we don't + // know the defining filename which is required to construct a Verneed entry. + if (sym.getName().data()[sym.getName().size()] == '@') { + undefs.push_back({&sym, {{&sec, offset}}, false}); + return true; + } + if (sym.isWeak()) return false; bool canBeExternal = !sym.isLocal() && sym.visibility == STV_DEFAULT; diff --git a/lld/test/ELF/lto/version-script2.ll b/lld/test/ELF/lto/version-script2.ll --- a/lld/test/ELF/lto/version-script2.ll +++ b/lld/test/ELF/lto/version-script2.ll @@ -4,13 +4,21 @@ ;; otherwise we may get a symbol named "foo@@VER1", but not "foo" with the ;; version VER1. -; RUN: llvm-as %s -o %t.o +; RUN: split-file %s %t +; RUN: llvm-as %t/ir -o %t.o +; RUN: llvm-mc -filetype=obj -triple=x86_64 %t/asm -o %tbar.o +; RUN: ld.lld %tbar.o -shared --soname=tbar --version-script %t.script -o %tbar.so ; RUN: echo "VER1 {};" > %t.script -; RUN: ld.lld %t.o -o %t.so -shared --version-script %t.script + +;; Emit an error is bar@VER1 is not defined. +; RUN: not ld.lld %t.o -o /dev/null -shared --version-script %t.script 2>&1 | FileCheck %s --check-prefix=UNDEF + +; UNDEF: error: undefined symbol: bar@VER1 + +; RUN: ld.lld %t.o %tbar.so -o %t.so -shared --version-script %t.script ; RUN: llvm-readelf --dyn-syms %t.so | FileCheck %s -;; For non-relocatable output, @ in symbol names has no effect on undefined symbols. -; CHECK: UND bar{{$}} +; CHECK: UND bar@VER1 ; CHECK-NEXT: {{[1-9]}} foo@@VER1 ;; For relocatable output, @ should be retained in the symbol name. @@ -21,6 +29,7 @@ ; RELOCATABLE: {{[1-9]}} foo@@VER1 ; RELOCATABLE-NEXT: UND bar@VER1 +;--- ir target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -28,3 +37,9 @@ module asm "foo: call bar" module asm ".symver foo,foo@@@VER1" module asm ".symver bar,bar@@@VER1" + +;--- asm +.globl bar +.symver bar,bar@@@VER1 +bar: + ret diff --git a/lld/test/ELF/symver.s b/lld/test/ELF/symver.s --- a/lld/test/ELF/symver.s +++ b/lld/test/ELF/symver.s @@ -2,6 +2,7 @@ # RUN: split-file %s %t # RUN: llvm-mc -filetype=obj -triple=x86_64 %t/ref.s -o %t/ref.o # RUN: llvm-mc -filetype=obj -triple=x86_64 %t/ref1.s -o %t/ref1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/ref1w.s -o %t/ref1w.o # RUN: llvm-mc -filetype=obj -triple=x86_64 %t/def1.s -o %t/def1.o # RUN: llvm-mc -filetype=obj -triple=x86_64 %t/hid1.s -o %t/hid1.o # RUN: llvm-mc -filetype=obj -triple=x86_64 %t/def2.s -o %t/def2.o @@ -17,6 +18,12 @@ # DUP-NEXT: >>> defined at {{.*}}/hid1.o:(.text+0x0) # DUP-NEXT: >>> defined at {{.*}}/def1.o:(.text+0x0) +# RUN: not ld.lld -shared --version-script=%t/ver %t/ref1w.o -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=UNDEF + +# UNDEF: error: undefined symbol: foo@v1 +# UNDEF-NEXT: >>> referenced by {{.*}}.o:(.text+0x1) + ## foo@@v1 resolves both undefined foo and foo@v1. There is one single definition. ## Note, set soname so that the name string referenced by .gnu.version_d is fixed. # RUN: ld.lld -shared --soname=t1 --version-script=%t/ver %t/ref.o %t/ref1.o %t/def1.o -o %t1 @@ -30,13 +37,10 @@ # CHECK-EMPTY: ## foo@@v2 does not resolve undefined foo@v1. -## TODO Undefined 'foo@v1' should be errored. -# RUN: ld.lld -shared --soname=t2 --version-script=%t/ver %t/ref.o %t/ref1.o %t/def2.o -o %t2 -# RUN: llvm-readelf --dyn-syms %t2 | FileCheck %s --check-prefix=CHECK2 +# RUN: not ld.lld -shared --soname=t2 --version-script=%t/ver %t/ref.o %t/ref1.o %t/def2.o \ +# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNDEF2 -# CHECK2: 1: {{.*}} NOTYPE GLOBAL DEFAULT UND foo{{$}} -# CHECK2-NEXT: 2: {{.*}} NOTYPE GLOBAL DEFAULT {{[1-9]}} foo@@v2 -# CHECK2-EMPTY: +# UNDEF2: error: undefined symbol: foo@v1 ## foo@@v2 resolves undefined foo while foo@v1 resolves undefined foo@v1. # RUN: ld.lld -shared --soname=t3 --version-script=%t/ver %t/ref.o %t/ref1.o %t/hid1.o %t/def2.o -o %t3 @@ -98,6 +102,11 @@ .symver foo, foo@@@v1 call foo +#--- ref1w.s +.weak foo +.symver foo, foo@@@v1 +call foo + #--- def1.s .globl foo .symver foo, foo@@@v1