1# Copyright 2018-2019 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 19standard_testfile 20 21if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}]} { 22 return -1 23} 24 25runto_main 26gdb_breakpoint frame_2 27gdb_continue_to_breakpoint frame_2 28 29gdb_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. 32proc 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. 50proc 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. 61proc 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". 79gdb_test "frame 0" "#0 frame_2.*" 80set frame_0_address [ get_frame_address "frame 0" ] 81gdb_test "frame 1" "#1 $hex in frame_1.*" 82set frame_1_address [ get_frame_address "frame 1" ] 83gdb_test "frame 2" "#2 $hex in main.*" 84set frame_2_address [ get_frame_address "frame 2" ] 85gdb_test "frame 3" "No frame at level 3\." 86 87# Find an address that matches no frame. 88set 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. 93gdb_test "frame level 0" "#0 frame_2.*" 94gdb_test "frame level 1" "#1 $hex in frame_1.*" 95gdb_test "frame level 2" "#2 $hex in main.*" 96gdb_test "frame level 3" "No frame at level 3\." 97 98# Select frame by address. 99gdb_test "frame address ${frame_0_address}" "#0 frame_2.*" \ 100 "select frame 0 by address" 101gdb_test "frame address ${frame_1_address}" "#1 $hex in frame_1.*" \ 102 "select frame 1 by address" 103gdb_test "frame address ${frame_2_address}" "#2 $hex in main.*" \ 104 "select frame 2 by address" 105gdb_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. 110gdb_test "frame function frame_2" "#0 frame_2.*" 111gdb_test "frame function frame_1" "#1 $hex in frame_1.*" 112gdb_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. 116gdb_test "frame function recursive" "No frame for function \"recursive\"." 117gdb_test "frame function foo" "Function \"foo\" not defined." 118 119 120with_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 130with_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 140with_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 155with_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. 166gdb_test "select-frame function recursive" \ 167 "No frame for function \"recursive\"." 168gdb_test "select-frame function foo" \ 169 "Function \"foo\" not defined." 170 171# Now continue until we hit the breakpoint again. 172with_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} 189