1 # Copyright 2022-2025 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 # Check that GDB can honor the epilogue_begin flag the compiler can place 17 # in the line-table data. 18 # We test 2 things: 1. that a software watchpoint triggered in an epilogue 19 # is correctly ignored 20 # 2. that GDB can mark the same line as both prologue and epilogue 21 22 load_lib dwarf.exp 23 24 # This test can only be run on targets which support DWARF-2 and use gas. 25 require dwarf2_support 26 # restricted to x86 to make it simpler to follow a variable 27 require is_x86_64_m64_target 28 29 set trivial_line [gdb_get_line_number "trivial function"] 30 set main_prologue [gdb_get_line_number "main prologue"] 31 set main_epilogue [gdb_get_line_number "main end"] 32 set watch_start_line [gdb_get_line_number "watch start"] 33 34 set asm_file [standard_output_file $srcfile2] 35 36 # The producer will be set to clang because at the time of writing 37 # we only care about epilogues if the producer is clang. When the 38 # producer is GCC, variables use CFA locations, so watchpoints can 39 # continue working even on epilogues. 40 Dwarf::assemble $asm_file { 41 global srcdir subdir srcfile srcfile2 42 global trivial_line main_prologue main_epilogue watch_start_line 43 declare_labels lines_label 44 45 get_func_info main 46 get_func_info trivial 47 get_func_info watch 48 49 if { $::version == 1 } { 50 set switch_file {} 51 } elseif { $::version == 2 } { 52 set switch_file { set f $f2 } 53 } else { 54 error "Unhandled version: $::version" 55 } 56 57 cu {} { 58 compile_unit { 59 {language @DW_LANG_C} 60 {name dw2-prologue-end.c} 61 {stmt_list ${lines_label} DW_FORM_sec_offset} 62 {producer "clang version 17.0.1"} 63 } { 64 declare_labels char_label 65 66 char_label: base_type { 67 {name char} 68 {encoding @DW_ATE_signed} 69 {byte_size 1 DW_FORM_sdata} 70 } 71 72 subprogram { 73 {external 1 flag} 74 {name trivial} 75 {low_pc $trivial_start addr} 76 {high_pc "$trivial_start + $trivial_len" addr} 77 } 78 subprogram { 79 {external 1 flag} 80 {name watch} 81 {low_pc $watch_start addr} 82 {high_pc "$watch_start + $watch_len" addr} 83 } { 84 DW_TAG_variable { 85 {name local} 86 {type :$char_label} 87 {DW_AT_location {DW_OP_reg0} SPECIAL_expr} 88 } 89 } 90 subprogram { 91 {external 1 flag} 92 {name main} 93 {low_pc $main_start addr} 94 {high_pc "$main_start + $main_len" addr} 95 } 96 } 97 } 98 99 lines {version 5} lines_label { 100 set diridx [include_dir "${srcdir}/${subdir}"] 101 set f1 [file_name "$srcfile" $diridx] 102 set f2 [file_name "$srcfile.inc" $diridx] 103 104 set f $f1 105 program { 106 DW_LNS_set_file $f 107 108 DW_LNE_set_address $trivial_start 109 line $trivial_line 110 DW_LNS_set_prologue_end 111 DW_LNS_set_epilogue_begin 112 DW_LNS_copy 113 114 DW_LNE_set_address $trivial_end 115 DW_LNE_end_sequence 116 117 118 DW_LNS_set_file $f 119 120 DW_LNE_set_address $watch_start 121 line $watch_start_line 122 DW_LNS_copy 123 124 DW_LNE_set_address watch_start 125 line [gdb_get_line_number "watch assign"] 126 DW_LNS_set_prologue_end 127 DW_LNS_copy 128 129 eval $switch_file 130 DW_LNS_set_file $f 131 132 DW_LNE_set_address watch_reassign 133 line [gdb_get_line_number "watch reassign"] 134 DW_LNS_set_epilogue_begin 135 DW_LNS_copy 136 137 DW_LNE_set_address watch_end 138 line [gdb_get_line_number "watch end"] 139 DW_LNS_copy 140 141 DW_LNE_set_address $watch_end 142 DW_LNE_end_sequence 143 144 145 DW_LNS_set_file $f 146 147 DW_LNE_set_address $main_start 148 line $main_prologue 149 DW_LNS_set_prologue_end 150 DW_LNS_copy 151 152 DW_LNE_set_address main_fun_call 153 line [gdb_get_line_number "main function call"] 154 DW_LNS_copy 155 156 DW_LNE_set_address main_epilogue 157 line $main_epilogue 158 DW_LNS_set_epilogue_begin 159 DW_LNS_copy 160 161 DW_LNE_set_address $main_end 162 DW_LNE_end_sequence 163 } 164 } 165 } 166 167 if { [prepare_for_testing "failed to prepare" ${testfile} \ 168 [list $srcfile $asm_file] {nodebug}] } { 169 return -1 170 } 171 172 if ![runto_main] { 173 return -1 174 } 175 176 # Moving to the scope with a local variable. 177 178 gdb_breakpoint $srcfile:$watch_start_line 179 gdb_continue_to_breakpoint "continuing to function" ".*" 180 gdb_test "next" "local = 2.*" "stepping to epilogue" 181 182 # Forcing software watchpoints because hardware ones don't care if we 183 # are in the epilogue or not. 184 gdb_test_no_output "set can-use-hw-watchpoints 0" 185 186 # Test that the software watchpoint will not trigger in this case 187 gdb_test "watch local" "\[W|w\]atchpoint .: local" "set watchpoint" 188 gdb_test "continue" ".*\[W|w\]atchpoint . deleted.*" \ 189 "confirm watchpoint doesn't trigger" 190 191 # First we test that the trivial function has a line with both a prologue 192 # and an epilogue. Do this by finding a line that has 3 Y columns 193 set sep "\[ \t\]" 194 set hex_number "0x\[0-9a-f\]+" 195 gdb_test_multiple "maint info line-table" "test epilogue in linetable" -lbl { 196 -re "\[0-9\]$sep+$trivial_line$sep+$hex_number$sep+$hex_number$sep+Y$sep+Y$sep+Y" { 197 pass $gdb_test_name 198 } 199 } 200