Re: ld plugin bfd_make_readable leak
[binutils-gdb.git] / gdb / testsuite / gdb.arch / mips16-thunks.exp
blob6a888d5f30f2c553b55ad5778ff0189320f6be15
1 # Copyright 2012-2024 Free Software Foundation, Inc.
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.
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.
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/>.
16 # Contributed by Mentor Graphics, written by Maciej W. Rozycki.
18 # Test MIPS16 thunk support.
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.
28 require {istarget "mips*-*-*"}
30 # A helper to set caller's SRCFILE and OBJFILE based on FILENAME and SUFFIX.
31 proc set_src_and_obj { filename { suffix "" } } {
32     upvar srcfile srcfile
33     upvar objfile objfile
34     global srcdir
35     global subdir
37     if {![string equal "$suffix" ""]} {
38         set suffix "-$suffix"
39     }
40     set srcfile ${srcdir}/${subdir}/${filename}.c
41     set objfile [standard_output_file ${filename}${suffix}.o]
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.
47 set testname mips16-thunks-main
49 set_src_and_obj mips16-thunks-inmain
50 set options [list debug nowarnings additional_flags=-mips16]
51 set objfiles ${objfile}
52 gdb_compile ${srcfile} ${objfile} object ${options}
54 set_src_and_obj mips16-thunks-main
55 set options [list debug nowarnings additional_flags=-mips16]
56 lappend objfiles ${objfile}
57 gdb_compile ${srcfile} ${objfile} object ${options}
59 set binfile [standard_output_file ${testname}]
60 set options [list debug nowarnings]
61 if {[gdb_compile ${objfiles} ${binfile} executable ${options}] != ""} {
62     unsupported "no MIPS16 support in the toolchain."
63     return
65 clean_restart ${testname}
66 gdb_breakpoint inmain
67 gdb_run_cmd
68 gdb_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 $" {
76                 unsupported "no MIPS16 support in the processor."
77                 return
78             }
79             default {
80                 unsupported "no MIPS16 support in the processor."
81                 return
82             }
83         }
84     }
85     -re "$gdb_prompt $" {
86         unsupported "no MIPS16 support in the processor."
87         return
88     }
89     default {
90         unsupported "no MIPS16 support in the processor."
91         return
92     }
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.
99 set testname mips16-thunks-pic
100 set picflag ""
102 set_src_and_obj mips16-thunks-inmain pic
103 set options [list \
104     debug nowarnings additional_flags=-mips16 additional_flags=-fPIC]
105 set objfiles ${objfile}
106 gdb_compile ${srcfile} ${objfile} object ${options}
108 set_src_and_obj mips16-thunks-main pic
109 set options [list \
110     debug nowarnings additional_flags=-mips16 additional_flags=-fPIC]
111 lappend objfiles ${objfile}
112 gdb_compile ${srcfile} ${objfile} object ${options}
114 set binfile [standard_output_file ${testname}]
115 set options [list debug nowarnings additional_flags=-fPIC]
116 if {[gdb_compile ${objfiles} ${binfile} executable ${options}] == ""} {
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."
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.
156 set testname mips16-thunks-sin
158 set_src_and_obj mips16-thunks-sinmain
159 set options [list debug nowarnings additional_flags=-mips16]
160 set objfiles ${objfile}
161 gdb_compile ${srcfile} ${objfile} object ${options}
163 set_src_and_obj mips16-thunks-sin
164 set options [list debug nowarnings additional_flags=-mno-mips16]
165 lappend objfiles ${objfile}
166 gdb_compile ${srcfile} ${objfile} object ${options}
168 set_src_and_obj mips16-thunks-sinmips16
169 set options [list debug nowarnings additional_flags=-mips16]
170 lappend objfiles ${objfile}
171 gdb_compile ${srcfile} ${objfile} object ${options}
173 set_src_and_obj mips16-thunks-sinfrob
174 set options [list \
175     debug nowarnings additional_flags=-mno-mips16 ${picflag}]
176 lappend objfiles ${objfile}
177 gdb_compile ${srcfile} ${objfile} object ${options}
179 set_src_and_obj mips16-thunks-sinfrob16
180 set options [list \
181     debug nowarnings additional_flags=-mips16 ${picflag}]
182 lappend objfiles ${objfile}
183 gdb_compile ${srcfile} ${objfile} object ${options}
185 set binfile [standard_output_file ${testname}]
186 set options [list debug nowarnings]
187 gdb_compile ${objfiles} ${binfile} executable ${options}
188 clean_restart ${testname}
189 if {![runto_main]} {
190     return
193 # Build some useful regular expressions out of a list of functions FUNCS
194 # to be used to match against backtraces.
195 proc build_frames_re { funcs } {
196     upvar anyframe anyframe
197     upvar frames frames
198     upvar frame frame
199     upvar func func
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     }
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.
218 proc step_through { id funcs } {
219     global gdb_prompt
221     set func [lindex $funcs 0]
222     build_frames_re "$funcs"
224     set msg "single-stepping through \"${func}\" ($id)"
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 ""
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.
264 proc finish_through { id funcs } {
265     global gdb_prompt
267     set func [lindex $funcs 0]
268     build_frames_re "$funcs"
270     set msg "finishing \"${func}\" ($id)"
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 ""
289 # Report PASS if VAL is equal to EXP, otherwise report FAIL, using MSG.
290 proc pass_if_eq { val exp msg } {
291     if {[string equal "$val" "$exp"]} {
292         pass "$msg"
293     } else {
294         fail "$msg"
295     }
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.
303 proc finish_if_ne { id func want funcs } {
304     if {![string equal "$func" "$want"]} {
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"
314 # Now single-step through the program, making sure all thunks are correctly
315 # stepped over and omitted from backtraces.
317 set id 1
318 set func [step_through $id [list main]]
319 pass_if_eq "$func" sinfrob16 "stepping from \"main\" into \"sinfrob16\" ($id)"
321 incr id
322 set func [step_through $id [list sinfrob16 main]]
323 set func [finish_if_ne $id "$func" main [list sinfrob16 main]]
324 pass_if_eq "$func" main "stepping from \"sinfrob16\" back to \"main\" ($id)"
326 incr id
327 set func [step_through $id [list main]]
328 pass_if_eq "$func" sinfrob "stepping from \"main\" into \"sinfrob\" ($id)"
330 incr id
331 set func [step_through $id [list sinfrob main]]
332 set func [finish_if_ne $id "$func" main [list sinfrob main]]
333 pass_if_eq "$func" main "stepping from \"sinfrob\" back to \"main\" ($id)"
335 # 5
336 incr id
337 set func [step_through $id [list main]]
338 pass_if_eq "$func" sinhelper "stepping from \"main\" into \"sinhelper\" ($id)"
340 incr id
341 set func [step_through $id [list sinhelper main]]
342 set func [finish_if_ne $id "$func" sinfrob16 [list sinhelper main]]
343 pass_if_eq "$func" sinfrob16 \
344     "stepping from \"sinhelper\" into \"sinfrob16\" ($id)"
346 incr id
347 set func [step_through $id [list sinfrob16 sinhelper main]]
348 set func [finish_if_ne $id "$func" sinhelper [list sinfrob16 sinhelper main]]
349 pass_if_eq "$func" sinhelper \
350     "stepping from \"sinfrob16\" back to \"sinhelper\" ($id)"
352 incr id
353 set func [step_through $id [list sinhelper main]]
354 pass_if_eq "$func" sinfrob "stepping from \"sinhelper\" into \"sinfrob\" ($id)"
356 incr id
357 set func [step_through $id [list sinfrob sinhelper main]]
358 set func [finish_if_ne $id "$func" sinhelper [list sinfrob sinhelper main]]
359 pass_if_eq "$func" sinhelper \
360     "stepping from \"sinfrob\" back to \"sinhelper\" ($id)"
362 # 10
363 incr id
364 set func [step_through $id [list sinhelper main]]
365 pass_if_eq "$func" sinmips16 \
366     "stepping from \"sinhelper\" into \"sinmips16\" ($id)"
368 incr id
369 set func [step_through $id [list sinmips16 sinhelper main]]
370 set func [finish_if_ne $id "$func" sinfrob16 [list sinmips16 sinhelper main]]
371 pass_if_eq "$func" sinfrob16 \
372     "stepping from \"sinmips16\" into \"sinfrob16\" ($id)"
374 incr id
375 set func [step_through $id [list sinfrob16 sinmips16 sinhelper main]]
376 set func [finish_if_ne $id "$func" sinmips16 \
377               [list sinfrob16 sinmips16 sinhelper main]]
378 pass_if_eq "$func" sinmips16 \
379     "stepping from \"sinfrob16\" back to \"sinmips16\" ($id)"
381 incr id
382 set func [step_through $id [list sinmips16 sinhelper main]]
383 pass_if_eq "$func" sinfrob "stepping from \"sinmips16\" into \"sinfrob\" ($id)"
385 incr id
386 set func [step_through $id [list sinfrob sinmips16 sinhelper main]]
387 set func [finish_if_ne $id "$func" sinhelper \
388               [list sinfrob sinmips16 sinhelper main]]
389 pass_if_eq "$func" sinmips16 \
390     "stepping from \"sinfrob\" back to \"sinmips16\" ($id)"
392 # 15
393 incr id
394 set func [step_through $id [list sinmips16 sinhelper main]]
395 pass_if_eq "$func" sinfrob16 \
396     "stepping from \"sinmips16\" into \"sinfrob16\" (indirectly) ($id)"
398 incr id
399 set func [step_through $id [list sinfrob16 sinmips16 sinhelper main]]
400 set func [finish_if_ne $id "$func" sinmips16 \
401               [list sinfrob16 sinmips16 sinhelper main]]
402 pass_if_eq "$func" sinmips16 \
403     "stepping from \"sinfrob16\" back to \"sinmips16\" (indirectly) ($id)"
405 incr id
406 set func [step_through $id [list sinmips16 sinhelper main]]
407 pass_if_eq "$func" sinfrob \
408     "stepping from \"sinmips16\" into \"sinfrob\" (indirectly) ($id)"
410 incr id
411 set func [step_through $id [list sinfrob sinmips16 sinhelper main]]
412 set func [finish_if_ne $id "$func" sinhelper \
413               [list sinfrob sinmips16 sinhelper main]]
414 pass_if_eq "$func" sinmips16 \
415     "stepping from \"sinfrob\" back to \"sinmips16\" (indirectly) ($id)"
417 incr id
418 set func [step_through $id [list sinmips16 sinhelper main]]
419 pass_if_eq "$func" sinhelper \
420     "stepping from \"sinmips16\" back to \"sinhelper\" ($id)"
422 # 20
423 incr id
424 set func [step_through $id [list sinhelper main]]
425 pass_if_eq "$func" main "stepping from \"sinhelper\" back to \"main\" ($id)"
427 incr id
428 set func [step_through $id [list main]]
429 pass_if_eq "$func" sinblah "stepping from \"main\" into \"sinblah\" ($id)"
431 incr id
432 set func [step_through $id [list sinblah main]]
433 set func [finish_if_ne $id "$func" main [list sinblah main]]
434 pass_if_eq "$func" main "stepping from \"sinblah\" back to \"main\" ($id)"
436 incr id
437 set func [step_through $id [list main]]
438 pass_if_eq "$func" sinblah16 "stepping from \"main\" into \"sinblah16\" ($id)"
440 incr id
441 set func [step_through $id [list sinblah16 main]]
442 set func [finish_if_ne $id "$func" main [list sinblah16 main]]
443 pass_if_eq "$func" main "stepping from \"sinblah16\" back to \"main\" ($id)"
445 # 25
446 incr id
447 set func [step_through $id [list main]]
448 pass_if_eq "$func" lsinhelper \
449     "stepping from \"main\" into \"lsinhelper\" ($id)"
451 incr id
452 set func [step_through $id [list lsinhelper main]]
453 set func [finish_if_ne $id "$func" sinblah [list lsinhelper main]]
454 pass_if_eq "$func" sinblah \
455     "stepping from \"lsinhelper\" into \"sinblah\" ($id)"
457 incr id
458 set func [step_through $id [list sinblah lsinhelper main]]
459 set func [finish_if_ne $id "$func" lsinhelper [list sinblah lsinhelper main]]
460 pass_if_eq "$func" lsinhelper \
461     "stepping from \"sinblah\" back to \"lsinhelper\" ($id)"
463 incr id
464 set func [step_through $id [list lsinhelper main]]
465 pass_if_eq "$func" sinblah16 \
466     "stepping from \"lsinhelper\" into \"sinblah16\" ($id)"
468 incr id
469 set func [step_through $id [list sinblah16 lsinhelper main]]
470 set func [finish_if_ne $id "$func" lsinhelper [list sinblah16 lsinhelper main]]
471 pass_if_eq "$func" lsinhelper \
472     "stepping from \"sinblah16\" back to \"lsinhelper\" ($id)"
474 # 30
475 incr id
476 set func [step_through $id [list lsinhelper main]]
477 pass_if_eq "$func" lsinmips16 \
478     "stepping from \"lsinhelper\" into \"lsinmips16\" ($id)"
480 incr id
481 set func [step_through $id [list lsinmips16 lsinhelper main]]
482 set func [finish_if_ne $id "$func" sinblah [list lsinmips16 lsinhelper main]]
483 pass_if_eq "$func" sinblah \
484     "stepping from \"lsinmips16\" into \"sinblah\" ($id)"
486 incr id
487 set func [step_through $id [list sinblah lsinmips16 lsinhelper main]]
488 set func [finish_if_ne $id "$func" lsinmips16 \
489               [list sinblah lsinmips16 lsinhelper main]]
490 pass_if_eq "$func" lsinmips16 \
491     "stepping from \"sinblah\" back to \"lsinmips16\" ($id)"
493 incr id
494 set func [step_through $id [list lsinmips16 lsinhelper main]]
495 pass_if_eq "$func" sinblah16 \
496     "stepping from \"lsinmips16\" into \"sinblah16\" ($id)"
498 incr id
499 set func [step_through $id [list sinblah16 lsinmips16 lsinhelper main]]
500 set func [finish_if_ne $id "$func" lsinhelper \
501               [list sinblah16 lsinmips16 lsinhelper main]]
502 pass_if_eq "$func" lsinmips16 \
503     "stepping from \"sinblah16\" back to \"lsinmips16\" ($id)"
505 # 35
506 incr id
507 set func [step_through $id [list lsinmips16 lsinhelper main]]
508 pass_if_eq "$func" sinblah \
509     "stepping from \"lsinmips16\" into \"sinblah\" (indirectly) ($id)"
511 incr id
512 set func [step_through $id [list sinblah lsinmips16 lsinhelper main]]
513 set func [finish_if_ne $id "$func" lsinmips16 \
514               [list sinblah lsinmips16 lsinhelper main]]
515 pass_if_eq "$func" lsinmips16 \
516     "stepping from \"sinblah\" back to \"lsinmips16\" (indirectly) ($id)"
518 incr id
519 set func [step_through $id [list lsinmips16 lsinhelper main]]
520 pass_if_eq "$func" sinblah16 \
521     "stepping from \"lsinmips16\" into \"sinblah16\" (indirectly) ($id)"
523 incr id
524 set func [step_through $id [list sinblah16 lsinmips16 lsinhelper main]]
525 set func [finish_if_ne $id "$func" lsinhelper \
526               [list sinblah16 lsinmips16 lsinhelper main]]
527 pass_if_eq "$func" lsinmips16 \
528     "stepping from \"sinblah16\" back to \"lsinmips16\" (indirectly) ($id)"
530 incr id
531 set func [step_through $id [list lsinmips16 lsinhelper main]]
532 pass_if_eq "$func" lsinhelper \
533     "stepping from \"lsinmips16\" back to \"lsinhelper\" ($id)"
535 # 40
536 incr id
537 set func [step_through $id [list lsinhelper main]]
538 pass_if_eq "$func" main "stepping from \"lsinhelper\" back to \"main\" ($id)"