Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.arch / mips16-thunks.exp
CommitLineData
88b9d363 1# Copyright 2012-2022 Free Software Foundation, Inc.
14132e89
MR
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# Contributed by Mentor Graphics, written by Maciej W. Rozycki.
17
18# Test MIPS16 thunk support.
19
20# This should work on any targets that support MIPS16 execution, including
21# Linux and bare-iron ones, but not all of them do, for example MIPS16
22# support has been added to Linux relatively late in the game. Also besides
23# environment support, the target processor has to support the MIPS16 ASE.
24# Finally as of this writing MIPS16 support has only been implemented in the
25# toolchain for a subset of ABIs, so we need to check that a MIPS16
26# executable can be built and run at all before we attempt the actual test.
27
28if { ![istarget "mips*-*-*"] } then {
29 verbose "Skipping MIPS16 thunk support tests."
30 return
31}
32
33# A helper to set caller's SRCFILE and OBJFILE based on FILENAME and SUFFIX.
34proc set_src_and_obj { filename { suffix "" } } {
35 upvar srcfile srcfile
36 upvar objfile objfile
37 global srcdir
14132e89
MR
38 global subdir
39
40 if ![string equal "$suffix" ""] then {
41 set suffix "-$suffix"
42 }
43 set srcfile ${srcdir}/${subdir}/${filename}.c
3d0ec882 44 set objfile [standard_output_file ${filename}${suffix}.o]
14132e89
MR
45}
46
47# First check if a trivial MIPS16 program can be built and debugged. This
48# verifies environment and processor support, any failure here must be
49# classed as the lack of support.
50set testname mips16-thunks-main
51
52set_src_and_obj mips16-thunks-inmain
53set options [list debug nowarnings additional_flags=-mips16]
54set objfiles ${objfile}
55gdb_compile ${srcfile} ${objfile} object ${options}
56
57set_src_and_obj mips16-thunks-main
58set options [list debug nowarnings additional_flags=-mips16]
59lappend objfiles ${objfile}
60gdb_compile ${srcfile} ${objfile} object ${options}
61
3d0ec882 62set binfile [standard_output_file ${testname}]
14132e89
MR
63set options [list debug nowarnings]
64if { [gdb_compile ${objfiles} ${binfile} executable ${options}] != "" } then {
bc6c7af4 65 unsupported "no MIPS16 support in the toolchain."
14132e89
MR
66 return
67}
68clean_restart ${testname}
69gdb_breakpoint inmain
70gdb_run_cmd
71gdb_test_multiple "" "check for MIPS16 support in the processor" {
72 -re "Breakpoint 1.*inmain .*$gdb_prompt $" {
73 gdb_test_multiple "finish" \
74 "check for MIPS16 support in the processor" {
75 -re "Value returned is \\\$\[0-9\]+ = 0\[^0-9\].*$gdb_prompt $" {
76 verbose "MIPS16 support check successful."
77 }
78 -re "$gdb_prompt $" {
bc6c7af4 79 unsupported "no MIPS16 support in the processor."
14132e89
MR
80 return
81 }
82 default {
bc6c7af4 83 unsupported "no MIPS16 support in the processor."
14132e89
MR
84 return
85 }
86 }
87 }
88 -re "$gdb_prompt $" {
bc6c7af4 89 unsupported "no MIPS16 support in the processor."
14132e89
MR
90 return
91 }
92 default {
bc6c7af4 93 unsupported "no MIPS16 support in the processor."
14132e89
MR
94 return
95 }
96}
97
98# Check if MIPS16 PIC code can be built and debugged. We want to check
99# PIC and MIPS16 thunks are handled correctly together if possible, but
100# on targets that do not support PIC code, e.g. bare iron, we still want
101# to test the rest of functionality.
102set testname mips16-thunks-pic
103set picflag ""
104
105set_src_and_obj mips16-thunks-inmain pic
106set options [list \
107 debug nowarnings additional_flags=-mips16 additional_flags=-fPIC]
108set objfiles ${objfile}
109gdb_compile ${srcfile} ${objfile} object ${options}
110
111set_src_and_obj mips16-thunks-main pic
112set options [list \
113 debug nowarnings additional_flags=-mips16 additional_flags=-fPIC]
114lappend objfiles ${objfile}
115gdb_compile ${srcfile} ${objfile} object ${options}
116
3d0ec882 117set binfile [standard_output_file ${testname}]
14132e89
MR
118set options [list debug nowarnings additional_flags=-fPIC]
119if { [gdb_compile ${objfiles} ${binfile} executable ${options}] == "" } then {
120 clean_restart ${testname}
121 gdb_breakpoint inmain
122 gdb_run_cmd
123 gdb_test_multiple "" "check for PIC support" {
124 -re "Breakpoint 1.*inmain .*$gdb_prompt $" {
125 note "PIC support present, will make additional PIC thunk checks."
126 set picflag additional_flags=-fPIC
127 }
128 -re "$gdb_prompt $" {
129 note "No PIC support, skipping additional PIC thunk checks."
130 }
131 default {
132 note "No PIC support, skipping additional PIC thunk checks."
133 }
134 }
135} else {
136 note "No PIC support, skipping additional PIC thunk checks."
137}
138
139# OK, build the twisted executable. This program contains the following
140# MIPS16 thunks:
141# - __call_stub_fp_sin,
142# - __call_stub_fp_sinblah,
143# - __call_stub_fp_sinfrob,
144# - __call_stub_fp_sinhelper,
145# - __call_stub_lsinhelper,
146# - __fn_stub_lsinmips16,
147# - __fn_stub_sinblah16,
148# - __fn_stub_sinfrob16,
149# - __fn_stub_sinmips16,
150# - __mips16_call_stub_df_2,
151# - __mips16_ret_df.
152# Additionally, if PIC code is supported, it contains the following PIC thunks:
153# - .pic.__mips16_call_stub_df_2,
154# - .pic.__mips16_ret_df,
155# - .pic.sinblah,
156# - .pic.sinblah16,
157# - .pic.sinfrob,
158# - .pic.sinfrob16.
159set testname mips16-thunks-sin
160
161set_src_and_obj mips16-thunks-sinmain
162set options [list debug nowarnings additional_flags=-mips16]
163set objfiles ${objfile}
164gdb_compile ${srcfile} ${objfile} object ${options}
165
166set_src_and_obj mips16-thunks-sin
167set options [list debug nowarnings additional_flags=-mno-mips16]
168lappend objfiles ${objfile}
169gdb_compile ${srcfile} ${objfile} object ${options}
170
171set_src_and_obj mips16-thunks-sinmips16
172set options [list debug nowarnings additional_flags=-mips16]
173lappend objfiles ${objfile}
174gdb_compile ${srcfile} ${objfile} object ${options}
175
176set_src_and_obj mips16-thunks-sinfrob
177set options [list \
178 debug nowarnings additional_flags=-mno-mips16 ${picflag}]
179lappend objfiles ${objfile}
180gdb_compile ${srcfile} ${objfile} object ${options}
181
182set_src_and_obj mips16-thunks-sinfrob16
183set options [list \
184 debug nowarnings additional_flags=-mips16 ${picflag}]
185lappend objfiles ${objfile}
186gdb_compile ${srcfile} ${objfile} object ${options}
187
3d0ec882 188set binfile [standard_output_file ${testname}]
14132e89
MR
189set options [list debug nowarnings]
190gdb_compile ${objfiles} ${binfile} executable ${options}
191clean_restart ${testname}
192if ![runto_main] then {
193 fail "running test program, MIPS16 thunk tests aborted"
194 return
195}
196
197# Build some useful regular expressions out of a list of functions FUNCS
198# to be used to match against backtraces.
199proc build_frames_re { funcs } {
200 upvar anyframe anyframe
201 upvar frames frames
202 upvar frame frame
203 upvar func func
204
205 set fid 0
206 set argsandsource " +\\\(.*\\\) +at +\[^\r\n\]+\r\n"
207 set addrin "(?:\[^ \]+ +in +)?"
208 set anyframe "#${fid} +${addrin}(\[^ \]+)${argsandsource}"
209 set frame "#${fid} +${addrin}${func}${argsandsource}"
210 set frames "$frame"
211 foreach f [lrange $funcs 1 end] {
212 incr fid
213 append frames "#${fid} +${addrin}${f}${argsandsource}"
214 }
215}
216
217# Single-step through the function that is at the head of function list
218# FUNCS until a different function (frame) is reached. Before each step
219# check the backtrace against FUNCS. ID is used for reporting, to tell
220# apart different calls to this procedure for the same function. If
221# successful, then return the name of the function we have stopped in.
222proc step_through { id funcs } {
223 global gdb_prompt
224
225 set func [lindex $funcs 0]
226 build_frames_re "$funcs"
227
228 set msg "single-stepping through \"${func}\" ($id)"
229
230 # Arbitrarily limit the maximium number of steps made to avoid looping
231 # indefinitely in the case something goes wrong, increase as (if)
232 # necessary.
233 set count 8
234 while { $count > 0 } {
235 if { [gdb_test_multiple "backtrace" "$msg (backtrace)" {
236 -re "${frames}$gdb_prompt $" {
237 if { [gdb_test_multiple "step" "$msg (step)" {
238 -re "$gdb_prompt $" {
239 if { [gdb_test_multiple "frame" "$msg (frame)" {
240 -re "${frame}.*$gdb_prompt $" {
241 }
242 -re "${anyframe}.*$gdb_prompt $" {
243 pass "$msg"
244 return $expect_out(1,string)
245 }
246 }] != 0 } then {
247 return ""
248 }
249 }
250 }] != 0 } then {
251 return ""
252 }
253 }
254 }] != 0 } then {
255 return ""
256 }
257 incr count -1
258 }
259 fail "$msg (too many steps)"
260 return ""
261}
262
263# Finish the current function that must be one that is at the head of
264# function list FUNCS. Before that check the backtrace against FUNCS.
265# ID is used for reporting, to tell apart different calls to this
266# procedure for the same function. If successful, then return the name
267# of the function we have stopped in.
268proc finish_through { id funcs } {
269 global gdb_prompt
270
271 set func [lindex $funcs 0]
272 build_frames_re "$funcs"
273
274 set msg "finishing \"${func}\" ($id)"
275
276 gdb_test_multiple "backtrace" "$msg (backtrace)" {
277 -re "${frames}$gdb_prompt $" {
278 gdb_test_multiple "finish" "$msg (finish)" {
279 -re "Run till exit from ${frame}.*$gdb_prompt $" {
280 gdb_test_multiple "frame" "$msg (frame)" {
281 -re "${anyframe}.*$gdb_prompt $" {
282 pass "$msg"
283 return $expect_out(1,string)
284 }
285 }
286 }
287 }
288 }
289 }
290 return ""
291}
292
293# Report PASS if VAL is equal to EXP, otherwise report FAIL, using MSG.
294proc pass_if_eq { val exp msg } {
295 if [string equal "$val" "$exp"] then {
296 pass "$msg"
297 } else {
298 fail "$msg"
299 }
300}
301
302# Check if FUNC is equal to WANT. If not, then assume that we have stepped
303# into a library call. In this case finish it, then step out of the caller.
304# ID is used for reporting, to tell apart different calls to this procedure
305# for the same function. If successful, then return the name of the
306# function we have stopped in.
307proc finish_if_ne { id func want funcs } {
308 if ![string equal "$func" "$want"] then {
309 set call "$func"
310 set want [lindex $funcs 0]
311 set func [finish_through "$id" [linsert $funcs 0 "$func"]]
312 pass_if_eq "$func" "$want" "\"${call}\" finishing to \"${want}\" ($id)"
313 set func [step_through "$id" $funcs]
314 }
315 return "$func"
316}
317
318# Now single-step through the program, making sure all thunks are correctly
319# stepped over and omitted from backtraces.
320
321set id 1
322set func [step_through $id [list main]]
323pass_if_eq "$func" sinfrob16 "stepping from \"main\" into \"sinfrob16\" ($id)"
324
325incr id
326set func [step_through $id [list sinfrob16 main]]
327set func [finish_if_ne $id "$func" main [list sinfrob16 main]]
328pass_if_eq "$func" main "stepping from \"sinfrob16\" back to \"main\" ($id)"
329
330incr id
331set func [step_through $id [list main]]
332pass_if_eq "$func" sinfrob "stepping from \"main\" into \"sinfrob\" ($id)"
333
334incr id
335set func [step_through $id [list sinfrob main]]
336set func [finish_if_ne $id "$func" main [list sinfrob main]]
337pass_if_eq "$func" main "stepping from \"sinfrob\" back to \"main\" ($id)"
338
339# 5
340incr id
341set func [step_through $id [list main]]
342pass_if_eq "$func" sinhelper "stepping from \"main\" into \"sinhelper\" ($id)"
343
344incr id
345set func [step_through $id [list sinhelper main]]
346set func [finish_if_ne $id "$func" sinfrob16 [list sinhelper main]]
347pass_if_eq "$func" sinfrob16 \
348 "stepping from \"sinhelper\" into \"sinfrob16\" ($id)"
349
350incr id
351set func [step_through $id [list sinfrob16 sinhelper main]]
352set func [finish_if_ne $id "$func" sinhelper [list sinfrob16 sinhelper main]]
353pass_if_eq "$func" sinhelper \
354 "stepping from \"sinfrob16\" back to \"sinhelper\" ($id)"
355
356incr id
357set func [step_through $id [list sinhelper main]]
358pass_if_eq "$func" sinfrob "stepping from \"sinhelper\" into \"sinfrob\" ($id)"
359
360incr id
361set func [step_through $id [list sinfrob sinhelper main]]
362set func [finish_if_ne $id "$func" sinhelper [list sinfrob sinhelper main]]
363pass_if_eq "$func" sinhelper \
364 "stepping from \"sinfrob\" back to \"sinhelper\" ($id)"
365
366# 10
367incr id
368set func [step_through $id [list sinhelper main]]
369pass_if_eq "$func" sinmips16 \
370 "stepping from \"sinhelper\" into \"sinmips16\" ($id)"
371
372incr id
373set func [step_through $id [list sinmips16 sinhelper main]]
374set func [finish_if_ne $id "$func" sinfrob16 [list sinmips16 sinhelper main]]
375pass_if_eq "$func" sinfrob16 \
376 "stepping from \"sinmips16\" into \"sinfrob16\" ($id)"
377
378incr id
379set func [step_through $id [list sinfrob16 sinmips16 sinhelper main]]
380set func [finish_if_ne $id "$func" sinmips16 \
381 [list sinfrob16 sinmips16 sinhelper main]]
382pass_if_eq "$func" sinmips16 \
383 "stepping from \"sinfrob16\" back to \"sinmips16\" ($id)"
384
385incr id
386set func [step_through $id [list sinmips16 sinhelper main]]
387pass_if_eq "$func" sinfrob "stepping from \"sinmips16\" into \"sinfrob\" ($id)"
388
389incr id
390set func [step_through $id [list sinfrob sinmips16 sinhelper main]]
391set func [finish_if_ne $id "$func" sinhelper \
392 [list sinfrob sinmips16 sinhelper main]]
393pass_if_eq "$func" sinmips16 \
394 "stepping from \"sinfrob\" back to \"sinmips16\" ($id)"
395
396# 15
397incr id
398set func [step_through $id [list sinmips16 sinhelper main]]
399pass_if_eq "$func" sinfrob16 \
400 "stepping from \"sinmips16\" into \"sinfrob16\" (indirectly) ($id)"
401
402incr id
403set func [step_through $id [list sinfrob16 sinmips16 sinhelper main]]
404set func [finish_if_ne $id "$func" sinmips16 \
405 [list sinfrob16 sinmips16 sinhelper main]]
406pass_if_eq "$func" sinmips16 \
407 "stepping from \"sinfrob16\" back to \"sinmips16\" (indirectly) ($id)"
408
409incr id
410set func [step_through $id [list sinmips16 sinhelper main]]
411pass_if_eq "$func" sinfrob \
412 "stepping from \"sinmips16\" into \"sinfrob\" (indirectly) ($id)"
413
414incr id
415set func [step_through $id [list sinfrob sinmips16 sinhelper main]]
416set func [finish_if_ne $id "$func" sinhelper \
417 [list sinfrob sinmips16 sinhelper main]]
418pass_if_eq "$func" sinmips16 \
419 "stepping from \"sinfrob\" back to \"sinmips16\" (indirectly) ($id)"
420
421incr id
422set func [step_through $id [list sinmips16 sinhelper main]]
423pass_if_eq "$func" sinhelper \
424 "stepping from \"sinmips16\" back to \"sinhelper\" ($id)"
425
426# 20
427incr id
428set func [step_through $id [list sinhelper main]]
429pass_if_eq "$func" main "stepping from \"sinhelper\" back to \"main\" ($id)"
430
431incr id
432set func [step_through $id [list main]]
433pass_if_eq "$func" sinblah "stepping from \"main\" into \"sinblah\" ($id)"
434
435incr id
436set func [step_through $id [list sinblah main]]
437set func [finish_if_ne $id "$func" main [list sinblah main]]
438pass_if_eq "$func" main "stepping from \"sinblah\" back to \"main\" ($id)"
439
440incr id
441set func [step_through $id [list main]]
442pass_if_eq "$func" sinblah16 "stepping from \"main\" into \"sinblah16\" ($id)"
443
444incr id
445set func [step_through $id [list sinblah16 main]]
446set func [finish_if_ne $id "$func" main [list sinblah16 main]]
447pass_if_eq "$func" main "stepping from \"sinblah16\" back to \"main\" ($id)"
448
449# 25
450incr id
451set func [step_through $id [list main]]
452pass_if_eq "$func" lsinhelper \
453 "stepping from \"main\" into \"lsinhelper\" ($id)"
454
455incr id
456set func [step_through $id [list lsinhelper main]]
457set func [finish_if_ne $id "$func" sinblah [list lsinhelper main]]
458pass_if_eq "$func" sinblah \
459 "stepping from \"lsinhelper\" into \"sinblah\" ($id)"
460
461incr id
462set func [step_through $id [list sinblah lsinhelper main]]
463set func [finish_if_ne $id "$func" lsinhelper [list sinblah lsinhelper main]]
464pass_if_eq "$func" lsinhelper \
465 "stepping from \"sinblah\" back to \"lsinhelper\" ($id)"
466
467incr id
468set func [step_through $id [list lsinhelper main]]
469pass_if_eq "$func" sinblah16 \
470 "stepping from \"lsinhelper\" into \"sinblah16\" ($id)"
471
472incr id
473set func [step_through $id [list sinblah16 lsinhelper main]]
474set func [finish_if_ne $id "$func" lsinhelper [list sinblah16 lsinhelper main]]
475pass_if_eq "$func" lsinhelper \
476 "stepping from \"sinblah16\" back to \"lsinhelper\" ($id)"
477
478# 30
479incr id
480set func [step_through $id [list lsinhelper main]]
481pass_if_eq "$func" lsinmips16 \
482 "stepping from \"lsinhelper\" into \"lsinmips16\" ($id)"
483
484incr id
485set func [step_through $id [list lsinmips16 lsinhelper main]]
486set func [finish_if_ne $id "$func" sinblah [list lsinmips16 lsinhelper main]]
487pass_if_eq "$func" sinblah \
488 "stepping from \"lsinmips16\" into \"sinblah\" ($id)"
489
490incr id
491set func [step_through $id [list sinblah lsinmips16 lsinhelper main]]
492set func [finish_if_ne $id "$func" lsinmips16 \
493 [list sinblah lsinmips16 lsinhelper main]]
494pass_if_eq "$func" lsinmips16 \
495 "stepping from \"sinblah\" back to \"lsinmips16\" ($id)"
496
497incr id
498set func [step_through $id [list lsinmips16 lsinhelper main]]
499pass_if_eq "$func" sinblah16 \
500 "stepping from \"lsinmips16\" into \"sinblah16\" ($id)"
501
502incr id
503set func [step_through $id [list sinblah16 lsinmips16 lsinhelper main]]
504set func [finish_if_ne $id "$func" lsinhelper \
505 [list sinblah16 lsinmips16 lsinhelper main]]
506pass_if_eq "$func" lsinmips16 \
507 "stepping from \"sinblah16\" back to \"lsinmips16\" ($id)"
508
509# 35
510incr id
511set func [step_through $id [list lsinmips16 lsinhelper main]]
512pass_if_eq "$func" sinblah \
513 "stepping from \"lsinmips16\" into \"sinblah\" (indirectly) ($id)"
514
515incr id
516set func [step_through $id [list sinblah lsinmips16 lsinhelper main]]
517set func [finish_if_ne $id "$func" lsinmips16 \
518 [list sinblah lsinmips16 lsinhelper main]]
519pass_if_eq "$func" lsinmips16 \
520 "stepping from \"sinblah\" back to \"lsinmips16\" (indirectly) ($id)"
521
522incr id
523set func [step_through $id [list lsinmips16 lsinhelper main]]
524pass_if_eq "$func" sinblah16 \
525 "stepping from \"lsinmips16\" into \"sinblah16\" (indirectly) ($id)"
526
527incr id
528set func [step_through $id [list sinblah16 lsinmips16 lsinhelper main]]
529set func [finish_if_ne $id "$func" lsinhelper \
530 [list sinblah16 lsinmips16 lsinhelper main]]
531pass_if_eq "$func" lsinmips16 \
532 "stepping from \"sinblah16\" back to \"lsinmips16\" (indirectly) ($id)"
533
534incr id
535set func [step_through $id [list lsinmips16 lsinhelper main]]
536pass_if_eq "$func" lsinhelper \
537 "stepping from \"lsinmips16\" back to \"lsinhelper\" ($id)"
538
539# 40
540incr id
541set func [step_through $id [list lsinhelper main]]
542pass_if_eq "$func" main "stepping from \"lsinhelper\" back to \"main\" ($id)"
This page took 1.178865 seconds and 4 git commands to generate.