xref: /llvm-project/lld/test/ELF/symver.s (revision cf783be8d7a8594ab82f8215671dddbebcae39ec)
1# REQUIRES: x86
2## Test symbol resolution related to .symver produced symbols in object files.
3
4# RUN: split-file %s %t
5# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/ref.s -o %t/ref.o
6# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/ref1.s -o %t/ref1.o
7# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/ref1p.s -o %t/ref1p.o
8# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/ref1w.s -o %t/ref1w.o
9# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/def1.s -o %t/def1.o
10# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/def1w.s -o %t/def1w.o
11# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/hid1.s -o %t/hid1.o
12# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/hid1w.s -o %t/hid1w.o
13# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/def2.s -o %t/def2.o
14# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/wrap.s -o %t/wrap.o
15# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/wrap1.s -o %t/wrap1.o
16# RUN: ld.lld -shared --soname=def1.so --version-script=%t/ver %t/def1.o -o %t/def1.so
17# RUN: ld.lld -shared --soname=hid1.so --version-script=%t/ver %t/hid1.o -o %t/hid1.so
18
19## Report a duplicate definition error for foo@v1 and foo@@v1.
20# RUN: not ld.lld -shared --version-script=%t/ver %t/def1.o %t/hid1.o -o /dev/null 2>&1 | \
21# RUN:   FileCheck %s --check-prefix=DUP
22# RUN: ld.lld -shared --version-script=%t/ver %t/def1w.o %t/hid1.o -o /dev/null
23# RUN: ld.lld -shared --version-script=%t/ver %t/def1.o %t/hid1w.o -o /dev/null
24# RUN: ld.lld -shared --version-script=%t/ver %t/def1w.o %t/hid1w.o -o /dev/null
25
26# DUP:      error: duplicate symbol: foo@@v1
27# DUP-NEXT: >>> defined at {{.*}}/def1{{w?}}.o:(.text+0x0)
28# DUP-NEXT: >>> defined at {{.*}}/hid1.o:(.text+0x0)
29
30## Protected undefined foo@v1 makes the output symbol protected.
31# RUN: ld.lld -shared --version-script=%t/ver %t/ref1p.o %t/def1.o -o %t.protected
32# RUN: llvm-readelf --dyn-syms %t.protected | FileCheck %s --check-prefix=PROTECTED
33
34# PROTECTED:  NOTYPE GLOBAL PROTECTED [[#]] foo@@v1
35
36## foo@@v1 resolves both undefined foo and foo@v1. There is one single definition.
37## Note: set soname so that the name string referenced by .gnu.version_d is fixed.
38# RUN: ld.lld -shared --soname=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/def1.o -o %t1
39# RUN: llvm-readelf -r --dyn-syms %t1 | FileCheck %s
40
41# CHECK:       Relocation section '.rela.plt' at offset {{.*}} contains 1 entries:
42# CHECK-NEXT:  {{.*}} Type               {{.*}}
43# CHECK-NEXT:  {{.*}} R_X86_64_JUMP_SLOT {{.*}} foo@@v1 + 0
44
45# CHECK:       1: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@@v1
46# CHECK-EMPTY:
47
48## foo@@v2 does not resolve undefined foo@v1.
49# RUN: not ld.lld -shared --soname=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/def2.o \
50# RUN:   -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNDEF
51
52# UNDEF: error: undefined symbol: foo@v1
53
54## An undefined weak unversioned symbol is not errored. However, an undefined
55## weak versioned symbol should still be errored because we cannot construct
56## a Verneed entry (Verneed::vn_file is unavailable).
57# RUN: not ld.lld -shared --version-script=%t/ver %t/ref1w.o -o /dev/null 2>&1 | \
58# RUN:   FileCheck %s --check-prefix=UNDEF
59
60## foo@@v2 resolves undefined foo while foo@v1 resolves undefined foo@v1.
61# RUN: ld.lld -shared --soname=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/hid1.o %t/def2.o -o %t3
62# RUN: llvm-readelf -r --dyn-syms %t3 | FileCheck %s --check-prefix=CHECK3
63# RUN: llvm-objdump -d --no-show-raw-insn %t3 | FileCheck %s --check-prefix=DIS3
64
65# CHECK3:       00000000000034a8 {{.*}} R_X86_64_JUMP_SLOT {{.*}} foo@@v2 + 0
66# CHECK3-NEXT:  00000000000034b0 {{.*}} R_X86_64_JUMP_SLOT {{.*}} foo@v1 + 0
67
68# CHECK3:       1: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@@v2
69# CHECK3-NEXT:  2: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo@v1
70# CHECK3-NEXT:  3: {{.*}} NOTYPE GLOBAL DEFAULT [[#]] foo_v1
71# CHECK3-EMPTY:
72
73# DIS3-LABEL: <.text>:
74# DIS3-NEXT:    callq 0x1380 <foo@plt>
75# DIS3-COUNT-3: int3
76# DIS3-NEXT:    callq 0x1390 <foo@plt>
77# DIS3-LABEL: <foo@plt>:
78# DIS3-NEXT:    jmpq *{{.*}}(%rip) # 0x34a8
79# DIS3-LABEL: <foo@plt>:
80# DIS3-NEXT:    jmpq *{{.*}}(%rip) # 0x34b0
81
82## Then, test the interaction with versioned definitions in shared objects.
83
84## TODO Both foo and foo@v1 are undefined. Ideally we should not create two .dynsym entries.
85# RUN: ld.lld -shared --soname=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/def1.so -o %t4
86# RUN: llvm-readelf --dyn-syms %t4 | FileCheck %s --check-prefix=CHECK4
87
88# CHECK4:       1: {{.*}} NOTYPE GLOBAL DEFAULT UND   foo@v1
89# CHECK4-NEXT:  2: {{.*}} NOTYPE GLOBAL DEFAULT UND   foo@v1
90# CHECK4-EMPTY:
91
92## hid1.so resolves undefined foo@v1. foo is undefined.
93# RUN: ld.lld -shared --soname=t --version-script=%t/ver %t/ref.o %t/ref1.o %t/hid1.so -o %t5
94# RUN: llvm-readelf --dyn-syms %t5 | FileCheck %s --check-prefix=CHECK5
95
96# CHECK5:       1: {{.*}} NOTYPE GLOBAL DEFAULT UND   foo{{$}}
97# CHECK5-NEXT:  2: {{.*}} NOTYPE GLOBAL DEFAULT UND   foo@v1
98# CHECK5-EMPTY:
99
100## Test the interaction with --wrap.
101
102## The reference from ref.o is redirected. The reference from ref1.o is not.
103# 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
104# RUN: llvm-readobj -r %t.w1 | FileCheck %s --check-prefix=W1REL
105# RUN: llvm-objdump -d --no-show-raw-insn %t.w1 | FileCheck %s --check-prefix=W1DIS
106
107# W1REL:      .rela.plt {
108# W1REL-NEXT:   R_X86_64_JUMP_SLOT foo@@v1 0x0
109# W1REL-NEXT:   R_X86_64_JUMP_SLOT __wrap_foo 0x0
110# W1REL-NEXT: }
111
112# W1DIS-LABEL: <.text>:
113# W1DIS-NEXT:    callq {{.*}} <__wrap_foo@plt>
114# W1DIS-COUNT-3: int3
115# W1DIS-NEXT:    callq {{.*}} <foo@plt>
116
117## The reference from ref.o is redirected. The reference from ref1.o is not.
118## Note: this case demonstrates the typical behavior wrapping a glibc libc.so definition.
119# 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
120# RUN: llvm-readobj -r %t.w2 | FileCheck %s --check-prefix=W2REL
121# RUN: llvm-objdump -d --no-show-raw-insn %t.w2 | FileCheck %s --check-prefix=W2DIS
122
123# W2REL:      .rela.plt {
124# W2REL-NEXT:   R_X86_64_JUMP_SLOT foo@v1 0x0
125# W2REL-NEXT:   R_X86_64_JUMP_SLOT __wrap_foo 0x0
126# W2REL-NEXT: }
127
128# W2DIS-LABEL: <.text>:
129# W2DIS-NEXT:    callq {{.*}} <__wrap_foo@plt>
130# W2DIS-COUNT-3: int3
131# W2DIS-NEXT:    callq {{.*}} <foo@plt>
132
133## Test --wrap on @ and @@.
134
135## Error because __wrap_foo@v1 is not defined.
136## Note: GNU ld errors "no symbol version section for versioned symbol `__wrap_foo@v1'".
137# 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 \
138# RUN:   -o /dev/null 2>&1 | FileCheck %s --check-prefix=W3
139
140# W3:      error: undefined symbol: __wrap_foo@v1
141# W3-NEXT: >>> referenced by {{.*}}ref1.o:(.text+0x1)
142# W3-NEXT: >>> did you mean: __wrap_foo{{$}}
143# W3-NEXT: >>> defined in: {{.*}}wrap.o
144
145## foo@v1 is correctly wrapped.
146# 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
147# RUN: llvm-readobj -r %t.w4 | FileCheck %s --check-prefix=W4REL
148# RUN: llvm-objdump -d --no-show-raw-insn %t.w4 | FileCheck %s --check-prefix=W4DIS
149
150# W4REL:      .rela.plt {
151# W4REL-NEXT:   R_X86_64_JUMP_SLOT foo@@v1 0x0
152# W4REL-NEXT:   R_X86_64_JUMP_SLOT __wrap_foo@v1 0x0
153# W4REL-NEXT: }
154
155# W4DIS-LABEL: <.text>:
156# W4DIS-NEXT:    callq {{.*}} <foo@plt>
157# W4DIS-COUNT-3: int3
158# W4DIS-NEXT:    callq {{.*}} <__wrap_foo@plt>
159
160## Note: GNU ld errors "no symbol version section for versioned symbol `__wrap_foo@@v1'".
161# 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
162# RUN: llvm-readobj -r %t.w5 | FileCheck %s --check-prefix=W5REL
163# RUN: llvm-objdump -d --no-show-raw-insn %t.w5 | FileCheck %s --check-prefix=W5DIS
164
165# W5REL:      .rela.plt {
166# W5REL-NEXT:   R_X86_64_JUMP_SLOT foo@@v1 0x0
167# W5REL-NEXT: }
168
169# W5DIS-LABEL: <.text>:
170# W5DIS-NEXT:    callq 0x1350 <foo@plt>
171# W5DIS-COUNT-3: int3
172# W5DIS-NEXT:    callq 0x1350 <foo@plt>
173
174#--- ver
175v1 {};
176v2 {};
177
178#--- ref.s
179call foo
180
181#--- ref1.s
182.symver foo, foo@@@v1
183call foo
184
185#--- ref1p.s
186.protected foo
187.symver foo, foo@@@v1
188call foo
189
190#--- ref1w.s
191.weak foo
192.symver foo, foo@@@v1
193call foo
194
195#--- def1.s
196.globl foo
197.symver foo, foo@@@v1
198foo:
199
200#--- def1w.s
201.weak foo
202.symver foo, foo@@@v1
203foo:
204
205#--- hid1.s
206.globl foo_v1
207.symver foo_v1, foo@v1
208foo_v1:
209  ret
210
211#--- hid1w.s
212.weak foo_v1
213.symver foo_v1, foo@v1
214foo_v1:
215  ret
216
217#--- def2.s
218.globl foo
219.symver foo, foo@@@v2
220foo:
221  ret
222
223#--- wrap.s
224.globl __wrap_foo
225__wrap_foo:
226  hlt
227
228#--- wrap1.s
229.globl __wrap_foo_v1
230.symver __wrap_foo_v1, __wrap_foo@v1
231__wrap_foo_v1:
232  int3
233