1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
# Copyright 2024 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 is a follow on from the test:
# gdb.dwarf2/dw2-step-between-inline-func-blocks.exp
# It is worth reading that test before looking at this one.
#
# This test creates a function 'foo' that contains two inline
# functions 'bar' and 'baz'. The function 'foo' is split into two
# ranges. 'bar' is inline in the first range and 'baz' is inline in
# the second range, but critically, 'baz' starts at the very start of
# the second range. The functions are laid out like this:
#
# (A) (B)
# bar: |------------|
# baz: |---|
# foo: |------------------| |--------|
#
# When the inferior reaches address (A) we jump directly to point (B).
# At that point we expect GDB to tell the user that the inferior is in
# 'foo'. GDB should not automatically enter 'baz'.
#
# This tests exists because in
# dw2-step-between-inline-func-blocks.exp, the second range is another
# part of 'bar' and the jump from (A) to (B) is from one part of 'bar'
# to the next, in this case GDB does automatically reenter 'bar'.
# This test checks that GDB isn't too keen to reenter inline
# functions.
load_lib dwarf.exp
require dwarf2_support
# The source program use 'goto *ADDR' which is a GCC extension.
require is_c_compiler_gcc
standard_testfile
# This compiles the source file and starts and stops GDB, so run it
# before calling prepare_for_testing otherwise GDB will have exited.
get_func_info foo
# Make some DWARF for the test.
set asm_file [standard_output_file "$::testfile-dw.S"]
Dwarf::assemble $asm_file {
global srcfile
# Create local varibles like BAR_SRC_* containing the line number
# for the souce lines of 'foo' and 'bar' and 'baz'. These will be
# referenced in the generated DWARF.
for { set i 1 } { $i <= 2 } { incr i } {
set bar_src_$i [gdb_get_line_number "bar line $i"]
set baz_src_$i [gdb_get_line_number "baz line $i"]
}
for { set i 1 } { $i <= 4 } { incr i } {
set foo_src_$i [gdb_get_line_number "foo line $i"]
}
# More line numbers needed for the generated DWARF.
set foo_decl_line [gdb_get_line_number "foo decl line"]
set bar_decl_line [gdb_get_line_number "bar decl line"]
set baz_decl_line [gdb_get_line_number "baz decl line"]
# Labels used to link parts of the DWARF together.
declare_labels lines_table bar_label baz_label
declare_labels ranges_label_bar ranges_label_baz ranges_label_foo
cu { version 4 } {
compile_unit {
{producer "gcc"}
{language @DW_LANG_C}
{name ${srcfile}}
{comp_dir /tmp}
{stmt_list $lines_table DW_FORM_sec_offset}
{low_pc 0 addr}
} {
bar_label: subprogram {
{external 1 flag}
{name bar}
{decl_file 1 data1}
{decl_line $bar_decl_line data1}
{decl_column 1 data1}
{inline 3 data1}
}
baz_label: subprogram {
{external 1 flag}
{name baz}
{decl_file 1 data1}
{decl_line $baz_decl_line data1}
{decl_column 1 data1}
{inline 3 data1}
}
subprogram {
{name foo}
{decl_file 1 data1}
{decl_line $foo_decl_line data1}
{decl_column 1 data1}
{ranges ${ranges_label_foo} DW_FORM_sec_offset}
{external 1 flag}
} {
inlined_subroutine {
{abstract_origin %$bar_label}
{call_file 1 data1}
{call_line $foo_src_2 data1}
{ranges ${ranges_label_bar} DW_FORM_sec_offset}
}
inlined_subroutine {
{abstract_origin %$baz_label}
{call_file 1 data1}
{call_line $foo_src_3 data1}
{ranges ${ranges_label_baz} DW_FORM_sec_offset}
}
}
}
}
lines {version 2} lines_table {
include_dir "$::srcdir/$::subdir"
file_name "$srcfile" 1
program {
DW_LNE_set_address "foo_label"
line $foo_src_1
DW_LNS_copy
DW_LNE_set_address "foo_label_1"
line $foo_src_2
DW_LNS_copy
DW_LNE_set_address "foo_label_2"
line $bar_src_1
DW_LNS_copy
DW_LNE_set_address "foo_label_3"
line $bar_src_2
DW_LNS_copy
DW_LNE_set_address "foo_label_4"
DW_LNE_end_sequence
DW_LNE_set_address "foo_label_6"
line $baz_src_1
DW_LNS_copy
DW_LNE_set_address "foo_label_7"
line $baz_src_2
DW_LNS_copy
DW_LNS_negate_stmt
DW_LNE_set_address "foo_label_7"
line $foo_src_3
DW_LNS_copy
DW_LNS_negate_stmt
DW_LNE_set_address "foo_label_8"
line $foo_src_4
DW_LNS_copy
DW_LNE_set_address $::foo_end
DW_LNE_end_sequence
}
}
ranges { } {
ranges_label_bar: sequence {
range foo_label_2 foo_label_4
}
ranges_label_baz: sequence {
range foo_label_6 foo_label_7
}
ranges_label_foo: sequence {
range foo_label_1 foo_label_4
range foo_label_6 foo_label_9
}
}
}
if {[prepare_for_testing "failed to prepare" "${::testfile}" \
[list $srcfile $asm_file] {nodebug}]} {
return -1
}
if ![runto_main] {
return -1
}
gdb_breakpoint bar
gdb_continue_to_breakpoint "continue to bar line 1" \
".*bar line 1\[^\r\n\]+"
gdb_test "step" ".*bar line 2\[^\r\n\]+" \
"step to bar line 2"
# This is the interesting one. This step will take us over the goto
# and place the inferior at the start of the second range of 'foo' and
# at the start of 'baz'.
#
# As we started the step in 'bar', GDB should not reenter 'baz'.
gdb_test "step" ".*foo line 3\[^\r\n\]+" \
"step to foo line 3"
# The next step should allow the inferior to enter 'baz'.
gdb_test "step" ".*baz line 1\[^\r\n\]+" \
"step to baz line 1"
# The remaining steps take the inferior through 'baz' and back into
# 'foo'.
gdb_test "step" ".*baz line 2\[^\r\n\]+" \
"step to baz line 2"
gdb_test "step" ".*foo line 4\[^\r\n\]+" \
"step out of bar to foo line 4"
|