-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ELF][test] Add some tests for versioned symbols in object files
Test the symbol resolution related to * defined foo@@v1 and foo@v1 in object files/shared objects * undefined foo@v1 * weak foo@@v1 and foo@v1 * visibility * interaction with --wrap. Reviewed By: grimar Differential Revision: https://reviews.llvm.org/D92258
- Loading branch information
Showing
1 changed file
with
222 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
# REQUIRES: x86 | ||
## Test symbol resolution related to .symver produced symbols in object files. | ||
|
||
# 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/ref1p.s -o %t/ref1p.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 | ||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/hid1w.s -o %t/hid1w.o | ||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/def2.s -o %t/def2.o | ||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/wrap.s -o %t/wrap.o | ||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/wrap1.s -o %t/wrap1.o | ||
# RUN: ld.lld -shared --soname=def1.so --version-script=%t/ver %t/def1.o -o %t/def1.so | ||
# RUN: ld.lld -shared --soname=hid1.so --version-script=%t/ver %t/hid1.o -o %t/hid1.so | ||
|
||
## TODO Report a duplicate definition error for foo@v1 and foo@@v1. | ||
# RUN: ld.lld -shared --version-script=%t/ver %t/def1.o %t/hid1.o -o /dev/null | ||
|
||
# RUN: ld.lld -shared --version-script=%t/ver %t/def1w.o %t/hid1.o -o /dev/null | ||
# RUN: ld.lld -shared --version-script=%t/ver %t/def1.o %t/hid1w.o -o /dev/null | ||
# RUN: ld.lld -shared --version-script=%t/ver %t/def1w.o %t/hid1w.o -o /dev/null | ||
|
||
## TODO foo@@v1 should resolve undefined foo@v1. | ||
# RUN: not ld.lld -shared --version-script=%t/ver %t/ref1p.o %t/def1.o -o /dev/null | ||
|
||
## TODO | ||
## 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=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/def1.o -o %t1 | ||
# RUN: llvm-readelf -r --dyn-syms %t1 | FileCheck %s | ||
|
||
# CHECK: Relocation section '.rela.plt' at offset {{.*}} contains 2 entries: | ||
# CHECK-NEXT: {{.*}} Type {{.*}} | ||
# CHECK-NEXT: {{.*}} R_X86_64_JUMP_SLOT {{.*}} foo@@v1 + 0 | ||
# CHECK-NEXT: {{.*}} R_X86_64_JUMP_SLOT {{.*}} foo + 0 | ||
|
||
# CHECK: 1: {{.*}} NOTYPE GLOBAL DEFAULT UND foo{{$}} | ||
# CHECK-NEXT: 2: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@@v1 | ||
# 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 | ||
|
||
# CHECK2: 1: {{.*}} NOTYPE GLOBAL DEFAULT UND foo{{$}} | ||
# CHECK2-NEXT: 2: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@@v2 | ||
# CHECK2-EMPTY: | ||
|
||
## 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 | ||
# RUN: llvm-readelf -r --dyn-syms %t3 | FileCheck %s --check-prefix=CHECK3 | ||
# RUN: llvm-objdump -d --no-show-raw-insn %t3 | FileCheck %s --check-prefix=DIS3 | ||
|
||
# CHECK3: 00000000000034a8 {{.*}} R_X86_64_JUMP_SLOT {{.*}} foo@@v2 + 0 | ||
# CHECK3-NEXT: 00000000000034b0 {{.*}} R_X86_64_JUMP_SLOT {{.*}} foo@v1 + 0 | ||
|
||
# CHECK3: 1: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@@v2 | ||
# CHECK3-NEXT: 2: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@v1 | ||
# CHECK3-NEXT: 3: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo_v1 | ||
# CHECK3-EMPTY: | ||
|
||
# DIS3-LABEL: <.text>: | ||
# DIS3-NEXT: callq 0x1380 <foo@plt> | ||
# DIS3-COUNT-3: int3 | ||
# DIS3-NEXT: callq 0x1390 <foo@plt> | ||
# DIS3-LABEL: <foo@plt>: | ||
# DIS3-NEXT: jmpq *{{.*}}(%rip) # 34a8 | ||
# DIS3-LABEL: <foo@plt>: | ||
# DIS3-NEXT: jmpq *{{.*}}(%rip) # 34b0 | ||
|
||
## Then, test the interaction with versioned definitions in shared objects. | ||
|
||
## TODO Both foo and foo@v1 are undefined. Ideally we should not create two .dynsym entries. | ||
# RUN: ld.lld -shared --soname=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/def1.so -o %t4 | ||
# RUN: llvm-readelf --dyn-syms %t4 | FileCheck %s --check-prefix=CHECK4 | ||
|
||
# CHECK4: 1: {{.*}} NOTYPE GLOBAL DEFAULT UND foo@v1 | ||
# CHECK4-NEXT: 2: {{.*}} NOTYPE GLOBAL DEFAULT UND foo@v1 | ||
# CHECK4-EMPTY: | ||
|
||
## hid1.so resolves undefined foo@v1. foo is undefined. | ||
# RUN: ld.lld -shared --soname=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/hid1.so -o %t5 | ||
# RUN: llvm-readelf --dyn-syms %t5 | FileCheck %s --check-prefix=CHECK5 | ||
|
||
# CHECK5: 1: {{.*}} NOTYPE GLOBAL DEFAULT UND foo{{$}} | ||
# CHECK5-NEXT: 2: {{.*}} NOTYPE GLOBAL DEFAULT UND foo@v1 | ||
# CHECK5-EMPTY: | ||
|
||
## Test the interaction with --wrap. | ||
|
||
## The reference from ref.o is redirected. The reference from ref1.o is not. | ||
# RUN: ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo %t/ref.o %t/ref1.o %t/def1.o %t/wrap.o -o %t.w1 | ||
# RUN: llvm-readobj -r %t.w1 | FileCheck %s --check-prefix=W1REL | ||
# RUN: llvm-objdump -d --no-show-raw-insn %t.w1 | FileCheck %s --check-prefix=W1DIS | ||
|
||
## TODO foo should be foo@@v1. | ||
# W1REL: .rela.plt { | ||
# W1REL-NEXT: R_X86_64_JUMP_SLOT __wrap_foo 0x0 | ||
# W1REL-NEXT: R_X86_64_JUMP_SLOT foo 0x0 | ||
# W1REL-NEXT: } | ||
|
||
# W1DIS-LABEL: <.text>: | ||
# W1DIS-NEXT: callq {{.*}} <__wrap_foo@plt> | ||
# W1DIS-COUNT-3: int3 | ||
# W1DIS-NEXT: callq {{.*}} <foo@plt> | ||
|
||
## The reference from ref.o is redirected. The reference from ref1.o is not. | ||
## Note: this case demonstrates the typical behavior wrapping a glibc libc.so definition. | ||
# RUN: ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo %t/ref.o %t/ref1.o %t/def1.so %t/wrap.o -o %t.w2 | ||
# RUN: llvm-readobj -r %t.w2 | FileCheck %s --check-prefix=W2REL | ||
# RUN: llvm-objdump -d --no-show-raw-insn %t.w2 | FileCheck %s --check-prefix=W2DIS | ||
|
||
# W2REL: .rela.plt { | ||
# W2REL-NEXT: R_X86_64_JUMP_SLOT __wrap_foo 0x0 | ||
# W2REL-NEXT: R_X86_64_JUMP_SLOT foo@v1 0x0 | ||
# W2REL-NEXT: } | ||
|
||
# W2DIS-LABEL: <.text>: | ||
# W2DIS-NEXT: callq {{.*}} <__wrap_foo@plt> | ||
# W2DIS-COUNT-3: int3 | ||
# W2DIS-NEXT: callq {{.*}} <foo@plt> | ||
|
||
## Test --wrap on @ and @@. | ||
|
||
## TODO 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 | ||
|
||
# W3REL: .rela.plt { | ||
# W3REL-NEXT: R_X86_64_JUMP_SLOT foo@@v1 0x0 | ||
# W3REL-NEXT: R_X86_64_JUMP_SLOT - 0x0 | ||
# W3REL-NEXT: } | ||
|
||
## 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 | ||
# RUN: llvm-readobj -r %t.w4 | FileCheck %s --check-prefix=W4REL | ||
# RUN: llvm-objdump -d --no-show-raw-insn %t.w4 | FileCheck %s --check-prefix=W4DIS | ||
|
||
# W4REL: .rela.plt { | ||
# W4REL-NEXT: R_X86_64_JUMP_SLOT foo@@v1 0x0 | ||
# W4REL-NEXT: R_X86_64_JUMP_SLOT __wrap_foo@v1 0x0 | ||
# W4REL-NEXT: } | ||
|
||
# W4DIS-LABEL: <.text>: | ||
# W4DIS-NEXT: callq {{.*}} <foo@plt> | ||
# W4DIS-COUNT-3: int3 | ||
# W4DIS-NEXT: callq {{.*}} <__wrap_foo@plt> | ||
|
||
## TODO The two callq should jump to the same address. | ||
## 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.w5 | ||
# RUN: llvm-readobj -r %t.w5 | FileCheck %s --check-prefix=W5REL | ||
# RUN: llvm-objdump -d --no-show-raw-insn %t.w5 | FileCheck %s --check-prefix=W5DIS | ||
|
||
# W5REL: .rela.plt { | ||
# W5REL-NEXT: R_X86_64_JUMP_SLOT foo@@v1 0x0 | ||
# W5REL-NEXT: R_X86_64_JUMP_SLOT foo 0x0 | ||
# W5REL-NEXT: } | ||
|
||
# W5DIS-LABEL: <.text>: | ||
# W5DIS-NEXT: callq 0x1380 <foo@plt> | ||
# W5DIS-COUNT-3: int3 | ||
# W5DIS-NEXT: callq 0x1390 <foo@plt> | ||
|
||
#--- ver | ||
v1 {}; | ||
v2 {}; | ||
|
||
#--- ref.s | ||
call foo | ||
|
||
#--- ref1.s | ||
.symver foo, foo@@@v1 | ||
call foo | ||
|
||
#--- ref1p.s | ||
.protected foo | ||
.symver foo, foo@@@v1 | ||
call foo | ||
|
||
#--- def1.s | ||
.globl foo | ||
.symver foo, foo@@@v1 | ||
foo: | ||
|
||
#--- def1w.s | ||
.weak foo | ||
.symver foo, foo@@@v1 | ||
foo: | ||
|
||
#--- hid1.s | ||
.globl foo_v1 | ||
.symver foo_v1, foo@v1 | ||
foo_v1: | ||
ret | ||
|
||
#--- hid1w.s | ||
.weak foo_v1 | ||
.symver foo_v1, foo@v1 | ||
foo_v1: | ||
ret | ||
|
||
#--- def2.s | ||
.globl foo | ||
.symver foo, foo@@@v2 | ||
foo: | ||
ret | ||
|
||
#--- wrap.s | ||
.globl __wrap_foo | ||
__wrap_foo: | ||
hlt | ||
|
||
#--- wrap1.s | ||
.globl __wrap_foo_v1 | ||
.symver __wrap_foo_v1, __wrap_foo@v1 | ||
__wrap_foo_v1: | ||
int3 |