blob: 410394c20dc0b48a7a14f7551f1a286f615c4e5a [file] [log] [blame] [edit]
# Copyright 2023-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/>.
# When stepping (forwards or backwards), GDB should step over the entire line
# and not just a particular entry in the line table. This test was added to
# verify the find_line_range_start function properly sets the step range for a
# line that consists of multiple statements, i.e. multiple entries in the line
# table. This test creates a DWARF line table that contains two entries for
# the same line to do the needed testing.
# This test can only be run on targets which support DWARF-2 and use gas.
load_lib dwarf.exp
require dwarf2_support
# The DWARF assembler requires the gcc compiler.
require is_c_compiler_gcc
# This test suitable only for process that can do reverse execution
require supports_reverse
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
# Find start address and length of program
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 map-to-same-line.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 the line table program with distinct source lines being
# mapped to the same line entry. Line 1, 5 and 8 contain 1 statement
# each. Line 2 contains 2 statements. Line 3 contains 3 statements.
program {
DW_LNE_set_address $main_start
line [gdb_get_line_number "TAG: main prologue"]
DW_LNS_copy
DW_LNE_set_address line1
line [gdb_get_line_number "TAG: line 1" ]
DW_LNS_copy
DW_LNE_set_address line2
line [gdb_get_line_number "TAG: line 2" ]
DW_LNS_copy
DW_LNE_set_address line3
line [gdb_get_line_number "TAG: line 2" ]
DW_LNS_copy
DW_LNE_set_address line4
line [gdb_get_line_number "TAG: line 3" ]
DW_LNS_copy
DW_LNE_set_address line5
line [gdb_get_line_number "TAG: line 3" ]
DW_LNS_copy
DW_LNE_set_address line6
line [gdb_get_line_number "TAG: line 3" ]
DW_LNS_copy
DW_LNE_set_address line7
line [gdb_get_line_number "TAG: line 5" ]
DW_LNS_copy
DW_LNE_set_address line8
line [gdb_get_line_number "TAG: line 8" ]
DW_LNS_copy
DW_LNE_set_address main_return
line [gdb_get_line_number "TAG: main return"]
DW_LNS_copy
DW_LNE_set_address $main_end
DW_LNE_end_sequence
}
}
}
if { [prepare_for_testing "failed to prepare" ${testfile} \
[list $srcfile $asm_file] {nodebug} ] } {
return -1
}
if { ![runto_main] } {
return
}
# Print the line table
gdb_test_multiple "maint info line-table ${testfile}" "" {
-re "\r\n$decimal\[ \t\]+$decimal\[ \t\]+($hex)\[ \t\]+Y\[^\r\n\]*" {
lappend is_stmt $expect_out(1,string)
exp_continue
}
-re -wrap "" {
}
}
# Do the reverse-step and reverse-next tests
foreach_with_prefix cmd {step next} {
gdb_test_no_output "record" "turn on process record, test $cmd"
set bp_main_return [gdb_get_line_number "TAG: main return" $srcfile]
gdb_breakpoint $srcfile:$bp_main_return
gdb_continue_to_breakpoint "run to end of main, reverse-$cmd test" ".*$srcfile:$bp_main_return.*"
gdb_test "display \$pc" ".*pc =.*" "display pc, reverse-$cmd test"
# At this point, GDB has already recorded the execution up until the return
# statement. Reverse and test if GDB transitions between lines in the
# expected order. It should reverse-step or reverse-next across lines 8,
# 5, 3, 2 and 1.
foreach line {8 5 3 2 1} {
gdb_test "reverse-$cmd" ".*TAG: line $line.*" "reverse $cmd to line $line"
}
if {$cmd =="step"} {
## Clean restart, test reverse-next command
clean_restart ${testfile}
if { ![runto_main] } {
return
}
}
}