From 50757f95a8296b3552362d9d6ac6c0182336766f Mon Sep 17 00:00:00 2001 From: Tankut Baris Aktemur Date: Tue, 24 Nov 2020 09:56:38 +0100 Subject: [PATCH] gdb/testsuite: do not hard-code location indices in condbreak-multi-context.exp Breakpoint locations are sorted according to their addresses. The addresses are determined by how the compiler emits the code. Therefore, we may have a different order of locations depending on the compiler we use. To make the gdb.base/condbreak-multi-context.exp test flexible enough for different compilers' output, do not hard-code location indices. Tested with GCC and Clang. gdb/testsuite/ChangeLog: 2020-11-24 Tankut Baris Aktemur * gdb.base/condbreak-multi-context.exp: Do not hard-code location indices. --- gdb/testsuite/ChangeLog | 5 + .../gdb.base/condbreak-multi-context.exp | 190 ++++++++++++------ 2 files changed, 128 insertions(+), 67 deletions(-) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index fa1f0e8faaf..5f62e45fed8 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-11-24 Tankut Baris Aktemur + + * gdb.base/condbreak-multi-context.exp: Do not hard-code location + indices. + 2020-11-24 Joel Brobecker * gdb.dwarf2/dw2-fixed-point.exp: Fix the expected output of diff --git a/gdb/testsuite/gdb.base/condbreak-multi-context.exp b/gdb/testsuite/gdb.base/condbreak-multi-context.exp index cef4280a81c..f89452f54c5 100644 --- a/gdb/testsuite/gdb.base/condbreak-multi-context.exp +++ b/gdb/testsuite/gdb.base/condbreak-multi-context.exp @@ -25,28 +25,79 @@ if {[prepare_for_testing "failed to prepare" ${binfile} ${srcfile}]} { set warning "warning: failed to validate condition" set fill "\[^\r\n\]*" -# Check that breakpoints are as expected. +# Location indices are determined by their address, which depends on +# how the compiler emits the code. We keep a map from the location +# index to the location context (i.e. A, Base, or C), so that we can +# write tests without hard-coding location indices. +set loc_name(1) "" +set loc_name(2) "" +set loc_name(3) "" +# And, for convenience, a reverse map from the name to the index. +set loc_index(A) 0 +set loc_index(Base) 0 +set loc_index(C) 0 + +# Find breakpoint location contexts. + +proc find_location_contexts {} { + global loc_name loc_index bpnum1 fill + global decimal hex gdb_prompt + + gdb_test_multiple "info breakpoint $bpnum1" "find_location_indices" { + -re "stop only if ${fill}\r\n" { + exp_continue + } + -re "^${bpnum1}\.($decimal) ${fill} ${hex} in (A|Base|C)::func${fill}\r\n" { + set index $expect_out(1,string) + set name $expect_out(2,string) + set loc_name($index) $name + set loc_index($name) $index + exp_continue + } + -re "$gdb_prompt $" { + verbose -log "Loc names: $loc_name(1), $loc_name(2), $loc_name(3)" + gdb_assert { ![string equal $loc_name(1) $loc_name(2)] } + gdb_assert { ![string equal $loc_name(1) $loc_name(3)] } + gdb_assert { ![string equal $loc_name(2) $loc_name(3)] } + gdb_assert { [string length $loc_name(1)] > 0 } + gdb_assert { [string length $loc_name(2)] > 0 } + gdb_assert { [string length $loc_name(3)] > 0 } + } + } +} -proc test_info_break {suffix} { - global bpnum1 bpnum2 fill +# Test the breakpoint location enabled states. STATES is a list of +# location states. We assume STATES to contain the state for A, Base, +# and C, and in this order. E.g. {N* y n} for 'N*' at A::func, 'y' at +# B::func, and 'n' at C::func, respectively. - set bp_hit_info "${fill}(\r\n${fill}breakpoint already hit 1 time)?" +proc check_bp_locations {bpnum states cond {msg ""}} { + global loc_name fill - gdb_test "info break ${bpnum1} ${bpnum2}" \ - [multi_line \ - "Num${fill}" \ - "${bpnum1}${fill}breakpoint${fill}keep y${fill}MULTIPLE${fill}" \ - "${fill}stop only if a == 10${bp_hit_info}" \ - "${bpnum1}.1${fill}N\\*${fill}Base::func${fill}" \ - "${bpnum1}.2${fill}y${fill}A::func${fill}" \ - "${bpnum1}.3${fill}N\\*${fill}C::func${fill}" \ - "${bpnum2}${fill}breakpoint${fill}keep y${fill}MULTIPLE${fill}" \ - "${fill}stop only if c == 30${bp_hit_info}" \ - "${bpnum2}.1${fill}N\\*${fill}Base::func${fill}" \ - "${bpnum2}.2${fill}N\\*${fill}A::func${fill}" \ - "${bpnum2}.3${fill}y${fill}C::func${fill}" \ - "\\(\\*\\): Breakpoint condition is invalid at this location."] \ - "info break $suffix" + # Map location names to location states. + set loc_states(A) [lindex $states 0] + set loc_states(Base) [lindex $states 1] + set loc_states(C) [lindex $states 2] + + if {$cond == ""} { + set cond_info "" + } else { + set bp_hit_info "${fill}(\r\n${fill}breakpoint already hit 1 time)?" + set cond_info "\r\n${fill}stop only if ${cond}${bp_hit_info}" + } + + set expected [multi_line \ + "Num${fill}" \ + "${bpnum}${fill}breakpoint${fill}keep y${fill}MULTIPLE${fill}${cond_info}" \ + "${bpnum}.1${fill} $loc_states($loc_name(1)) ${fill}" \ + "${bpnum}.2${fill} $loc_states($loc_name(2)) ${fill}" \ + "${bpnum}.3${fill} $loc_states($loc_name(3)) ${fill}"] + + if {[lsearch $states N*] >= 0} { + append expected "\r\n\\(\\*\\): Breakpoint condition is invalid at this location." + } + + gdb_test "info break $bpnum" $expected "check bp $bpnum $msg" } # Scenario 1: Define breakpoints conditionally, using the "break N if @@ -54,12 +105,15 @@ proc test_info_break {suffix} { # only. with_test_prefix "scenario 1" { - # Define the conditional breakpoints. + # Define the conditional breakpoints. Two locations (Base::func + # and C::func) should be disabled. We do not test location + # indices strictly at this moment, because we don't know them, + # yet. We have strict location index tests below. gdb_test "break func if a == 10" \ [multi_line \ - "${warning} at location 1, disabling:" \ + "${warning} at location $decimal, disabling:" \ " No symbol \"a\" in current context." \ - "${warning} at location 3, disabling:" \ + "${warning} at location $decimal, disabling:" \ " No symbol \"a\" in current context." \ "Breakpoint $decimal at $fill .3 locations."] \ "define bp with condition a == 10" @@ -67,15 +121,20 @@ with_test_prefix "scenario 1" { gdb_test "break func if c == 30" \ [multi_line \ - ".*${warning} at location 1, disabling:" \ + ".*${warning} at location $decimal, disabling:" \ " No symbol \"c\" in current context." \ - ".*${warning} at location 2, disabling:" \ + ".*${warning} at location $decimal, disabling:" \ " No symbol \"c\" in current context." \ ".*Breakpoint $decimal at $fill .3 locations."] \ "define bp with condition c == 30" set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] - test_info_break 1 + find_location_contexts + + with_test_prefix "before run" { + check_bp_locations $bpnum1 {y N* N*} "a == 10" + check_bp_locations $bpnum2 {N* N* y} "c == 30" + } # Do not use runto_main, it deletes all breakpoints. gdb_run_cmd @@ -92,14 +151,17 @@ with_test_prefix "scenario 1" { # No more hits! gdb_continue_to_end - test_info_break 2 + with_test_prefix "after run" { + check_bp_locations $bpnum1 {y N* N*} "a == 10" + check_bp_locations $bpnum2 {N* N* y} "c == 30" + } } # Start GDB with two breakpoints and define the conditions separately. proc setup_bps {} { - global srcfile binfile srcfile2 - global bpnum1 bpnum2 bp_location warning + global srcfile binfile srcfile2 decimal + global bpnum1 bpnum2 bp_location warning loc_index clean_restart ${binfile} @@ -111,19 +173,21 @@ proc setup_bps {} { set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] # Defining a condition on 'a' disables 2 locations. + set locs [lsort -integer "$loc_index(Base) $loc_index(C)"] gdb_test "cond $bpnum1 a == 10" \ [multi_line \ - "$warning at location ${bpnum1}.1, disabling:" \ + "$warning at location ${bpnum1}.[lindex $locs 0], disabling:" \ " No symbol \"a\" in current context." \ - "$warning at location ${bpnum1}.3, disabling:" \ + "$warning at location ${bpnum1}.[lindex $locs 1], disabling:" \ " No symbol \"a\" in current context."] # Defining a condition on 'c' disables 2 locations. + set locs [lsort -integer "$loc_index(Base) $loc_index(A)"] gdb_test "cond $bpnum2 c == 30" \ [multi_line \ - "$warning at location ${bpnum2}.1, disabling:" \ + "$warning at location ${bpnum2}.[lindex $locs 0], disabling:" \ " No symbol \"c\" in current context." \ - "$warning at location ${bpnum2}.2, disabling:" \ + "$warning at location ${bpnum2}.[lindex $locs 1], disabling:" \ " No symbol \"c\" in current context."] } @@ -135,7 +199,10 @@ proc setup_bps {} { with_test_prefix "scenario 2" { setup_bps - test_info_break 1 + with_test_prefix "before run" { + check_bp_locations $bpnum1 {y N* N*} "a == 10" + check_bp_locations $bpnum2 {N* N* y} "c == 30" + } # Do not use runto_main, it deletes all breakpoints. gdb_run_cmd @@ -152,22 +219,10 @@ with_test_prefix "scenario 2" { # No more hits! gdb_continue_to_end - test_info_break 2 -} - -# Test the breakpoint location enabled states. - -proc check_bp_locations {bpnum states msg} { - global fill - - set expected ".*${bpnum}.1${fill} [lindex $states 0] ${fill}\r\n" - append expected "${bpnum}.2${fill} [lindex $states 1] ${fill}\r\n" - append expected "${bpnum}.3${fill} [lindex $states 2] ${fill}" - if {[lsearch $states N*] >= 0} { - append expected "\r\n\\(\\*\\): Breakpoint condition is invalid at this location." + with_test_prefix "after run" { + check_bp_locations $bpnum1 {y N* N*} "a == 10" + check_bp_locations $bpnum2 {N* N* y} "c == 30" } - - gdb_test "info break $bpnum" $expected "check bp $bpnum $msg" } # Scenario 3: Apply misc. checks on the already-defined breakpoints. @@ -175,44 +230,45 @@ proc check_bp_locations {bpnum states msg} { with_test_prefix "scenario 3" { setup_bps + set locs [lsort -integer "$loc_index(Base) $loc_index(A)"] gdb_test "cond $bpnum1 c == 30" \ [multi_line \ - "${warning} at location ${bpnum1}.1, disabling:" \ + "${warning} at location ${bpnum1}.[lindex $locs 0], disabling:" \ " No symbol \"c\" in current context." \ - "${warning} at location ${bpnum1}.2, disabling:" \ + "${warning} at location ${bpnum1}.[lindex $locs 1], disabling:" \ " No symbol \"c\" in current context." \ - "Breakpoint ${bpnum1}'s condition is now valid at location 3, enabling."] \ + "Breakpoint ${bpnum1}'s condition is now valid at location $loc_index(C), enabling."] \ "change the condition of bp 1" - check_bp_locations $bpnum1 {N* N* y} "after changing the condition" + check_bp_locations $bpnum1 {N* N* y} "c == 30" "after changing the condition" gdb_test "cond $bpnum1" \ [multi_line \ - "Breakpoint ${bpnum1}'s condition is now valid at location 1, enabling." \ - "Breakpoint ${bpnum1}'s condition is now valid at location 2, enabling." \ + "Breakpoint ${bpnum1}'s condition is now valid at location [lindex $locs 0], enabling." \ + "Breakpoint ${bpnum1}'s condition is now valid at location [lindex $locs 1], enabling." \ "Breakpoint ${bpnum1} now unconditional."] \ "reset the condition of bp 1" - check_bp_locations $bpnum1 {y y y} "after resetting the condition" + check_bp_locations $bpnum1 {y y y} "" "after resetting the condition" - gdb_test_no_output "disable ${bpnum2}.2" - check_bp_locations $bpnum2 {N* N* y} "after disabling loc 2" + gdb_test_no_output "disable ${bpnum2}.$loc_index(A)" + check_bp_locations $bpnum2 {N* N* y} "c == 30" "after disabling loc for A" gdb_test "cond $bpnum2" ".*" "reset the condition of bp 2" - check_bp_locations $bpnum2 {y n y} "loc 2 should remain disabled" + check_bp_locations $bpnum2 {n y y} "" "loc for A should remain disabled" - gdb_test_no_output "disable ${bpnum2}.3" - check_bp_locations $bpnum2 {y n n} "after disabling loc 3" + gdb_test_no_output "disable ${bpnum2}.$loc_index(C)" + check_bp_locations $bpnum2 {n y n} "" "after disabling loc for C" gdb_test "cond $bpnum2 c == 30" \ [multi_line \ - "${warning} at location ${bpnum2}.1, disabling:" \ + "${warning} at location ${bpnum2}.$loc_index(Base), disabling:" \ " No symbol \"c\" in current context."] \ "re-define a condition" - check_bp_locations $bpnum2 {N* N* n} "loc 3 should remain disabled" + check_bp_locations $bpnum2 {N* N* n} "c == 30" "loc for C should remain disabled" - gdb_test "enable ${bpnum2}.1" \ - "Breakpoint ${bpnum2}'s condition is invalid at location 1, cannot enable." \ + gdb_test "enable ${bpnum2}.$loc_index(Base)" \ + "Breakpoint ${bpnum2}'s condition is invalid at location $loc_index(Base), cannot enable." \ "reject enabling a location that is disabled-by-cond" - check_bp_locations $bpnum2 {N* N* n} "after enable attempt" + check_bp_locations $bpnum2 {N* N* n} "c == 30" "after enable attempt" gdb_test "cond $bpnum2 garbage" \ "No symbol \"garbage\" in current context." \ @@ -246,10 +302,10 @@ with_test_prefix "force" { "${warning} at location ${bpnum1}.3, disabling:" \ " No symbol \"foo\" in current context."] \ "force the condition of bp 1" - check_bp_locations $bpnum1 {N* N* N*} "after forcing the condition" + check_bp_locations $bpnum1 {N* N* N*} "foo" "after forcing the condition" # Now with the 'break' command. gdb_breakpoint "func -force-condition if baz" set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] - check_bp_locations $bpnum2 {N* N* N*} "set using the break command" + check_bp_locations $bpnum2 {N* N* N*} "baz" "set using the break command" } -- 2.30.2