]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/gdb.base/unwind-on-each-insn.exp
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.base / unwind-on-each-insn.exp
1 # Copyright 2022-2023 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 # Single step through a simple (empty) function that was compiled
17 # without DWARF debug information.
18 #
19 # At each instruction check that the frame-id, and frame base address,
20 # are calculated correctly.
21 #
22 # Additionally, check we can correctly unwind to the previous frame,
23 # and that the previous stack-pointer value, and frame base address
24 # value, can be calculated correctly.
25
26 standard_testfile .c -foo.c
27
28 if {[prepare_for_testing_full "failed to prepare" \
29 [list ${testfile} debug \
30 $srcfile {debug} $srcfile2 {nodebug}]]} {
31 return -1
32 }
33
34 if {![runto_main]} {
35 return 0
36 }
37
38 # Return a two element list, the first element is the stack-pointer
39 # value (from the $sp register), and the second element is the frame
40 # base address (from the 'info frame' output).
41 proc get_sp_and_fba { testname } {
42 with_test_prefix "get \$sp and frame base $testname" {
43 set sp [get_hexadecimal_valueof "\$sp" "*UNKNOWN*"]
44
45 set fba ""
46 gdb_test_multiple "info frame" "" {
47 -re -wrap ".*Stack level ${::decimal}, frame at ($::hex):.*" {
48 set fba $expect_out(1,string)
49 }
50 }
51
52 return [list $sp $fba]
53 }
54 }
55
56 # Return the frame-id of the current frame, collected using the 'maint
57 # print frame-id' command.
58 proc get_fid { } {
59 set fid ""
60 gdb_test_multiple "maint print frame-id" "" {
61 -re -wrap ".*frame-id for frame #${::decimal}: (.*)" {
62 set fid $expect_out(1,string)
63 }
64 }
65 return $fid
66 }
67
68 # Record the current stack-pointer, and the frame base address.
69 lassign [get_sp_and_fba "in main"] main_sp main_fba
70 set main_fid [get_fid]
71
72 # Now enter the foo function.
73 gdb_breakpoint "*foo"
74 gdb_continue_to_breakpoint "enter foo"
75
76 # Figure out the range of addresses covered by this function.
77 set last_addr_in_foo ""
78
79 # The disassembly of foo on PowerPC looks like:
80 # Dump of assembler code for function foo:
81 # => 0x00000000100006dc <+0>: std r31,-8(r1)
82 # 0x00000000100006e0 <+4>: stdu r1,-48(r1)
83 # 0x00000000100006e4 <+8>: mr r31,r1
84 # 0x00000000100006e8 <+12>: nop
85 # 0x00000000100006ec <+16>: addi r1,r31,48
86 # 0x00000000100006f0 <+20>: ld r31,-8(r1)
87 # 0x00000000100006f4 <+24>: blr
88 # 0x00000000100006f8 <+28>: .long 0x0
89 # 0x00000000100006fc <+32>: .long 0x0
90 # 0x0000000010000700 <+36>: .long 0x1000180
91 # End of assembler dump.
92 #
93 # The last instruction in function foo is blr. Need to ignore the .long
94 # entries following the blr instruction.
95
96 gdb_test_multiple "disassemble foo" "" {
97 -re "^disassemble foo\r\n" {
98 exp_continue
99 }
100
101 -re "^Dump of assembler code for function foo:\r\n" {
102 exp_continue
103 }
104
105 -re "^...($hex) \[<>+0-9:\s\t\]*\.long\[\s\t\]*\[^\r\n\]*\r\n" {
106 exp_continue
107 }
108
109 -re "^...($hex) \[^\r\n\]+\r\n" {
110 set last_addr_in_foo $expect_out(1,string)
111 exp_continue
112 }
113
114 -wrap -re "^End of assembler dump\\." {
115 gdb_assert { ![string equal $last_addr_in_foo ""] } \
116 "found some addresses in foo"
117 pass $gdb_test_name
118 }
119 }
120
121 # Record the current stack-pointer, and the frame base address.
122 lassign [get_sp_and_fba "in foo"] foo_sp foo_fba
123 set foo_fid [get_fid]
124
125 for { set i_count 1 } { true } { incr i_count } {
126 with_test_prefix "instruction ${i_count}" {
127
128 # The current stack-pointer value can legitimately change
129 # throughout the lifetime of a function, so we don't check the
130 # current stack-pointer value. But the frame base address
131 # should not change, so we do check for that.
132 lassign [get_sp_and_fba "for foo"] sp_value fba_value
133 gdb_assert { $fba_value == $foo_fba }
134
135 # The frame-id should never change within a function, so check
136 # that now.
137 set fid [get_fid]
138 gdb_assert { [string equal $fid $foo_fid] } \
139 "check frame-id matches"
140
141 # Check that the previous frame is 'main'.
142 gdb_test "bt 2" "\r\n#1\\s+\[^\r\n\]+ in main \\(\\) .*"
143
144 # Move up the stack (to main).
145 gdb_test "up" \
146 "\r\n#1\\s+\[^\r\n\]+ in main \\(\\) .*"
147
148 # Check we can unwind the stack-pointer and the frame base
149 # address correctly.
150 lassign [get_sp_and_fba "for main"] sp_value fba_value
151 gdb_assert { $sp_value == $main_sp }
152 gdb_assert { $fba_value == $main_fba }
153
154 # Check we have a consistent value for main's frame-id.
155 set fid [get_fid]
156 gdb_assert { [string equal $fid $main_fid] }
157
158 # Move back to the inner most frame.
159 gdb_test "frame 0" ".*"
160
161 set pc [get_hexadecimal_valueof "\$pc" "*UNKNOWN*"]
162 if { $pc == $last_addr_in_foo } {
163 break
164 }
165
166 if { $i_count > 100 } {
167 # We expect a handful of instructions, if we reach 100,
168 # something is going wrong. Avoid an infinite loop.
169 fail "exceeded max number of instructions"
170 break
171 }
172
173 gdb_test "stepi" ".*"
174 }
175 }