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