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