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