[lld] a5f9588 - [ELF][test] Add some tests for versioned symbols in object files

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 1 08:49:22 PST 2020


Author: Fangrui Song
Date: 2020-12-01T08:49:14-08:00
New Revision: a5f95887d0f8d27f1c33f19944d0c1da66aef606

URL: https://github.com/llvm/llvm-project/commit/a5f95887d0f8d27f1c33f19944d0c1da66aef606
DIFF: https://github.com/llvm/llvm-project/commit/a5f95887d0f8d27f1c33f19944d0c1da66aef606.diff

LOG: [ELF][test] Add some tests for versioned symbols in object files

Test the symbol resolution related to

* defined foo@@v1 and foo at v1 in object files/shared objects
* undefined foo at v1
* weak foo@@v1 and foo at v1
* visibility
* interaction with --wrap.

Reviewed By: grimar

Differential Revision: https://reviews.llvm.org/D92258

Added: 
    lld/test/ELF/symver.s

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/lld/test/ELF/symver.s b/lld/test/ELF/symver.s
new file mode 100644
index 000000000000..7495805bfe4d
--- /dev/null
+++ b/lld/test/ELF/symver.s
@@ -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 at 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 at 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 at 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 at v1.
+## TODO Undefined 'foo at 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 at v1 resolves undefined foo at 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 at v1 + 0
+
+# CHECK3:       1: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@@v2
+# CHECK3-NEXT:  2: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo at v1
+# CHECK3-NEXT:  3: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo_v1
+# CHECK3-EMPTY:
+
+# DIS3-LABEL: <.text>:
+# DIS3-NEXT:    callq 0x1380 <foo at plt>
+# DIS3-COUNT-3: int3
+# DIS3-NEXT:    callq 0x1390 <foo at plt>
+# DIS3-LABEL: <foo at plt>:
+# DIS3-NEXT:    jmpq *{{.*}}(%rip) # 34a8
+# DIS3-LABEL: <foo at plt>:
+# DIS3-NEXT:    jmpq *{{.*}}(%rip) # 34b0
+
+## Then, test the interaction with versioned definitions in shared objects.
+
+## TODO Both foo and foo at 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 at v1
+# CHECK4-NEXT:  2: {{.*}} NOTYPE GLOBAL DEFAULT UND   foo at v1
+# CHECK4-EMPTY:
+
+## hid1.so resolves undefined foo at 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 at 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 at plt>
+# W1DIS-COUNT-3: int3
+# W1DIS-NEXT:    callq {{.*}} <foo at 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 at v1 0x0
+# W2REL-NEXT: }
+
+# W2DIS-LABEL: <.text>:
+# W2DIS-NEXT:    callq {{.*}} <__wrap_foo at plt>
+# W2DIS-COUNT-3: int3
+# W2DIS-NEXT:    callq {{.*}} <foo at plt>
+
+## Test --wrap on @ and @@.
+
+## TODO Error because __wrap_foo at v1 is not defined.
+## Note: GNU ld errors "no symbol version section for versioned symbol `__wrap_foo at v1'".
+# RUN: ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo at 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 at v1 is correctly wrapped.
+# RUN: ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo at 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 at v1 0x0
+# W4REL-NEXT: }
+
+# W4DIS-LABEL: <.text>:
+# W4DIS-NEXT:    callq {{.*}} <foo at plt>
+# W4DIS-COUNT-3: int3
+# W4DIS-NEXT:    callq {{.*}} <__wrap_foo at 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 at plt>
+# W5DIS-COUNT-3: int3
+# W5DIS-NEXT:    callq 0x1390 <foo at 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 at v1
+foo_v1:
+  ret
+
+#--- hid1w.s
+.weak foo_v1
+.symver foo_v1, foo at 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 at v1
+__wrap_foo_v1:
+  int3


        


More information about the llvm-commits mailing list