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