blob: 91d03792a3e77d8b02c8f68c59303d7816a51a55 [file] [log] [blame] [edit]
# Copyright (C) 2024-2025 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/>.
# Check the 'maint info inline-frames' and 'maint info blocks'
# commands.
standard_testfile
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
{debug nopie}]} {
return -1
}
if {![runto normal_func]} {
return 0
}
# Make a pattern to match 'maint info blocks' output. ARGS is the
# list of function names we expect to see. If the function name
# starts with 'inline_func' then we expect to see an inline block,
# otherwise blocks are not expected to be inline.
proc make_blocks_result { args } {
set result \
[list \
"Blocks at $::hex:" \
" from objfile: \\\[\\(objfile \\*\\) $::hex\\\] [string_to_regexp $::binfile]" \
""\
"\\\[\\(block \\*\\) $::hex\\\] $::hex\\.\\.$::hex" \
" entry pc: $::hex" \
" is global block" \
".*" \
"\\\[\\(block \\*\\) $::hex\\\] $::hex\\.\\.$::hex" \
" entry pc: $::hex" \
" is static block" \
".*" ]
foreach func $args {
lappend result \
"\\\[\\(block \\*\\) $::hex\\\] $::hex\\.\\.$::hex" \
" entry pc: $::hex"
if { [string range $func 0 10] eq "inline_func" } {
lappend result" inline function: $func"
} else {
lappend result" function: $func"
}
lappend result ".*"
}
return [multi_line {*}$result]
}
gdb_test "maint info blocks" [make_blocks_result normal_func] \
"maint info blocks in normal_func only"
# Next forward until we find the call to inline_func_a(). The hope is
# that when we see the 'inline_func_a()' line this will be the start of
# the inlined function. This might not be the case on all
# architectures if the compiler needs to perform some preamble.
gdb_test_multiple "next" "next forward to inline_func_a" {
-re "^$decimal\\s+inline_func_a \\(\\);\r\n" {
# Consume the next prompt.
gdb_expect {
-re "^$gdb_prompt $" {}
}
pass $gdb_test_name
}
-re "^$decimal\\s+\[^\r\n\]+After inline function\[^\r\n\]+\r\n" {
# We've gone too far!
fail $gdb_test_name
}
-re "^$decimal\\s+\[^\r\n\]+\r\n" {
send_gdb "next\n"
exp_continue
}
-re "^\[^\r\n\]+\r\n" {
exp_continue
}
}
gdb_test "maint info blocks" [make_blocks_result normal_func \
inline_func_a inline_func_b] \
"maint info blocks when all blocks visible"
# View the inline frame information. This should display that we are
# at the start of inline_func_a() within normal_func().
gdb_test "maint info inline-frames" \
[multi_line \
"^Cached inline state information for thread $decimal\\." \
"program counter = $hex" \
"skipped frames = 2" \
" inline_func_b" \
" inline_func_a" \
"> normal_func"] \
"check inline-frames state when in normal_func"
# Step, we should now enter the inlined function.
gdb_test "step" ".*" \
"step to enter inline_func"
# And the inline-frames information should update.
gdb_test "maint info inline-frames" \
[multi_line \
"^Cached inline state information for thread $decimal\\." \
"program counter = $hex" \
"skipped frames = 1" \
" inline_func_b" \
"> inline_func_a" \
" normal_func"] \
"check inline-frames state when just entered inline_func_a"
# Record the current program counter.
set pc [get_hexadecimal_valueof "\$pc" "UNKNOWN"]
# Use the recorded $pc value to check inline frames.
gdb_test "maint info inline-frames $pc" \
[multi_line \
"^program counter = $hex" \
"skipped frames = 2" \
" inline_func_b" \
" inline_func_a" \
"> normal_func"] \
"check inline-frames state at recorded \$pc while at the \$pc"
# Step again, we should now enter inlined_func_b().
gdb_test "step" ".*" \
"step into inline_func_b"
gdb_test "maint info inline-frames" \
[multi_line \
"^Cached inline state information for thread $decimal\\." \
"program counter = $hex" \
"skipped frames = 0" \
"> inline_func_b" \
" inline_func_a" \
" normal_func"] \
"check inline-frames state when just entered inline_func_b"
gdb_test "maint info blocks" [make_blocks_result normal_func \
inline_func_a inline_func_b] \
"maint info blocks when all blocks still visible"
gdb_test "step" ".*" \
"step into the body of inline_func_b"
# Now we are no longer at the start of the inlined function we should
# no longer see normal_func() in the inline-frames information.
gdb_test "maint info inline-frames" \
[multi_line \
"^Cached inline state information for thread $decimal\\." \
"program counter = $hex" \
"skipped frames = 0" \
"> inline_func_b"] \
"check inline-frames state when within inline_func_b"
gdb_test "maint info blocks" [make_blocks_result normal_func \
inline_func_a inline_func_b] \
"maint info blocks within inline function, all blocks still visible"
# Use 'stepi' and check 'maint info inline-frames' still works.
gdb_test "stepi" ".*" "perform stepi"
gdb_test "maint info inline-frames" \
[multi_line \
"^Inline state information for thread $decimal\\." \
"program counter = $hex" \
"skipped frames = 0" \
"> inline_func_b"] \
"check inline-frames state when within inline_func_b after stepi"
gdb_test "maint info blocks" [make_blocks_result normal_func \
inline_func_a inline_func_b] \
"maint info blocks within inline function after stepi, all blocks still visible"
# Use the recorded $pc value to check inline frames.
gdb_test "maint info inline-frames $pc" \
[multi_line \
"^program counter = $hex" \
"skipped frames = 2" \
" inline_func_b" \
" inline_func_a" \
"> normal_func"] \
"check inline-frames state at recorded \$pc"
gdb_test "maint info blocks" [make_blocks_result normal_func \
inline_func_a inline_func_b] \
"maint info blocks using stored \$pc, inferior still running"
clean_restart
gdb_load $binfile
# Use the recorded $pc value to check inline frames when the inferior
# is not executing.
gdb_test "maint info inline-frames $pc" \
[multi_line \
"^program counter = $hex" \
"skipped frames = 2" \
" inline_func_b" \
" inline_func_a" \
"> normal_func"] \
"check inline-frames state at recorded \$pc before execution starts"
gdb_test "maint info blocks $pc" [make_blocks_result normal_func \
inline_func_a inline_func_b] \
"maint info blocks using stored \$pc, inferior not running"
# Trying to read the $pc from the current thread should fail if the
# inferior is not yet running.
gdb_test "maint info inline-frames" \
"^no inferior thread" \
"check inline-frames state of current thread before execution starts"
gdb_test "maint info blocks" "^no inferior thread" \
"maint info blocks with no \$pc and inferior not running"