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