binutils-gdb/gdb/testsuite/gdb.base/until-trailing-insns.exp
Andrew Burgess ef7a6b977b gdb/testsuite: remove global gcc_compiled from gdb.exp
After this commit the gcc_compiled global is no longer exported from
lib/gdb.exp.  In theory we could switch over all uses of gcc_compiled
to instead call test_compiler_info directly, however, I have instead
added a new proc to gdb.exp: 'is_c_compiler_gcc'.  I've then updated
the testsuite to call this proc instead of using the global.

Having a new proc specifically for this task means that we have a
single consistent pattern for detecting gcc.  By wrapping this logic
within a proc that calls test_compiler_info, rather than using the
global, means that test scripts don't need to call get_compiler_info
before they read the global, simply calling the new proc does
everything in one go.

As a result I've been able to remove the get_compiler_info calls from
all the test scripts that I've touched in this commit.

In some of the tests e.g. gdb.dwarf2/*.exp, the $gcc_compiled flag was
being checked at the top of the script to decide if the whole script
should be skipped or not.  In these cases I've called the new proc
directly and removed all uses of gcc_compiled.

In other cases, e.g. most of the gdb.base scripts, there were many
uses of gcc_compiled.  In these cases I set a new global gcc_compiled
near the top of the script, and leave the rest of the script
unchanged.

There should be no changes in what is tested after this commit.
2022-06-24 15:07:28 +01:00

180 lines
6.1 KiB
Plaintext

# Copyright 2022 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 test sets up debug information for a loop as we see in some cases
# from clang-13. In this situation, instructions at both the start and end
# of the loop are associated (in the line table), with the header line of
# the loop (line 10 in the example below).
#
# At the end of the loop we see some instructions marked as not a statement,
# but still associated with the same loop header line. For example,
# consider the following C code:
#
# 10: for (i = 0; i < 10; ++i)
# 11: loop_body ();
# 12: other_stuff ();
#
# Transformed into the following pseudo-assembler, with associated line table:
#
# Address | Pseudo-Assembler | Line | Is-Statement?
#
# 0x100 | i = 0 | 10 | Yes
# 0x104 | loop_body () | 11 | Yes
# 0x108 | i = i + 1 | 10 | Yes
# 0x10c | if (i < 10): | 10 | No
# 0x110 | goto 0x104 | 10 | No
# 0x114 | other_stuff () | 12 | Yes
#
# Notice the two non-statement instructions at the end of the loop.
#
# The problem here is that when we reach address 0x108 and use 'until',
# hoping to leave the loop, GDB sets up a stepping range that runs from the
# start of the function (0x100 in our example) to the end of the current
# line table entry, that is 0x10c in our example. GDB then starts stepping
# forward.
#
# When 0x10c is reached GDB spots that we have left the stepping range, that
# the new location is not a statement, and that the new location is
# associated with the same source line number as the previous stepping
# range. GDB then sets up a new stepping range that runs from 0x10c to
# 0x114, and continues stepping forward.
#
# Within that stepping range the inferior hits the goto and loops back to
# address 0x104.
#
# At 0x104 GDB spots that we have left the previous stepping range, that the
# new address is marked as a statement, and that the new address is for a
# different source line. As a result, GDB stops and returns control to the
# user. This is not what the user was expecting, they expected GDB not to
# stop until they were outside of the loop.
#
# The fix is that, when the user issues the 'until' command, and GDB sets up
# the initial stepping range, GDB will check subsequent SALs to see if they
# are non-statements associated with the same line number. If they are then
# the end of the initial stepping range is pushed out to the end of the
# non-statement SALs.
#
# In our example above, the user is at 0x108 and uses 'until'. GDB now sets
# up a stepping range from the start of the function 0x100 to 0x114, the
# first address associated with a different line.
#
# Now as GDB steps around the loop it never leaves the initial stepping
# range. It is only when GDB exits the loop that we leave the stepping
# range, and the stepping finishes at address 0x114.
#
# This test checks this behaviour using the DWARF assembler.
load_lib dwarf.exp
# This test can only be run on targets which support DWARF-2 and use gas.
if {![dwarf2_support]} {
unsupported "dwarf2 support required for this test"
return 0
}
# The DWARF assembler requires the gcc compiler.
if {![is_c_compiler_gcc]} {
unsupported "gcc is required for this test"
return 0
}
standard_testfile .c .S
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
set asm_file [standard_output_file $srcfile2]
Dwarf::assemble $asm_file {
global srcdir subdir srcfile
declare_labels integer_label L
set int_size [get_sizeof "int" 4]
# Find start address and length for our functions.
lassign [function_range main [list ${srcdir}/${subdir}/$srcfile]] \
main_start main_len
set main_end "$main_start + $main_len"
cu {} {
compile_unit {
{language @DW_LANG_C}
{name until-trailing-isns.c}
{stmt_list $L DW_FORM_sec_offset}
{low_pc 0 addr}
} {
subprogram {
{external 1 flag}
{name main}
{low_pc $main_start addr}
{high_pc $main_len DW_FORM_data4}
}
}
}
lines {version 2 default_is_stmt 1} L {
include_dir "${srcdir}/${subdir}"
file_name "$srcfile" 1
# Generate a line table program. This mimicks clang-13's behavior
# of adding some !is_stmt at the end of a loop line, making until
# not work properly.
program {
DW_LNE_set_address $main_start
line [gdb_get_line_number "TAG: main prologue"]
DW_LNS_copy
DW_LNE_set_address loop_start
line [gdb_get_line_number "TAG: loop line"]
DW_LNS_copy
DW_LNE_set_address loop_condition
line [gdb_get_line_number "TAG: loop line"]
DW_LNS_negate_stmt
DW_LNS_copy
DW_LNE_set_address loop_code
line [gdb_get_line_number "TAG: loop code"]
DW_LNS_negate_stmt
DW_LNS_copy
DW_LNE_set_address loop_increment
line [gdb_get_line_number "TAG: loop line"]
DW_LNS_copy
DW_LNE_set_address loop_jump
line [gdb_get_line_number "TAG: loop line"]
DW_LNS_negate_stmt
DW_LNS_copy
DW_LNE_set_address main_return
line [gdb_get_line_number "TAG: main return"]
DW_LNS_negate_stmt
DW_LNS_copy
DW_LNE_set_address $main_end
line [expr [gdb_get_line_number "TAG: main return"] + 1]
DW_LNS_copy
DW_LNE_end_sequence
}
}
}
if { [prepare_for_testing "failed to prepare" ${testfile} \
[list $srcfile $asm_file] {nodebug} ] } {
return -1
}
if ![runto_main] {
return -1
}
gdb_test "next" ".* TAG: loop code .*" "inside the loop"
gdb_test "next" ".* TAG: loop line .*" "ending of loop"
gdb_test "until" ".* TAG: main return .*" "left loop"