forked from OSchip/llvm-project
[ELF] Error for undefined foo@v1
If an object file has an undefined foo@v1, we emit a dynamic symbol foo. This is incorrect if at runtime a shared object provides the non-default version foo@v1 (the undefined foo may bind to foo@@v2, for example). GNU ld issues an error for this case, even if foo@v1 is undefined weak (https://sourceware.org/bugzilla/show_bug.cgi?id=3351). This behavior makes sense because to represent an undefined foo@v1, we have to construct a Verneed entry. However, without knowing the defining filename, we cannot construct a Verneed entry (Verneed::vn_file is unavailable). This patch implements the error. Depends on D92258 Reviewed By: grimar Differential Revision: https://reviews.llvm.org/D92260
This commit is contained in:
parent
624af932a8
commit
843c2b2303
|
@ -945,7 +945,15 @@ template <class ELFT> void elf::reportUndefinedSymbols() {
|
|||
// 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.getVersionSuffix() == '@') {
|
||||
undefs.push_back({&sym, {{&sec, offset}}, false});
|
||||
return true;
|
||||
}
|
||||
if (sym.isWeak())
|
||||
return false;
|
||||
|
||||
bool canBeExternal = !sym.isLocal() && sym.visibility == STV_DEFAULT;
|
||||
|
|
|
@ -183,7 +183,7 @@ public:
|
|||
// For @@, the name has been truncated by insert(). For @, the name has been
|
||||
// truncated by Symbol::parseSymbolVersion().
|
||||
const char *getVersionSuffix() const {
|
||||
assert(nameSize != (uint32_t)-1);
|
||||
(void)getName();
|
||||
return nameData + nameSize;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 if 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 ".global foo"
|
|||
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
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
# 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/ref1p.s -o %t/ref1p.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/def1w.s -o %t/def1w.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/hid1.s -o %t/hid1.o
|
||||
|
@ -45,13 +46,16 @@
|
|||
# CHECK-EMPTY:
|
||||
|
||||
## foo@@v2 does not resolve undefined foo@v1.
|
||||
## TODO Undefined 'foo@v1' should be errored.
|
||||
# RUN: ld.lld -shared --soname=t --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=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/def2.o \
|
||||
# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNDEF
|
||||
|
||||
# CHECK2: 1: {{.*}} NOTYPE GLOBAL DEFAULT UND foo{{$}}
|
||||
# CHECK2-NEXT: 2: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@@v2
|
||||
# CHECK2-EMPTY:
|
||||
# UNDEF: error: undefined symbol: foo@v1
|
||||
|
||||
## An undefined weak unversioned symbol is not errored. However, an undefined
|
||||
## weak versioned symbol should still be errored because we cannot construct
|
||||
## a Verneed entry (Verneed::vn_file is unavailable).
|
||||
# RUN: not ld.lld -shared --version-script=%t/ver %t/ref1w.o -o /dev/null 2>&1 | \
|
||||
# RUN: FileCheck %s --check-prefix=UNDEF
|
||||
|
||||
## foo@@v2 resolves undefined foo while foo@v1 resolves undefined foo@v1.
|
||||
# RUN: ld.lld -shared --soname=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/hid1.o %t/def2.o -o %t3
|
||||
|
@ -128,15 +132,15 @@
|
|||
|
||||
## Test --wrap on @ and @@.
|
||||
|
||||
## TODO Error because __wrap_foo@v1 is not defined.
|
||||
## Error because __wrap_foo@v1 is not defined.
|
||||
## Note: GNU ld errors "no symbol version section for versioned symbol `__wrap_foo@v1'".
|
||||
# RUN: ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo@v1 %t/ref.o %t/ref1.o %t/def1.o %t/wrap.o -o %t.w3
|
||||
# RUN: llvm-readobj -r %t.w3 | FileCheck %s --check-prefix=W3REL
|
||||
# RUN: not ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo@v1 %t/ref.o %t/ref1.o %t/def1.o %t/wrap.o \
|
||||
# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=W3
|
||||
|
||||
# W3REL: .rela.plt {
|
||||
# W3REL-NEXT: R_X86_64_JUMP_SLOT foo@@v1 0x0
|
||||
# W3REL-NEXT: R_X86_64_JUMP_SLOT - 0x0
|
||||
# W3REL-NEXT: }
|
||||
# W3: error: undefined symbol: __wrap_foo@v1
|
||||
# W3-NEXT: >>> referenced by {{.*}}ref1.o:(.text+0x1)
|
||||
# W3-NEXT: >>> did you mean: __wrap_foo{{$}}
|
||||
# W3-NEXT: >>> defined in: {{.*}}wrap.o
|
||||
|
||||
## foo@v1 is correctly wrapped.
|
||||
# RUN: ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo@v1 %t/ref.o %t/ref1.o %t/def1.o %t/wrap1.o -o %t.w4
|
||||
|
@ -183,6 +187,11 @@ call foo
|
|||
.symver foo, foo@@@v1
|
||||
call foo
|
||||
|
||||
#--- ref1w.s
|
||||
.weak foo
|
||||
.symver foo, foo@@@v1
|
||||
call foo
|
||||
|
||||
#--- def1.s
|
||||
.globl foo
|
||||
.symver foo, foo@@@v1
|
||||
|
|
Loading…
Reference in New Issue