1 # Copyright
(C
) 2009-2019 Free Software Foundation
, Inc.
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.
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.
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
/>.
16 if {[skip_shlib_tests
]} {
20 if {[skip_ifunc_tests
]} {
25 set staticexecutable $
{testfile
}-static
26 set staticbinfile
[standard_output_file $
{staticexecutable
}]
28 set libfile
"${testfile}-lib"
29 set libsrc $
{libfile
}.c
31 set final_file
"${testfile}-final"
32 set final_src $
{final_file
}.c
34 if [get_compiler_info
] {
38 #
Return the binary suffix appended to
program and library names to
39 # make each testcase variant unique.
40 proc make_binsuffix
{resolver_attr resolver_debug final_debug
} {
41 return "$resolver_attr-$resolver_debug-$final_debug"
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.
49 proc build
{resolver_attr resolver_debug final_debug
} {
50 global srcdir subdir srcfile binfile
51 global libsrc lib_so libfile
52 global exec_opts executable
54 global final_file final_src
56 set suffix
[make_binsuffix $resolver_attr $resolver_debug $final_debug
]
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
]
62 set exec_opts
[list debug shlib
=$lib_so
]
68 lappend lib_opts
"additional_flags=-DIFUNC_RESOLVER_ATTR"
71 if {$resolver_debug
} {
72 lappend lib_opts
"debug"
76 lappend final_opts
"debug"
79 set final_o
[standard_output_file $final_file
-$suffix.o
]
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"
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.
97 proc_with_prefix
set-break {resolver_attr resolver_debug final_debug
} {
98 global binfile libfile lib_so
102 set suffix
[make_binsuffix $resolver_attr $resolver_debug $final_debug
]
104 set lib_so
[standard_output_file $
{libfile
}-$suffix.so
]
105 clean_restart $binfile
-$suffix
106 gdb_load_shlib $
{lib_so
}
108 if ![runto_main
] then {
109 fail
"can't run to main"
113 gdb_breakpoint
[gdb_get_line_number
"break-at-call"]
114 gdb_continue_to_breakpoint
"break-at-call" ".*break-at-call.*"
119 if {$resolver_attr
} {
120 set gnu_ifunc_resolver
"gnu_ifunc_resolver"
122 set gnu_ifunc_resolver
"gnu_ifunc"
125 if {!$resolver_debug
} {
126 set gnu_ifunc_resolver
"${dot}${gnu_ifunc_resolver}"
130 set final
"${dot}final"
135 with_test_prefix
"before resolving" {
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}>"
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"
150 with_test_prefix
"resolve" {
151 gdb_breakpoint
[gdb_get_line_number
"break-at-exit"]
152 gdb_continue_to_breakpoint
"break-at-exit" ".*break-at-exit.*"
155 with_test_prefix
"after resolving" {
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.
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
)
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}\\+.*>"
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
)
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"
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"
197 # Misc GNU ifunc tests.
For the description of RESOLVER_ATTR
,
198 # RESOLVER_DEBUG and FINAL_DEBUG
, see the
"build" procedure above.
199 proc 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
206 set suffix
[make_binsuffix $resolver_attr $resolver_debug $final_debug
]
208 if {$resolver_attr
} {
209 set gnu_ifunc_resolver
"gnu_ifunc_resolver"
211 set gnu_ifunc_resolver
"gnu_ifunc"
216 if {!$resolver_debug
} {
217 set gnu_ifunc_resolver
"${dot}${gnu_ifunc_resolver}"
221 set final
"${dot}final"
226 # Start with a fresh gdb.
228 clean_restart $binfile
-$suffix
229 gdb_load_shlib $
{lib_so
}
231 if ![runto_main
] then {
232 fail
"can't run to main"
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"
239 gdb_breakpoint
[gdb_get_line_number
"break-at-call"]
240 gdb_continue_to_breakpoint
"break-at-call" ".*break-at-call.*"
242 # Test GDB will automatically indirect the
call.
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"
251 gdb_test
"p gnu_ifunc()" "Too few arguments in function call\\."
252 gdb_test
"p gnu_ifunc (3)" " = 4"
255 # Test that the resolver received its
argument.
257 set actual_hwcap
"0x0"
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
)
263 -re
".*$gdb_prompt $" {
264 pass
"$test (no HWCAP)"
268 gdb_test
"p/x resolver_hwcap" "= $actual_hwcap" "resolver received HWCAP"
270 # Test GDB will skip the gnu_ifunc resolver
on first
call.
272 # Even
if the resolver has debug
info, stepping into an ifunc
call
273 # should skip the resolver.
275 # Make GDB stop stepping even
if it steps into a function with
277 gdb_test_no_output
"set step-mode on"
278 gdb_test
"step" "$hex in ${dot}final \\\(\\\)"
280 gdb_test
"step" "\r\nfinal .*"
283 # Test GDB will not
break before the final chosen implementation.
285 # Also test a former patch regression
:
287 # Error in testing breakpoint condition
:
288 # Attempt to take address of value not located in memory.
290 # Breakpoint
2, main
() at .
/gdb.base
/gnu
-ifunc.c
:33
292 gdb_test
"continue" \
293 "Continuing.\r\n\r\nBreakpoint .* (at|in) .*break-at-nextcall.*" \
294 "continue to break-at-nextcall"
296 gdb_breakpoint
"gnu_ifunc"
298 gdb_continue_to_breakpoint
"nextcall gnu_ifunc"
301 "#0 +(0x\[0-9a-f\]+ in +)?${final} \\(.*" "nextcall gnu_ifunc skipped"
303 # Check
any commands not doing an inferior
call access the address of the
304 # STT_GNU_IFUNC resolver
, not the target function.
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.
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"
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 $" {
326 gdb_test_multiple $test $test
{
327 -re
"Symbol \"gnu_ifunc\" is at (0x\[0-9a-f\]+) in .*$gdb_prompt $" {
332 gdb_test
"info sym $expect_out(1,string)" \
333 "${gnu_ifunc_resolver} in section .*" \
334 "info sym <gnu_ifunc-address>"
336 # Test calling the resolver directly instead of the ifunc symbol.
337 # Can only
do that
if the ifunc and the ifunc resolver have
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}>"
345 gdb_test
"p gnu_ifunc_resolver(0)" \
346 " = \\(int \\(\\*\\)\\(int\\)\\) $hex <final>"
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}>"
357 # Test all the combinations of
:
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.
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.
367 #
- ifunc target function
(resolved
) compiled with and without debug
369 foreach_with_prefix resolver_attr
{0 1} {
370 foreach_with_prefix resolver_debug
{0 1} {
371 foreach_with_prefix final_debug
{0 1} {
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
380 # Test statically linked ifunc resolving during inferior start.
381 # https
://bugzilla.redhat.com
/show_bug.cgi?id
=624967
383 with_test_prefix
"static" {
384 #
Compile $staticbinfile separately as it may exit
on error
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"
397 clean_restart $staticexecutable
399 gdb_breakpoint
"gnu_ifunc"
400 gdb_breakpoint
"main"
402 gdb_test
"" "Breakpoint \[0-9\]*, main .*" "static gnu_ifunc"