1# Copyright 2018-2019 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/>. 15load_lib dwarf.exp 16 17# Test DW_AT_ranges in the context of a subprogram scope. 18 19# This test can only be run on targets which support DWARF-2 and use gas. 20if {![dwarf2_support]} { 21 unsupported "dwarf2 support required for this test" 22 return 0 23} 24 25if [get_compiler_info] { 26 return -1 27} 28if !$gcc_compiled { 29 unsupported "gcc required for this test" 30 return 0 31} 32 33standard_testfile dw2-ranges-func.c dw2-ranges-func-dw.S 34 35# We need to know the size of integer and address types in order to 36# write some of the debugging info we'd like to generate. 37# 38# For that, we ask GDB by debugging our test program. Any program 39# would do, but since we already have it specifically for this 40# testcase, might as well use that. 41 42if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { 43 return -1 44} 45 46set asm_file [standard_output_file $srcfile2] 47Dwarf::assemble $asm_file { 48 global srcdir subdir srcfile srcfile2 49 declare_labels integer_label volatile_label func_ranges_label cu_ranges_label L 50 set int_size [get_sizeof "int" 4] 51 52 # Find start address and length for our functions. 53 lassign [function_range main [list ${srcdir}/${subdir}/$srcfile]] \ 54 main_start main_len 55 set main_end "$main_start + $main_len" 56 lassign [function_range foo [list ${srcdir}/${subdir}/$srcfile]] \ 57 foo_start foo_len 58 set foo_end "$foo_start + $foo_len" 59 lassign [function_range foo_low [list ${srcdir}/${subdir}/$srcfile]] \ 60 foo_low_start foo_low_len 61 set foo_low_end "$foo_low_start + $foo_low_len" 62 lassign [function_range bar [list ${srcdir}/${subdir}/$srcfile]] \ 63 bar_start bar_len 64 set bar_end "$bar_start + $bar_len" 65 lassign [function_range baz [list ${srcdir}/${subdir}/$srcfile]] \ 66 baz_start baz_len 67 set baz_end "$baz_start + $baz_len" 68 69 set e_var [gdb_target_symbol e] 70 71 cu {} { 72 compile_unit { 73 {language @DW_LANG_C} 74 {name dw-ranges-func.c} 75 {stmt_list $L DW_FORM_sec_offset} 76 {low_pc 0 addr} 77 {ranges ${cu_ranges_label} DW_FORM_sec_offset} 78 } { 79 integer_label: DW_TAG_base_type { 80 {DW_AT_byte_size $int_size DW_FORM_sdata} 81 {DW_AT_encoding @DW_ATE_signed} 82 {DW_AT_name integer} 83 } 84 volatile_label: DW_TAG_volatile_type { 85 {type :$integer_label} 86 } 87 DW_TAG_variable { 88 {name e} 89 {external 1 flag} 90 {type :$volatile_label} 91 {location {addr $e_var} SPECIAL_expr} 92 } 93 subprogram { 94 {external 1 flag} 95 {name main} 96 {DW_AT_type :$integer_label} 97 {low_pc $main_start addr} 98 {high_pc $main_len DW_FORM_data4} 99 } 100 subprogram { 101 {external 1 flag} 102 {name foo} 103 {ranges ${func_ranges_label} DW_FORM_sec_offset} 104 } 105 subprogram { 106 {external 1 flag} 107 {name bar} 108 {low_pc $bar_start addr} 109 {high_pc $bar_len DW_FORM_data4} 110 } 111 subprogram { 112 {external 1 flag} 113 {name baz} 114 {low_pc $baz_start addr} 115 {high_pc $baz_len DW_FORM_data4} 116 } 117 } 118 } 119 120 lines {version 2} L { 121 include_dir "${srcdir}/${subdir}" 122 file_name "$srcfile" 1 123 124 # Generate a line table program. An attempt was made to make it 125 # reasonably accurate as it made debugging the test case easier. 126 program { 127 {DW_LNE_set_address $main_start} 128 {DW_LNS_advance_line [expr [gdb_get_line_number "main prologue"] - 1]} 129 {DW_LNS_copy} 130 {DW_LNE_set_address main_label} 131 {DW_LNS_advance_line [expr [gdb_get_line_number "main foo call"] - [gdb_get_line_number "main prologue"]]} 132 {DW_LNS_copy} 133 {DW_LNE_set_address main_label2} 134 {DW_LNS_advance_line [expr [gdb_get_line_number "main return"] - [gdb_get_line_number "main foo call"]]} 135 {DW_LNS_copy} 136 {DW_LNE_set_address $main_end} 137 {DW_LNS_advance_line [expr [gdb_get_line_number "main end"] - [gdb_get_line_number "main return"] + 1]} 138 {DW_LNS_copy} 139 {DW_LNE_end_sequence} 140 141 {DW_LNE_set_address $foo_start} 142 {DW_LNS_advance_line [expr [gdb_get_line_number "foo prologue"] - 1] } 143 {DW_LNS_copy} 144 {DW_LNE_set_address foo_label} 145 {DW_LNS_advance_line [expr [gdb_get_line_number "foo bar call"] - [gdb_get_line_number "foo prologue"]]} 146 {DW_LNS_copy} 147 {DW_LNE_set_address foo_label2} 148 {DW_LNS_advance_line [expr [gdb_get_line_number "foo foo_low call"] - [gdb_get_line_number "foo bar call"]]} 149 {DW_LNS_copy} 150 {DW_LNE_set_address foo_label3} 151 {DW_LNS_advance_line [expr [gdb_get_line_number "foo end"] - [gdb_get_line_number "foo foo_low call"]]} 152 {DW_LNS_copy} 153 {DW_LNE_set_address $foo_end} 154 {DW_LNS_advance_line 1} 155 {DW_LNS_copy} 156 {DW_LNE_end_sequence} 157 158 {DW_LNE_set_address $bar_start} 159 {DW_LNS_advance_line [expr [gdb_get_line_number "bar end"] - 1]} 160 {DW_LNS_copy} 161 {DW_LNS_advance_pc $bar_len} 162 {DW_LNS_advance_line 1} 163 {DW_LNS_copy} 164 {DW_LNE_end_sequence} 165 166 {DW_LNE_set_address $baz_start} 167 {DW_LNS_advance_line [expr [gdb_get_line_number "baz end"] - 1]} 168 {DW_LNS_copy} 169 {DW_LNS_advance_pc $baz_len} 170 {DW_LNS_advance_line 1} 171 {DW_LNS_copy} 172 {DW_LNE_end_sequence} 173 174 {DW_LNE_set_address $foo_low_start} 175 {DW_LNS_advance_line [expr [gdb_get_line_number "foo_low prologue"] - 1]} 176 {DW_LNS_copy} 177 {DW_LNE_set_address foo_low_label} 178 {DW_LNS_advance_line [expr [gdb_get_line_number "foo_low baz call"] - [gdb_get_line_number "foo_low prologue"]]} 179 {DW_LNS_copy} 180 {DW_LNE_set_address foo_low_label2} 181 {DW_LNS_advance_line [expr [gdb_get_line_number "foo_low end"] - [gdb_get_line_number "foo_low baz call"]]} 182 {DW_LNS_copy} 183 {DW_LNE_set_address $foo_low_end} 184 {DW_LNS_advance_line 1} 185 {DW_LNS_copy} 186 {DW_LNE_end_sequence} 187 } 188 } 189 190 # Generate ranges data. 191 ranges {is_64 [is_64_target]} { 192 func_ranges_label: sequence { 193 {range {$foo_start } $foo_end} 194 {range {$foo_low_start} $foo_low_end} 195 } 196 cu_ranges_label: sequence { 197 {range {$foo_start } $foo_end} 198 {range {$foo_low_start} $foo_low_end} 199 {range {$main_start} $main_end} 200 {range {$bar_start} $bar_end} 201 {range {$baz_start} $baz_end} 202 } 203 } 204} 205 206if { [prepare_for_testing "failed to prepare" ${testfile} \ 207 [list $srcfile $asm_file] {nodebug}] } { 208 return -1 209} 210 211if ![runto_main] { 212 return -1 213} 214 215set main_prologue_line_num [gdb_get_line_number "main prologue"] 216# Do a sanity check to make sure that line number info is available. 217gdb_test "info line main" \ 218 "Line ${main_prologue_line_num} of .* starts at address .* and ends at .*" 219 220with_test_prefix "step-test-1" { 221 set bp_foo_bar [gdb_get_line_number "foo bar call"] 222 223 gdb_test "break $bp_foo_bar" \ 224 "Breakpoint.*at.* file .*$srcfile, line $bp_foo_bar\\." \ 225 "break at call to bar" 226 227 gdb_test "continue" \ 228 "Continuing\\..*Breakpoint \[0-9\]+, foo \\(\\).*$bp_foo_bar\\s+bar\\s\\(\\);.*foo bar call.*" \ 229 "continue to call of bar" 230 231 gdb_test "step" \ 232 "bar \\(\\).*bar end.*" \ 233 "step into bar" 234 235 gdb_test "step" \ 236 "foo \\(\\).*foo foo_low call.*" \ 237 "step out of bar, back into foo" 238} 239 240with_test_prefix "step-test-2" { 241 clean_restart ${testfile} 242 if ![runto_main] { 243 return -1 244 } 245 246 # Note that the RE used for the following test will fail when the 247 # breakpoint has been set on multiple locations. E.g. "(2 locations)". 248 # This is intentional since that behavior is one of the bugs that 249 # this test case tests for. 250 gdb_test "break foo" \ 251 "Breakpoint.*at.* file .*$srcfile, line \\d+\\." \ 252 "break foo" 253 254 # Continue to foo. Allow execution to stop either on the prologue 255 # or on the call to bar since either behavior is acceptable though 256 # the latter is preferred. 257 set test "continue to foo" 258 gdb_test_multiple "continue" $test { 259 -re "Breakpoint \\d+, foo \\(\\).*foo prologue.*${gdb_prompt}" { 260 pass $test 261 gdb_test "step" \ 262 "foo bar call .*" \ 263 "step to call of bar after landing on prologue" 264 } 265 -re "Breakpoint \\d+, foo \\(\\).*foo bar call.*${gdb_prompt}" { 266 pass $test 267 } 268 } 269 270 gdb_test "step" \ 271 "bar \\(\\).*bar end.*" \ 272 "step into bar" 273 274 gdb_test "step" \ 275 "foo \\(\\).*foo foo_low call.*" \ 276 "step out of bar, back into foo" 277} 278 279clean_restart ${testfile} 280if ![runto_main] { 281 return -1 282} 283 284# Disassembly of foo should have multiple address ranges. 285gdb_test_sequence "disassemble foo" "" [list \ 286 "Dump of assembler code for function foo:" \ 287 "Address range $hex to $hex:" \ 288 " $hex <\\+0>:" \ 289 "Address range $hex to $hex:" \ 290 " $hex <(.+?)>:" \ 291 "End of assembler dump\\." \ 292] 293 294set foo_low_addr -1 295set test "x/i foo_low" 296gdb_test_multiple $test $test { 297 -re " ($hex) <foo.*?>.*${gdb_prompt}" { 298 set foo_low_addr $expect_out(1,string) 299 pass $test 300 } 301} 302 303set foo_addr -1 304set test "x/i foo" 305gdb_test_multiple $test $test { 306 -re " ($hex) <foo.*?>.*${gdb_prompt}" { 307 set foo_addr $expect_out(1,string) 308 pass $test 309 } 310} 311 312gdb_assert {$foo_low_addr != $foo_addr} "foo and foo_low are at different addresses" 313 314# This more permissive RE for "break foo" will allow a breakpoint on 315# multiple locations to PASS. */ 316gdb_test "break foo" \ 317 "Breakpoint.*at.*" \ 318 "break foo" 319 320gdb_test "break baz" \ 321 "Breakpoint.*at.* file .*$srcfile, line \\d+\\." 322 323gdb_test "continue" \ 324 "Breakpoint \\d+, foo \\(\\).*" \ 325 "continue to foo" 326 327gdb_test_no_output "set variable e=1" 328 329# If GDB incorrectly places the foo breakpoint on multiple locations, 330# then GDB will (incorrectly) stop in foo_low instead of in baz. 331gdb_test "continue" \ 332 "Breakpoint \\d+, (?:$hex in )?baz \\(\\).*" \ 333 "continue to baz" 334 335with_test_prefix "step-test-3" { 336 clean_restart ${testfile} 337 if ![runto_main] { 338 return -1 339 } 340 341 gdb_test "step" \ 342 "foo \\(\\).*bar \\(\\);.*foo bar call.*" \ 343 "step into foo from main" 344 345 gdb_test "step" \ 346 "bar \\(\\).*\}.* bar end.*" \ 347 "step into bar from foo" 348 349 gdb_test "step" \ 350 "foo(_label2)? \\(\\).*foo_low \\(\\);.*foo foo_low call.*" \ 351 "step out of bar to foo" 352 353 # The tests in the "enable_foo_low_stepping" section, below, work 354 # with some versions of gcc, though it's not clear that they 355 # should. This test case causes foo_low, originally a separate 356 # function invoked via a subroutine call, to be considered as part 357 # of foo via use of DW_AT_ranges. Real code that I've looked at 358 # uses a branch instruction to cause code in the "cold" range to 359 # be executed. 360 # 361 # For the moment though, these tests have been left in place, but 362 # disabled, in case we decide that making such a subroutine call 363 # is a reasonable thing to do that should also be supported by 364 # GDB. 365 366 set enable_foo_low_stepping false 367 368 if { $enable_foo_low_stepping } { 369 gdb_test_no_output "set variable e=1" 370 371 set test "step into foo_low from foo" 372 gdb_test_multiple "step" $test { 373 -re "foo(_low)? \\(\\).*\{.*foo_low prologue.*${gdb_prompt}" { 374 pass $test 375 gdb_test "step" \ 376 "foo \\(\\).*baz \\(\\);.*foo_low baz call.*" \ 377 "step to baz call in foo_low" 378 379 } 380 -re "foo(_low)? \\(\\).*baz \\(\\);.*foo_low baz call.*${gdb_prompt}" { 381 pass $test 382 } 383 } 384 385 gdb_test "step" \ 386 "baz \\(\\).*\}.*baz end.*" \ 387 "step into baz from foo_low" 388 389 gdb_test "step" \ 390 "foo(?:_low(?:_label2)?)? \\(\\).*\}.*foo_low end.*" \ 391 "step out of baz to foo_low" 392 393 gdb_test "step" \ 394 "foo(?:_label3)? \\(\\).*\}.*foo end.*" \ 395 "step out of foo_low to foo" 396 } else { 397 gdb_test "next" \ 398 ".*foo end.*" \ 399 "next over foo_low call" 400 } 401 402 gdb_test "step" \ 403 "main(?:_label2)? \\(\\).*" \ 404 "step out of foo to main" 405} 406