]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/gdb.base/frame-selection.exp
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.base / frame-selection.exp
1 # Copyright 2018-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 # This tests GDB's frame selection as used by the 'frame',
17 # 'select-frame', and 'info frame' commands.
18
19 standard_testfile
20
21 if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}]} {
22 return -1
23 }
24
25 runto_main
26 gdb_breakpoint frame_2
27 gdb_continue_to_breakpoint frame_2
28
29 gdb_test "bt" "#0 frame_2.*#1 $hex in frame_1.*#2 $hex in main.*" "backtrace at breakpoint"
30
31 # Perform "info frame" to extract the frame's address.
32 proc get_frame_address { {testname ""} } {
33 global hex gdb_prompt
34
35 set frame_address "unknown"
36 set testname "get_frame_address: ${testname}"
37 gdb_test_multiple "info frame" $testname {
38 -re ", frame at ($hex):\r\n.*\r\n$gdb_prompt $" {
39 set frame_address $expect_out(1,string)
40 pass $testname
41 }
42 }
43
44 return $frame_address
45 }
46
47 # Passed a list of addresses. Return a new address that is not in the
48 # list by sorting the addresses and adding 0x10 to the highest
49 # address.
50 proc get_new_address { {addresses {}} } {
51 # Find the highest element in the list.
52 set elem [lindex [lsort -integer -decreasing $addresses] 0]
53
54 # Return a new address as a hex formatted string.
55 return [format "%#x" [expr $elem + 0x10]]
56 }
57
58
59 # Check that the current frame is at stack depth LEVEL, at frame
60 # address ADDRESS, and is in FUNCTION.
61 proc check_frame { level address function } {
62 global hex gdb_prompt
63
64 set re [multi_line \
65 "Stack level ${level}, frame at ($address):" \
66 ".* = $hex in ${function} \(\[^\r\n\]*\); saved .* = $hex" \
67 ".*\r\n$gdb_prompt $" ]
68
69 set testname "check frame level ${level}"
70 gdb_test_multiple "info frame" $testname {
71 -re $re {
72 pass $testname
73 }
74 }
75 }
76
77 # Select frame using level, but relying on this being the default
78 # action, so "frame 0" performs "frame level 0".
79 gdb_test "frame 0" "#0 frame_2.*"
80 set frame_0_address [ get_frame_address "frame 0" ]
81 gdb_test "frame 1" "#1 $hex in frame_1.*"
82 set frame_1_address [ get_frame_address "frame 1" ]
83 gdb_test "frame 2" "#2 $hex in main.*"
84 set frame_2_address [ get_frame_address "frame 2" ]
85 gdb_test "frame 3" "No frame at level 3\."
86
87 # Find an address that matches no frame.
88 set no_frame_address [ get_new_address [list $frame_0_address \
89 $frame_1_address \
90 $frame_2_address] ]
91
92 # Select frame using 'level' specification.
93 gdb_test "frame level 0" "#0 frame_2.*"
94 gdb_test "frame level 1" "#1 $hex in frame_1.*"
95 gdb_test "frame level 2" "#2 $hex in main.*"
96 gdb_test "frame level 3" "No frame at level 3\."
97
98 # Select frame by address.
99 gdb_test "frame address ${frame_0_address}" "#0 frame_2.*" \
100 "select frame 0 by address"
101 gdb_test "frame address ${frame_1_address}" "#1 $hex in frame_1.*" \
102 "select frame 1 by address"
103 gdb_test "frame address ${frame_2_address}" "#2 $hex in main.*" \
104 "select frame 2 by address"
105 gdb_test "frame address ${no_frame_address}" \
106 "No frame at address ${no_frame_address}\." \
107 "attempt to select a frame at an invalid address"
108
109 # Select frame by function.
110 gdb_test "frame function frame_2" "#0 frame_2.*"
111 gdb_test "frame function frame_1" "#1 $hex in frame_1.*"
112 gdb_test "frame function main" "#2 $hex in main.*"
113
114 # Check for a distinction between a known function not in the stack
115 # trace, and an unknown function.
116 gdb_test "frame function recursive" "No frame for function \"recursive\"."
117 gdb_test "frame function foo" "Function \"foo\" not defined."
118
119
120 with_test_prefix "select-frame, no keyword" {
121 gdb_test_no_output "select-frame 0"
122 check_frame "0" "${frame_0_address}" "frame_2"
123 gdb_test_no_output "select-frame 1"
124 check_frame "1" "${frame_1_address}" "frame_1"
125 gdb_test_no_output "select-frame 2"
126 check_frame "2" "${frame_2_address}" "main"
127 gdb_test "select-frame 3" "No frame at level 3\."
128 }
129
130 with_test_prefix "select-frame, keyword=level" {
131 gdb_test_no_output "select-frame level 0"
132 check_frame "0" "${frame_0_address}" "frame_2"
133 gdb_test_no_output "select-frame level 1"
134 check_frame "1" "${frame_1_address}" "frame_1"
135 gdb_test_no_output "select-frame level 2"
136 check_frame "2" "${frame_2_address}" "main"
137 gdb_test "select-frame level 3" "No frame at level 3\."
138 }
139
140 with_test_prefix "select-frame, keyword=address" {
141 gdb_test_no_output "select-frame address ${frame_0_address}" \
142 "select frame 0 by address"
143 check_frame "0" "${frame_0_address}" "frame_2"
144 gdb_test_no_output "select-frame address ${frame_1_address}" \
145 "select frame 1 by address"
146 check_frame "1" "${frame_1_address}" "frame_1"
147 gdb_test_no_output "select-frame address ${frame_2_address}" \
148 "select frame 2 by address"
149 check_frame "2" "${frame_2_address}" "main"
150 gdb_test "select-frame address ${no_frame_address}" \
151 "No frame at address ${no_frame_address}\." \
152 "select-frame for an invalid address"
153 }
154
155 with_test_prefix "select-frame, keyword=function" {
156 gdb_test_no_output "select-frame function frame_2"
157 check_frame "0" "${frame_0_address}" "frame_2"
158 gdb_test_no_output "select-frame function frame_1"
159 check_frame "1" "${frame_1_address}" "frame_1"
160 gdb_test_no_output "select-frame function main"
161 check_frame "2" "${frame_2_address}" "main"
162 }
163
164 # Check for a distinction between a known function not in the stack
165 # trace, and an unknown function.
166 gdb_test "select-frame function recursive" \
167 "No frame for function \"recursive\"."
168 gdb_test "select-frame function foo" \
169 "Function \"foo\" not defined."
170
171 # Now continue until we hit the breakpoint again.
172 with_test_prefix "second frame_2 breakpoint" {
173 gdb_continue_to_breakpoint frame_2
174 gdb_test "bt" \
175 "#0 frame_2.*#1 $hex in recursive.*#2 $hex in recursive.*#3 $hex in recursive.*#4 $hex in main.*" \
176 "backtrace at breakpoint with recursive frames"
177
178 # Check "frame function" when a function name occurs multiple times in
179 # the stack. The inner most (lowest level) should always be selected.
180 gdb_test "frame function frame_2" "#0 frame_2.*"
181 gdb_test "frame function recursive" "#1 $hex in recursive.*" \
182 "select frame for function recursive, first attempt"
183 gdb_test "frame function recursive" "#1 $hex in recursive.*" \
184 "select frame for function recursive, second attempt"
185 gdb_test "frame function main" "#4 $hex in main.*"
186 gdb_test "frame function recursive" "#1 $hex in recursive.*" \
187 "select frame for function recursive, third attempt"
188 }