Update copyright year range in all GDB files.
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.base / gnu-ifunc.exp
CommitLineData
42a4f53d 1# Copyright (C) 2009-2019 Free Software Foundation, Inc.
e4620230
JK
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16if {[skip_shlib_tests]} {
17 return 0
18}
19
ca98345e
SL
20if {[skip_ifunc_tests]} {
21 return 0
22}
23
289f9037 24standard_testfile .c
c7075ad5 25set staticexecutable ${testfile}-static
289f9037 26set staticbinfile [standard_output_file ${staticexecutable}]
e4620230
JK
27
28set libfile "${testfile}-lib"
29set libsrc ${libfile}.c
e4620230 30
c7075ad5
PA
31set final_file "${testfile}-final"
32set final_src ${final_file}.c
e4620230 33
4c93b1db 34if [get_compiler_info] {
e4620230
JK
35 return -1
36}
37
c7075ad5
PA
38# Return the binary suffix appended to program and library names to
39# make each testcase variant unique.
40proc make_binsuffix {resolver_attr resolver_debug final_debug} {
41 return "$resolver_attr-$resolver_debug-$final_debug"
e4620230
JK
42}
43
c7075ad5
PA
44# Compile the testcase. RESOLVER_ATTR is true if we're testing with
45# an ifunc resolver that has a different name from the user symbol,
46# specified with GCC's __attribute__ ifunc. RESOLVER_DEBUG is true
47# iff the resolver was compiled with debug info. FINAL_DEBUG is true
48# iff the target function was compiled with debug info.
49proc build {resolver_attr resolver_debug final_debug} {
50 global srcdir subdir srcfile binfile
51 global libsrc lib_so libfile
52 global exec_opts executable
53 global hex gdb_prompt
54 global final_file final_src
55
56 set suffix [make_binsuffix $resolver_attr $resolver_debug $final_debug]
57
58 set lib_so [standard_output_file ${libfile}-$suffix.so]
59 # $lib_o must not have {debug}, it would override the STT_GNU_IFUNC ELF markers.
60 set lib_o [standard_output_file ${libfile}-$suffix.o]
61
62 set exec_opts [list debug shlib=$lib_so]
63
64 set lib_opts {}
65 set final_opts {}
66
67 if {$resolver_attr} {
68 lappend lib_opts "additional_flags=-DIFUNC_RESOLVER_ATTR"
69 }
70
71 if {$resolver_debug} {
72 lappend lib_opts "debug"
73 }
74
75 if {$final_debug} {
76 lappend final_opts "debug"
77 }
e4620230 78
f9e48344 79 set final_o [standard_output_file $final_file-$suffix.o]
c7075ad5
PA
80
81 if { [gdb_compile_shlib ${srcdir}/${subdir}/$libsrc \
82 $lib_so $lib_opts] != ""
83 || [gdb_compile ${srcdir}/${subdir}/$final_src \
84 $final_o object $final_opts] != ""
85 || [gdb_compile [list ${srcdir}/${subdir}/$srcfile $final_o] \
86 $binfile-$suffix executable $exec_opts] != ""} {
87 untested "failed to compile testcase"
88 return 0
89 }
e4620230 90
ae59b1da 91 return 1
e4620230
JK
92}
93
c7075ad5
PA
94# Test setting a breakpoint on a ifunc function before and after the
95# ifunc is resolved. For the description of RESOLVER_ATTR,
96# RESOLVER_DEBUG and FINAL_DEBUG, see the "build" procedure above.
97proc_with_prefix set-break {resolver_attr resolver_debug final_debug} {
98 global binfile libfile lib_so
99 global hex decimal
100 global gdb_prompt
101
102 set suffix [make_binsuffix $resolver_attr $resolver_debug $final_debug]
103
104 set lib_so [standard_output_file ${libfile}-$suffix.so]
105 clean_restart $binfile-$suffix
106 gdb_load_shlib ${lib_so}
107
108 if ![runto_main] then {
109 fail "can't run to main"
110 return 1
111 }
112
79188d8d
PA
113 gdb_breakpoint [gdb_get_line_number "break-at-call"]
114 gdb_continue_to_breakpoint "break-at-call" ".*break-at-call.*"
115
c7075ad5
PA
116 set ws "\[ \t\]+"
117 set dot "\\.?"
e4620230 118
c7075ad5
PA
119 if {$resolver_attr} {
120 set gnu_ifunc_resolver "gnu_ifunc_resolver"
121 } else {
122 set gnu_ifunc_resolver "gnu_ifunc"
123 }
e4620230 124
c7075ad5
PA
125 if {!$resolver_debug} {
126 set gnu_ifunc_resolver "${dot}${gnu_ifunc_resolver}"
127 }
e4620230 128
c7075ad5
PA
129 if {!$final_debug} {
130 set final "${dot}final"
131 } else {
132 set final "final"
133 }
e4620230 134
c7075ad5
PA
135 with_test_prefix "before resolving" {
136 delete_breakpoints
137 gdb_test "break gnu_ifunc" \
138 "Breakpoint $decimal at gnu-indirect-function resolver at $hex"
139 gdb_test "info breakpoints" \
140 "$decimal${ws}STT_GNU_IFUNC resolver${ws}keep${ws}y${ws}$hex <${gnu_ifunc_resolver}>"
79188d8d
PA
141
142 # Make the breakpoint conditional on a condition that always
143 # fails. This is so that when the ifunc-resolver breakpoint
144 # triggers, GDB resumes the program immediately.
145 gdb_test_no_output "condition \$bpnum 0"
c7075ad5 146 }
e1b2624a 147
c7075ad5
PA
148 global final_src
149
150 with_test_prefix "resolve" {
c7075ad5
PA
151 gdb_breakpoint [gdb_get_line_number "break-at-exit"]
152 gdb_continue_to_breakpoint "break-at-exit" ".*break-at-exit.*"
e1b2624a 153 }
c7075ad5
PA
154
155 with_test_prefix "after resolving" {
c7075ad5
PA
156 if {!$final_debug} {
157 # Set a breakpoint both at the ifunc, and at the ifunc's
158 # target. GDB should resolve both to the same address.
159 # Start with the ifunc's target.
160 set addr "-"
161 set test "break final"
162 # Extract the address without the leading "0x", because
163 # addresses in "info break" output include leading 0s
164 # (like "0x0000ADDR").
165 set hex_number {[0-9a-fA-F][0-9a-fA-F]*}
166 gdb_test_multiple $test $test {
167 -re "Breakpoint .* at 0x($hex_number)\r\n$gdb_prompt $" {
168 set addr $expect_out(1,string)
169 pass $test
170 }
171 }
172
173 # Now set a break at the ifunc.
174 gdb_test "break gnu_ifunc" "Breakpoint .* at 0x$addr"
175 set location "$decimal${ws}breakpoint${ws}keep${ws}y${ws}0x0*$addr${ws}<${final}\\+.*>"
176 } else {
177 set lineno -1
178 set test "break final"
179 gdb_test_multiple $test $test {
180 -re "Breakpoint .* at $hex: file .*$final_src, line ($decimal)\\.\r\n$gdb_prompt $" {
181 set lineno $expect_out(1,string)
182 pass $test
183 }
184 }
185 gdb_test "break gnu_ifunc" "Breakpoint .* at $hex: file .*$final_src, line $lineno\\."
186 set location "$decimal${ws}breakpoint${ws}keep${ws}y${ws}$hex in final at .*$final_src:$lineno"
187 }
79188d8d
PA
188
189 # The first location here is for the breakpoint that was set
190 # before the ifunc was resolved. It should be resolved by
191 # now, and it should have the exact same address/line as the
192 # other two locations.
193 gdb_test "info breakpoints" "$location\r\n.*$location\r\n$location"
e1b2624a
AA
194 }
195}
196
c7075ad5
PA
197# Misc GNU ifunc tests. For the description of RESOLVER_ATTR,
198# RESOLVER_DEBUG and FINAL_DEBUG, see the "build" procedure above.
199proc misc_tests {resolver_attr resolver_debug final_debug} {
200 global srcdir subdir srcfile binfile
201 global libsrc lib_so libfile
202 global exec_opts executable
203 global hex gdb_prompt
204 global final_file final_src
205
206 set suffix [make_binsuffix $resolver_attr $resolver_debug $final_debug]
207
208 if {$resolver_attr} {
209 set gnu_ifunc_resolver "gnu_ifunc_resolver"
210 } else {
211 set gnu_ifunc_resolver "gnu_ifunc"
212 }
213
214 set dot "\\.?"
e1b2624a 215
c7075ad5
PA
216 if {!$resolver_debug} {
217 set gnu_ifunc_resolver "${dot}${gnu_ifunc_resolver}"
218 }
e4620230 219
c7075ad5
PA
220 if {!$final_debug} {
221 set final "${dot}final"
222 } else {
223 set final "final"
224 }
e4620230 225
c7075ad5 226 # Start with a fresh gdb.
e4620230 227
c7075ad5
PA
228 clean_restart $binfile-$suffix
229 gdb_load_shlib ${lib_so}
e4620230 230
c7075ad5
PA
231 if ![runto_main] then {
232 fail "can't run to main"
233 return 1
234 }
e4620230 235
c7075ad5
PA
236 # The "if" condition is artifical to test regression of a former patch.
237 gdb_breakpoint "[gdb_get_line_number "break-at-nextcall"] if i && (int) gnu_ifunc (i) != 42"
e4620230 238
c7075ad5
PA
239 gdb_breakpoint [gdb_get_line_number "break-at-call"]
240 gdb_continue_to_breakpoint "break-at-call" ".*break-at-call.*"
e4620230 241
c7075ad5 242 # Test GDB will automatically indirect the call.
e4620230 243
c7075ad5
PA
244 if {!$resolver_debug && !$final_debug} {
245 gdb_test "p gnu_ifunc()" \
246 "'${dot}final' has unknown return type; cast the call to its declared return type"
247 gdb_test "p gnu_ifunc (3)" \
248 "'${dot}final' has unknown return type; cast the call to its declared return type"
249 gdb_test "p (int) gnu_ifunc (3)" " = 4"
250 } else {
251 gdb_test "p gnu_ifunc()" "Too few arguments in function call\\."
252 gdb_test "p gnu_ifunc (3)" " = 4"
253 }
e4620230 254
c7075ad5
PA
255 # Test that the resolver received its argument.
256
257 set actual_hwcap "0x0"
258 set test "info auxv"
259 gdb_test_multiple $test $test {
260 -re "\r\n\\d+\\s+AT_HWCAP\[^\r\n\]+($hex)\r\n.*$gdb_prompt $" {
261 set actual_hwcap $expect_out(1,string)
262 }
263 -re ".*$gdb_prompt $" {
264 pass "$test (no HWCAP)"
265 }
266 }
e4620230 267
c7075ad5 268 gdb_test "p/x resolver_hwcap" "= $actual_hwcap" "resolver received HWCAP"
e4620230 269
c7075ad5 270 # Test GDB will skip the gnu_ifunc resolver on first call.
e4620230 271
c7075ad5
PA
272 # Even if the resolver has debug info, stepping into an ifunc call
273 # should skip the resolver.
274 if {!$final_debug} {
275 # Make GDB stop stepping even if it steps into a function with
276 # no debug info.
277 gdb_test_no_output "set step-mode on"
278 gdb_test "step" "$hex in ${dot}final \\\(\\\)"
279 } else {
280 gdb_test "step" "\r\nfinal .*"
281 }
282
283 # Test GDB will not break before the final chosen implementation.
284
285 # Also test a former patch regression:
286 # Continuing.
287 # Error in testing breakpoint condition:
288 # Attempt to take address of value not located in memory.
289 #
290 # Breakpoint 2, main () at ./gdb.base/gnu-ifunc.c:33
291
292 gdb_test "continue" \
293 "Continuing.\r\n\r\nBreakpoint .* (at|in) .*break-at-nextcall.*" \
294 "continue to break-at-nextcall"
295
296 gdb_breakpoint "gnu_ifunc"
297
298 gdb_continue_to_breakpoint "nextcall gnu_ifunc"
299
300 gdb_test "frame" \
301 "#0 +(0x\[0-9a-f\]+ in +)?${final} \\(.*" "nextcall gnu_ifunc skipped"
302
303 # Check any commands not doing an inferior call access the address of the
304 # STT_GNU_IFUNC resolver, not the target function.
305
306 if {[istarget powerpc64-*] && [is_lp64_target]} {
307 # With only minimal symbols GDB provides the function descriptors. With
308 # full debug info the function code would be displayed.
309 }
310
311 gdb_test "p gnu_ifunc" \
312 " = {<text gnu-indirect-function variable, no debug info>} 0x\[0-9a-f\]+ <${gnu_ifunc_resolver}>" \
313 "p gnu_ifunc executing"
314 gdb_test "info sym gnu_ifunc" \
315 "${gnu_ifunc_resolver} in section .*" \
316 "info sym gnu_ifunc executing"
317
318 set test "info addr gnu_ifunc"
319 if {!$resolver_attr && $resolver_debug} {
320 gdb_test_multiple $test $test {
321 -re "Symbol \"gnu_ifunc\" is a function at address (0x\[0-9a-f\]+).*$gdb_prompt $" {
322 pass $test
323 }
324 }
325 } else {
326 gdb_test_multiple $test $test {
327 -re "Symbol \"gnu_ifunc\" is at (0x\[0-9a-f\]+) in .*$gdb_prompt $" {
328 pass $test
329 }
330 }
331 }
332 gdb_test "info sym $expect_out(1,string)" \
333 "${gnu_ifunc_resolver} in section .*" \
334 "info sym <gnu_ifunc-address>"
335
336 # Test calling the resolver directly instead of the ifunc symbol.
337 # Can only do that if the ifunc and the ifunc resolver have
338 # different names.
339 if {$resolver_attr} {
340 if {$resolver_debug} {
341 if {[istarget powerpc64-*] && [is_lp64_target]} {
342 gdb_test "p gnu_ifunc_resolver(0)" \
343 " = \\(int \\(\\*\\)\\(int\\)\\) @$hex: $hex <${final}>"
344 } else {
345 gdb_test "p gnu_ifunc_resolver(0)" \
346 " = \\(int \\(\\*\\)\\(int\\)\\) $hex <final>"
347 }
348 } else {
349 gdb_test "p gnu_ifunc_resolver(0)" \
350 "'${gnu_ifunc_resolver}' has unknown return type; cast the call to its declared return type"
351 gdb_test "p (void *) gnu_ifunc_resolver(0)" \
352 " = \\(void \\*\\) $hex <${final}>"
353 }
e4620230
JK
354 }
355}
e4620230 356
c7075ad5
PA
357# Test all the combinations of:
358#
359# - An ifunc resolver with the same name as the ifunc symbol vs an
360# ifunc resolver with a different name as the ifunc symbol.
361#
362# - ifunc resolver compiled with and without debug info. This ensures
363# that GDB understands that a function not a regular function by
364# looking at the STT_GNU_IFUNC type in the elf symbols. DWARF has
365# no way to express the STT_GNU_IFUNC type.
366#
367# - ifunc target function (resolved) compiled with and without debug
368# info.
369foreach_with_prefix resolver_attr {0 1} {
370 foreach_with_prefix resolver_debug {0 1} {
371 foreach_with_prefix final_debug {0 1} {
ca98345e
SL
372 if { [build $resolver_attr $resolver_debug $final_debug] != 0 } {
373 misc_tests $resolver_attr $resolver_debug $final_debug
374 set-break $resolver_attr $resolver_debug $final_debug
375 }
c7075ad5
PA
376 }
377 }
378}
e4620230
JK
379
380# Test statically linked ifunc resolving during inferior start.
381# https://bugzilla.redhat.com/show_bug.cgi?id=624967
382
c7075ad5
PA
383with_test_prefix "static" {
384 # Compile $staticbinfile separately as it may exit on error
385 # (ld/12595).
386
387 set lib_o [standard_output_file ${libfile}.o]
388 set final_o [standard_output_file ${final_file}.o]
389 if { [gdb_compile ${srcdir}/${subdir}/$libsrc $lib_o object {}] != ""
390 || [gdb_compile ${srcdir}/${subdir}/$final_src $final_o object {}] != ""
391 || [gdb_compile "${srcdir}/${subdir}/$srcfile $lib_o $final_o" \
392 $staticbinfile executable {debug}] != "" } {
393 untested "failed to compile second testcase"
394 return -1
395 }
e4620230 396
c7075ad5 397 clean_restart $staticexecutable
e4620230 398
c7075ad5
PA
399 gdb_breakpoint "gnu_ifunc"
400 gdb_breakpoint "main"
401 gdb_run_cmd
402 gdb_test "" "Breakpoint \[0-9\]*, main .*" "static gnu_ifunc"
403}
This page took 0.921757 seconds and 4 git commands to generate.