]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/gdb.arch/mips16-thunks.exp
Update copyright year range in all GDB files
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.arch / mips16-thunks.exp
1 # Copyright 2012-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 # 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
28 if { ![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.
34 proc set_src_and_obj { filename { suffix "" } } {
35 upvar srcfile srcfile
36 upvar objfile objfile
37 global srcdir
38 global subdir
39
40 if ![string equal "$suffix" ""] then {
41 set suffix "-$suffix"
42 }
43 set srcfile ${srcdir}/${subdir}/${filename}.c
44 set objfile [standard_output_file ${filename}${suffix}.o]
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.
50 set testname mips16-thunks-main
51
52 set_src_and_obj mips16-thunks-inmain
53 set options [list debug nowarnings additional_flags=-mips16]
54 set objfiles ${objfile}
55 gdb_compile ${srcfile} ${objfile} object ${options}
56
57 set_src_and_obj mips16-thunks-main
58 set options [list debug nowarnings additional_flags=-mips16]
59 lappend objfiles ${objfile}
60 gdb_compile ${srcfile} ${objfile} object ${options}
61
62 set binfile [standard_output_file ${testname}]
63 set options [list debug nowarnings]
64 if { [gdb_compile ${objfiles} ${binfile} executable ${options}] != "" } then {
65 unsupported "no MIPS16 support in the toolchain."
66 return
67 }
68 clean_restart ${testname}
69 gdb_breakpoint inmain
70 gdb_run_cmd
71 gdb_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 $" {
79 unsupported "no MIPS16 support in the processor."
80 return
81 }
82 default {
83 unsupported "no MIPS16 support in the processor."
84 return
85 }
86 }
87 }
88 -re "$gdb_prompt $" {
89 unsupported "no MIPS16 support in the processor."
90 return
91 }
92 default {
93 unsupported "no MIPS16 support in the processor."
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.
102 set testname mips16-thunks-pic
103 set picflag ""
104
105 set_src_and_obj mips16-thunks-inmain pic
106 set options [list \
107 debug nowarnings additional_flags=-mips16 additional_flags=-fPIC]
108 set objfiles ${objfile}
109 gdb_compile ${srcfile} ${objfile} object ${options}
110
111 set_src_and_obj mips16-thunks-main pic
112 set options [list \
113 debug nowarnings additional_flags=-mips16 additional_flags=-fPIC]
114 lappend objfiles ${objfile}
115 gdb_compile ${srcfile} ${objfile} object ${options}
116
117 set binfile [standard_output_file ${testname}]
118 set options [list debug nowarnings additional_flags=-fPIC]
119 if { [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.
159 set testname mips16-thunks-sin
160
161 set_src_and_obj mips16-thunks-sinmain
162 set options [list debug nowarnings additional_flags=-mips16]
163 set objfiles ${objfile}
164 gdb_compile ${srcfile} ${objfile} object ${options}
165
166 set_src_and_obj mips16-thunks-sin
167 set options [list debug nowarnings additional_flags=-mno-mips16]
168 lappend objfiles ${objfile}
169 gdb_compile ${srcfile} ${objfile} object ${options}
170
171 set_src_and_obj mips16-thunks-sinmips16
172 set options [list debug nowarnings additional_flags=-mips16]
173 lappend objfiles ${objfile}
174 gdb_compile ${srcfile} ${objfile} object ${options}
175
176 set_src_and_obj mips16-thunks-sinfrob
177 set options [list \
178 debug nowarnings additional_flags=-mno-mips16 ${picflag}]
179 lappend objfiles ${objfile}
180 gdb_compile ${srcfile} ${objfile} object ${options}
181
182 set_src_and_obj mips16-thunks-sinfrob16
183 set options [list \
184 debug nowarnings additional_flags=-mips16 ${picflag}]
185 lappend objfiles ${objfile}
186 gdb_compile ${srcfile} ${objfile} object ${options}
187
188 set binfile [standard_output_file ${testname}]
189 set options [list debug nowarnings]
190 gdb_compile ${objfiles} ${binfile} executable ${options}
191 clean_restart ${testname}
192 if ![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.
199 proc 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.
222 proc 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.
268 proc 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.
294 proc 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.
307 proc 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
321 set id 1
322 set func [step_through $id [list main]]
323 pass_if_eq "$func" sinfrob16 "stepping from \"main\" into \"sinfrob16\" ($id)"
324
325 incr id
326 set func [step_through $id [list sinfrob16 main]]
327 set func [finish_if_ne $id "$func" main [list sinfrob16 main]]
328 pass_if_eq "$func" main "stepping from \"sinfrob16\" back to \"main\" ($id)"
329
330 incr id
331 set func [step_through $id [list main]]
332 pass_if_eq "$func" sinfrob "stepping from \"main\" into \"sinfrob\" ($id)"
333
334 incr id
335 set func [step_through $id [list sinfrob main]]
336 set func [finish_if_ne $id "$func" main [list sinfrob main]]
337 pass_if_eq "$func" main "stepping from \"sinfrob\" back to \"main\" ($id)"
338
339 # 5
340 incr id
341 set func [step_through $id [list main]]
342 pass_if_eq "$func" sinhelper "stepping from \"main\" into \"sinhelper\" ($id)"
343
344 incr id
345 set func [step_through $id [list sinhelper main]]
346 set func [finish_if_ne $id "$func" sinfrob16 [list sinhelper main]]
347 pass_if_eq "$func" sinfrob16 \
348 "stepping from \"sinhelper\" into \"sinfrob16\" ($id)"
349
350 incr id
351 set func [step_through $id [list sinfrob16 sinhelper main]]
352 set func [finish_if_ne $id "$func" sinhelper [list sinfrob16 sinhelper main]]
353 pass_if_eq "$func" sinhelper \
354 "stepping from \"sinfrob16\" back to \"sinhelper\" ($id)"
355
356 incr id
357 set func [step_through $id [list sinhelper main]]
358 pass_if_eq "$func" sinfrob "stepping from \"sinhelper\" into \"sinfrob\" ($id)"
359
360 incr id
361 set func [step_through $id [list sinfrob sinhelper main]]
362 set func [finish_if_ne $id "$func" sinhelper [list sinfrob sinhelper main]]
363 pass_if_eq "$func" sinhelper \
364 "stepping from \"sinfrob\" back to \"sinhelper\" ($id)"
365
366 # 10
367 incr id
368 set func [step_through $id [list sinhelper main]]
369 pass_if_eq "$func" sinmips16 \
370 "stepping from \"sinhelper\" into \"sinmips16\" ($id)"
371
372 incr id
373 set func [step_through $id [list sinmips16 sinhelper main]]
374 set func [finish_if_ne $id "$func" sinfrob16 [list sinmips16 sinhelper main]]
375 pass_if_eq "$func" sinfrob16 \
376 "stepping from \"sinmips16\" into \"sinfrob16\" ($id)"
377
378 incr id
379 set func [step_through $id [list sinfrob16 sinmips16 sinhelper main]]
380 set func [finish_if_ne $id "$func" sinmips16 \
381 [list sinfrob16 sinmips16 sinhelper main]]
382 pass_if_eq "$func" sinmips16 \
383 "stepping from \"sinfrob16\" back to \"sinmips16\" ($id)"
384
385 incr id
386 set func [step_through $id [list sinmips16 sinhelper main]]
387 pass_if_eq "$func" sinfrob "stepping from \"sinmips16\" into \"sinfrob\" ($id)"
388
389 incr id
390 set func [step_through $id [list sinfrob sinmips16 sinhelper main]]
391 set func [finish_if_ne $id "$func" sinhelper \
392 [list sinfrob sinmips16 sinhelper main]]
393 pass_if_eq "$func" sinmips16 \
394 "stepping from \"sinfrob\" back to \"sinmips16\" ($id)"
395
396 # 15
397 incr id
398 set func [step_through $id [list sinmips16 sinhelper main]]
399 pass_if_eq "$func" sinfrob16 \
400 "stepping from \"sinmips16\" into \"sinfrob16\" (indirectly) ($id)"
401
402 incr id
403 set func [step_through $id [list sinfrob16 sinmips16 sinhelper main]]
404 set func [finish_if_ne $id "$func" sinmips16 \
405 [list sinfrob16 sinmips16 sinhelper main]]
406 pass_if_eq "$func" sinmips16 \
407 "stepping from \"sinfrob16\" back to \"sinmips16\" (indirectly) ($id)"
408
409 incr id
410 set func [step_through $id [list sinmips16 sinhelper main]]
411 pass_if_eq "$func" sinfrob \
412 "stepping from \"sinmips16\" into \"sinfrob\" (indirectly) ($id)"
413
414 incr id
415 set func [step_through $id [list sinfrob sinmips16 sinhelper main]]
416 set func [finish_if_ne $id "$func" sinhelper \
417 [list sinfrob sinmips16 sinhelper main]]
418 pass_if_eq "$func" sinmips16 \
419 "stepping from \"sinfrob\" back to \"sinmips16\" (indirectly) ($id)"
420
421 incr id
422 set func [step_through $id [list sinmips16 sinhelper main]]
423 pass_if_eq "$func" sinhelper \
424 "stepping from \"sinmips16\" back to \"sinhelper\" ($id)"
425
426 # 20
427 incr id
428 set func [step_through $id [list sinhelper main]]
429 pass_if_eq "$func" main "stepping from \"sinhelper\" back to \"main\" ($id)"
430
431 incr id
432 set func [step_through $id [list main]]
433 pass_if_eq "$func" sinblah "stepping from \"main\" into \"sinblah\" ($id)"
434
435 incr id
436 set func [step_through $id [list sinblah main]]
437 set func [finish_if_ne $id "$func" main [list sinblah main]]
438 pass_if_eq "$func" main "stepping from \"sinblah\" back to \"main\" ($id)"
439
440 incr id
441 set func [step_through $id [list main]]
442 pass_if_eq "$func" sinblah16 "stepping from \"main\" into \"sinblah16\" ($id)"
443
444 incr id
445 set func [step_through $id [list sinblah16 main]]
446 set func [finish_if_ne $id "$func" main [list sinblah16 main]]
447 pass_if_eq "$func" main "stepping from \"sinblah16\" back to \"main\" ($id)"
448
449 # 25
450 incr id
451 set func [step_through $id [list main]]
452 pass_if_eq "$func" lsinhelper \
453 "stepping from \"main\" into \"lsinhelper\" ($id)"
454
455 incr id
456 set func [step_through $id [list lsinhelper main]]
457 set func [finish_if_ne $id "$func" sinblah [list lsinhelper main]]
458 pass_if_eq "$func" sinblah \
459 "stepping from \"lsinhelper\" into \"sinblah\" ($id)"
460
461 incr id
462 set func [step_through $id [list sinblah lsinhelper main]]
463 set func [finish_if_ne $id "$func" lsinhelper [list sinblah lsinhelper main]]
464 pass_if_eq "$func" lsinhelper \
465 "stepping from \"sinblah\" back to \"lsinhelper\" ($id)"
466
467 incr id
468 set func [step_through $id [list lsinhelper main]]
469 pass_if_eq "$func" sinblah16 \
470 "stepping from \"lsinhelper\" into \"sinblah16\" ($id)"
471
472 incr id
473 set func [step_through $id [list sinblah16 lsinhelper main]]
474 set func [finish_if_ne $id "$func" lsinhelper [list sinblah16 lsinhelper main]]
475 pass_if_eq "$func" lsinhelper \
476 "stepping from \"sinblah16\" back to \"lsinhelper\" ($id)"
477
478 # 30
479 incr id
480 set func [step_through $id [list lsinhelper main]]
481 pass_if_eq "$func" lsinmips16 \
482 "stepping from \"lsinhelper\" into \"lsinmips16\" ($id)"
483
484 incr id
485 set func [step_through $id [list lsinmips16 lsinhelper main]]
486 set func [finish_if_ne $id "$func" sinblah [list lsinmips16 lsinhelper main]]
487 pass_if_eq "$func" sinblah \
488 "stepping from \"lsinmips16\" into \"sinblah\" ($id)"
489
490 incr id
491 set func [step_through $id [list sinblah lsinmips16 lsinhelper main]]
492 set func [finish_if_ne $id "$func" lsinmips16 \
493 [list sinblah lsinmips16 lsinhelper main]]
494 pass_if_eq "$func" lsinmips16 \
495 "stepping from \"sinblah\" back to \"lsinmips16\" ($id)"
496
497 incr id
498 set func [step_through $id [list lsinmips16 lsinhelper main]]
499 pass_if_eq "$func" sinblah16 \
500 "stepping from \"lsinmips16\" into \"sinblah16\" ($id)"
501
502 incr id
503 set func [step_through $id [list sinblah16 lsinmips16 lsinhelper main]]
504 set func [finish_if_ne $id "$func" lsinhelper \
505 [list sinblah16 lsinmips16 lsinhelper main]]
506 pass_if_eq "$func" lsinmips16 \
507 "stepping from \"sinblah16\" back to \"lsinmips16\" ($id)"
508
509 # 35
510 incr id
511 set func [step_through $id [list lsinmips16 lsinhelper main]]
512 pass_if_eq "$func" sinblah \
513 "stepping from \"lsinmips16\" into \"sinblah\" (indirectly) ($id)"
514
515 incr id
516 set func [step_through $id [list sinblah lsinmips16 lsinhelper main]]
517 set func [finish_if_ne $id "$func" lsinmips16 \
518 [list sinblah lsinmips16 lsinhelper main]]
519 pass_if_eq "$func" lsinmips16 \
520 "stepping from \"sinblah\" back to \"lsinmips16\" (indirectly) ($id)"
521
522 incr id
523 set func [step_through $id [list lsinmips16 lsinhelper main]]
524 pass_if_eq "$func" sinblah16 \
525 "stepping from \"lsinmips16\" into \"sinblah16\" (indirectly) ($id)"
526
527 incr id
528 set func [step_through $id [list sinblah16 lsinmips16 lsinhelper main]]
529 set func [finish_if_ne $id "$func" lsinhelper \
530 [list sinblah16 lsinmips16 lsinhelper main]]
531 pass_if_eq "$func" lsinmips16 \
532 "stepping from \"sinblah16\" back to \"lsinmips16\" (indirectly) ($id)"
533
534 incr id
535 set func [step_through $id [list lsinmips16 lsinhelper main]]
536 pass_if_eq "$func" lsinhelper \
537 "stepping from \"lsinmips16\" back to \"lsinhelper\" ($id)"
538
539 # 40
540 incr id
541 set func [step_through $id [list lsinhelper main]]
542 pass_if_eq "$func" main "stepping from \"lsinhelper\" back to \"main\" ($id)"