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