Home | History | Annotate | Line # | Download | only in gdb.dwarf2
      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