mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-21 04:42:53 +08:00
42a4f53d2b
This commit applies all changes made after running the gdb/copyright.py script. Note that one file was flagged by the script, due to an invalid copyright header (gdb/unittests/basic_string_view/element_access/char/empty.cc). As the file was copied from GCC's libstdc++-v3 testsuite, this commit leaves this file untouched for the time being; a patch to fix the header was sent to gcc-patches first. gdb/ChangeLog: Update copyright year range in all GDB files.
189 lines
6.9 KiB
Plaintext
189 lines
6.9 KiB
Plaintext
# Copyright 2018-2019 Free Software Foundation, Inc.
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# This tests GDB's frame selection as used by the 'frame',
|
|
# 'select-frame', and 'info frame' commands.
|
|
|
|
standard_testfile
|
|
|
|
if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}]} {
|
|
return -1
|
|
}
|
|
|
|
runto_main
|
|
gdb_breakpoint frame_2
|
|
gdb_continue_to_breakpoint frame_2
|
|
|
|
gdb_test "bt" "#0 frame_2.*#1 $hex in frame_1.*#2 $hex in main.*" "backtrace at breakpoint"
|
|
|
|
# Perform "info frame" to extract the frame's address.
|
|
proc get_frame_address { {testname ""} } {
|
|
global hex gdb_prompt
|
|
|
|
set frame_address "unknown"
|
|
set testname "get_frame_address: ${testname}"
|
|
gdb_test_multiple "info frame" $testname {
|
|
-re ", frame at ($hex):\r\n.*\r\n$gdb_prompt $" {
|
|
set frame_address $expect_out(1,string)
|
|
pass $testname
|
|
}
|
|
}
|
|
|
|
return $frame_address
|
|
}
|
|
|
|
# Passed a list of addresses. Return a new address that is not in the
|
|
# list by sorting the addresses and adding 0x10 to the highest
|
|
# address.
|
|
proc get_new_address { {addresses {}} } {
|
|
# Find the highest element in the list.
|
|
set elem [lindex [lsort -integer -decreasing $addresses] 0]
|
|
|
|
# Return a new address as a hex formatted string.
|
|
return [format "%#x" [expr $elem + 0x10]]
|
|
}
|
|
|
|
|
|
# Check that the current frame is at stack depth LEVEL, at frame
|
|
# address ADDRESS, and is in FUNCTION.
|
|
proc check_frame { level address function } {
|
|
global hex gdb_prompt
|
|
|
|
set re [multi_line \
|
|
"Stack level ${level}, frame at ($address):" \
|
|
".* = $hex in ${function} \(\[^\r\n\]*\); saved .* = $hex" \
|
|
".*\r\n$gdb_prompt $" ]
|
|
|
|
set testname "check frame level ${level}"
|
|
gdb_test_multiple "info frame" $testname {
|
|
-re $re {
|
|
pass $testname
|
|
}
|
|
}
|
|
}
|
|
|
|
# Select frame using level, but relying on this being the default
|
|
# action, so "frame 0" performs "frame level 0".
|
|
gdb_test "frame 0" "#0 frame_2.*"
|
|
set frame_0_address [ get_frame_address "frame 0" ]
|
|
gdb_test "frame 1" "#1 $hex in frame_1.*"
|
|
set frame_1_address [ get_frame_address "frame 1" ]
|
|
gdb_test "frame 2" "#2 $hex in main.*"
|
|
set frame_2_address [ get_frame_address "frame 2" ]
|
|
gdb_test "frame 3" "No frame at level 3\."
|
|
|
|
# Find an address that matches no frame.
|
|
set no_frame_address [ get_new_address [list $frame_0_address \
|
|
$frame_1_address \
|
|
$frame_2_address] ]
|
|
|
|
# Select frame using 'level' specification.
|
|
gdb_test "frame level 0" "#0 frame_2.*"
|
|
gdb_test "frame level 1" "#1 $hex in frame_1.*"
|
|
gdb_test "frame level 2" "#2 $hex in main.*"
|
|
gdb_test "frame level 3" "No frame at level 3\."
|
|
|
|
# Select frame by address.
|
|
gdb_test "frame address ${frame_0_address}" "#0 frame_2.*" \
|
|
"select frame 0 by address"
|
|
gdb_test "frame address ${frame_1_address}" "#1 $hex in frame_1.*" \
|
|
"select frame 1 by address"
|
|
gdb_test "frame address ${frame_2_address}" "#2 $hex in main.*" \
|
|
"select frame 2 by address"
|
|
gdb_test "frame address ${no_frame_address}" \
|
|
"No frame at address ${no_frame_address}\." \
|
|
"attempt to select a frame at an invalid address"
|
|
|
|
# Select frame by function.
|
|
gdb_test "frame function frame_2" "#0 frame_2.*"
|
|
gdb_test "frame function frame_1" "#1 $hex in frame_1.*"
|
|
gdb_test "frame function main" "#2 $hex in main.*"
|
|
|
|
# Check for a distinction between a known function not in the stack
|
|
# trace, and an unknown function.
|
|
gdb_test "frame function recursive" "No frame for function \"recursive\"."
|
|
gdb_test "frame function foo" "Function \"foo\" not defined."
|
|
|
|
|
|
with_test_prefix "select-frame, no keyword" {
|
|
gdb_test_no_output "select-frame 0"
|
|
check_frame "0" "${frame_0_address}" "frame_2"
|
|
gdb_test_no_output "select-frame 1"
|
|
check_frame "1" "${frame_1_address}" "frame_1"
|
|
gdb_test_no_output "select-frame 2"
|
|
check_frame "2" "${frame_2_address}" "main"
|
|
gdb_test "select-frame 3" "No frame at level 3\."
|
|
}
|
|
|
|
with_test_prefix "select-frame, keyword=level" {
|
|
gdb_test_no_output "select-frame level 0"
|
|
check_frame "0" "${frame_0_address}" "frame_2"
|
|
gdb_test_no_output "select-frame level 1"
|
|
check_frame "1" "${frame_1_address}" "frame_1"
|
|
gdb_test_no_output "select-frame level 2"
|
|
check_frame "2" "${frame_2_address}" "main"
|
|
gdb_test "select-frame level 3" "No frame at level 3\."
|
|
}
|
|
|
|
with_test_prefix "select-frame, keyword=address" {
|
|
gdb_test_no_output "select-frame address ${frame_0_address}" \
|
|
"select frame 0 by address"
|
|
check_frame "0" "${frame_0_address}" "frame_2"
|
|
gdb_test_no_output "select-frame address ${frame_1_address}" \
|
|
"select frame 1 by address"
|
|
check_frame "1" "${frame_1_address}" "frame_1"
|
|
gdb_test_no_output "select-frame address ${frame_2_address}" \
|
|
"select frame 2 by address"
|
|
check_frame "2" "${frame_2_address}" "main"
|
|
gdb_test "select-frame address ${no_frame_address}" \
|
|
"No frame at address ${no_frame_address}\." \
|
|
"select-frame for an invalid address"
|
|
}
|
|
|
|
with_test_prefix "select-frame, keyword=function" {
|
|
gdb_test_no_output "select-frame function frame_2"
|
|
check_frame "0" "${frame_0_address}" "frame_2"
|
|
gdb_test_no_output "select-frame function frame_1"
|
|
check_frame "1" "${frame_1_address}" "frame_1"
|
|
gdb_test_no_output "select-frame function main"
|
|
check_frame "2" "${frame_2_address}" "main"
|
|
}
|
|
|
|
# Check for a distinction between a known function not in the stack
|
|
# trace, and an unknown function.
|
|
gdb_test "select-frame function recursive" \
|
|
"No frame for function \"recursive\"."
|
|
gdb_test "select-frame function foo" \
|
|
"Function \"foo\" not defined."
|
|
|
|
# Now continue until we hit the breakpoint again.
|
|
with_test_prefix "second frame_2 breakpoint" {
|
|
gdb_continue_to_breakpoint frame_2
|
|
gdb_test "bt" \
|
|
"#0 frame_2.*#1 $hex in recursive.*#2 $hex in recursive.*#3 $hex in recursive.*#4 $hex in main.*" \
|
|
"backtrace at breakpoint with recursive frames"
|
|
|
|
# Check "frame function" when a function name occurs multiple times in
|
|
# the stack. The inner most (lowest level) should always be selected.
|
|
gdb_test "frame function frame_2" "#0 frame_2.*"
|
|
gdb_test "frame function recursive" "#1 $hex in recursive.*" \
|
|
"select frame for function recursive, first attempt"
|
|
gdb_test "frame function recursive" "#1 $hex in recursive.*" \
|
|
"select frame for function recursive, second attempt"
|
|
gdb_test "frame function main" "#4 $hex in main.*"
|
|
gdb_test "frame function recursive" "#1 $hex in recursive.*" \
|
|
"select frame for function recursive, third attempt"
|
|
}
|