[v2,3/4] gdb/testsuite: fix testing gdb.reverse/step-reverse.exp with clang

Message ID 20230727074118.1583199-4-blarsen@redhat.com
State New
Headers
Series Many fixes to gdb.reverse tests |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Guinevere Larsen July 27, 2023, 7:41 a.m. UTC
  When testing using reverse-stepi to fully step through a function, the
code checks for an infinite loop by seeing if we land on the line that
contains the return statement multiple times. This assumption only works
if there is only one instruction associated with that line, which is how
GCC handles line information, but other compilers may handle it differently.
Clang-15, for instance, associates 6. Because of this, the inferior used
to get seriously out of sync with the test expectations, and result in 13
spurious failures. The same issue occurs with gdb.reverse/step-precsave.exp.

This commit changes the test so that we check for PC instead of line
number. The test still only happens when the same line is detected, to
simplify the resulting log. With this change, no new failures are
emitted when using clang.

It also adds a new parameter to get_hexadecimal_valueof, so that we can
use it without generating new passes, otherwise we'd get multiple
duplicate test names. This change shouldn't affect any other test using
this proc.
---
 gdb/testsuite/gdb.reverse/step-precsave.exp | 18 +++++++++++++++++-
 gdb/testsuite/gdb.reverse/step-reverse.exp  | 20 +++++++++++++++++++-
 gdb/testsuite/lib/gdb.exp                   |  6 ++++--
 3 files changed, 40 insertions(+), 4 deletions(-)
  

Comments

Tom Tromey July 28, 2023, 1:14 p.m. UTC | #1
>>>>> "Bruno" == Bruno Larsen via Gdb-patches <gdb-patches@sourceware.org> writes:

Bruno> It also adds a new parameter to get_hexadecimal_valueof, so that we can
Bruno> use it without generating new passes, otherwise we'd get multiple
Bruno> duplicate test names. This change shouldn't affect any other test using
Bruno> this proc.

You can just pass different test names instead.

Bruno> +proc get_current_pc {} {
Bruno> +    set pc 0
Bruno> +    gdb_test_multiple "print \$pc" "" {
Bruno> +	-re -wrap ".*0x(\[0-9a-f\]+).*" {
Bruno> +	    set pc $expect_out(1,string)
Bruno> +	}
Bruno> +    }
Bruno> +    return $pc

It seems to me that this shouldn't be needed.

Bruno> diff --git a/gdb/testsuite/gdb.reverse/step-reverse.exp b/gdb/testsuite/gdb.reverse/step-reverse.exp
Bruno> index 4b78a8f8fb7..9ff97bfde42 100644
Bruno> --- a/gdb/testsuite/gdb.reverse/step-reverse.exp
Bruno> +++ b/gdb/testsuite/gdb.reverse/step-reverse.exp
Bruno> @@ -28,6 +28,16 @@ if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
Bruno>      return -1
Bruno>  }
 
Bruno> +proc get_current_pc {} {
Bruno> +    set pc 0
Bruno> +    gdb_test_multiple "print \$pc" "" {
Bruno> +	-re -wrap ".*0x(\[0-9a-f\]+).*" {
Bruno> +	    set pc $expect_out(1,string)
Bruno> +	}
Bruno> +    }
Bruno> +    return $pc

Same with this one.

Tom
  
Guinevere Larsen July 28, 2023, 1:20 p.m. UTC | #2
On 28/07/2023 15:14, Tom Tromey wrote:
>>>>>> "Bruno" == Bruno Larsen via Gdb-patches <gdb-patches@sourceware.org> writes:
> Bruno> It also adds a new parameter to get_hexadecimal_valueof, so that we can
> Bruno> use it without generating new passes, otherwise we'd get multiple
> Bruno> duplicate test names. This change shouldn't affect any other test using
> Bruno> this proc.
>
> You can just pass different test names instead.

I mean, yeah I can, but since it is in a loop, the differences would 
only be a counter at the end of the test case. Are we really getting any 
value from that? To me it seems like it would just boggle down the sum 
file with meaningless "tests" that aren't exercising any relevant code 
paths. I can do it if you disagree, though, it isn't a big deal.

One thing I did think of was that I should test for default value when 
getting the PC, to make sure that we didnt get a valid PC at first, then 
started getting "no registers" or similar. I'll have that on v3
  
Tom Tromey July 28, 2023, 2:18 p.m. UTC | #3
>>>>> "Bruno" == Bruno Larsen via Gdb-patches <gdb-patches@sourceware.org> writes:

Bruno> I mean, yeah I can, but since it is in a loop, the differences would
Bruno> only be a counter at the end of the test case. Are we really getting
Bruno> any value from that? To me it seems like it would just boggle down the
Bruno> sum file with meaningless "tests" that aren't exercising any relevant
Bruno> code paths. I can do it if you disagree, though, it isn't a big deal.

Yeah, I don't know if it's useful -- but are any of these passes useful?
The problem I think is that the proc can unconditionally emit a fail, so
having a corresponding pass seems to make sense.

Tom
  
Guinevere Larsen July 28, 2023, 2:20 p.m. UTC | #4
On 28/07/2023 16:18, Tom Tromey wrote:
>>>>>> "Bruno" == Bruno Larsen via Gdb-patches <gdb-patches@sourceware.org> writes:
> Bruno> I mean, yeah I can, but since it is in a loop, the differences would
> Bruno> only be a counter at the end of the test case. Are we really getting
> Bruno> any value from that? To me it seems like it would just boggle down the
> Bruno> sum file with meaningless "tests" that aren't exercising any relevant
> Bruno> code paths. I can do it if you disagree, though, it isn't a big deal.
>
> Yeah, I don't know if it's useful -- but are any of these passes useful?
> The problem I think is that the proc can unconditionally emit a fail, so
> having a corresponding pass seems to make sense.
>
Ah, yeah, in that angle it does make sense. I'll do it for v3!
  

Patch

diff --git a/gdb/testsuite/gdb.reverse/step-precsave.exp b/gdb/testsuite/gdb.reverse/step-precsave.exp
index 19cd5d9930e..da3a47e07e2 100644
--- a/gdb/testsuite/gdb.reverse/step-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/step-precsave.exp
@@ -30,6 +30,16 @@  if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
     return -1
 }
 
+proc get_current_pc {} {
+    set pc 0
+    gdb_test_multiple "print \$pc" "" {
+	-re -wrap ".*0x(\[0-9a-f\]+).*" {
+	    set pc $expect_out(1,string)
+	}
+    }
+    return $pc
+}
+
 runto_main
 
 # Activate process record/replay
@@ -209,11 +219,17 @@  gdb_test_multiple "stepi" "$test_message" {
 
 # stepi backward out of a function call
 
+set start_pc [get_current_pc]
 set stepi_location  [gdb_get_line_number "STEPI TEST" "$srcfile"]
 set test_message "reverse stepi from a function call"
 gdb_test_multiple "stepi" "$test_message" {
     -re "ARRIVED IN CALLEE.*$gdb_prompt $" {
-	fail "$test_message (start statement)"
+	if { [get_current_pc] == $start_pc } {
+	    fail "$test_message (start statement)"
+	} else {
+	    send_gdb "stepi\n" 
+	    exp_continue
+	}
     }
     -re "ENTER CALLEE.*$gdb_prompt $" {
 	send_gdb "stepi\n" 
diff --git a/gdb/testsuite/gdb.reverse/step-reverse.exp b/gdb/testsuite/gdb.reverse/step-reverse.exp
index 4b78a8f8fb7..9ff97bfde42 100644
--- a/gdb/testsuite/gdb.reverse/step-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/step-reverse.exp
@@ -28,6 +28,16 @@  if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
     return -1
 }
 
+proc get_current_pc {} {
+    set pc 0
+    gdb_test_multiple "print \$pc" "" {
+	-re -wrap ".*0x(\[0-9a-f\]+).*" {
+	    set pc $expect_out(1,string)
+	}
+    }
+    return $pc
+}
+
 runto_main
 
 if [supports_process_record] {
@@ -174,11 +184,19 @@  gdb_test_multiple "stepi" "$test_message" {
 
 # stepi backward out of a function call
 
+# When testing stepi, we dont want to infinitely step if we're not moving
+# so we store the starting PC, in case we land on the same line as above
+set start_pc [get_hexadecimal_valueof "\$pc" 0 "" "false"]
 set stepi_location  [gdb_get_line_number "STEPI TEST" "$srcfile"]
 set test_message "reverse stepi from a function call"
 gdb_test_multiple "stepi" "$test_message" {
     -re "ARRIVED IN CALLEE.*$gdb_prompt $" {
-	fail "$test_message (start statement)"
+	if { [get_hexadecimal_valueof "\$pc" 0 "" "false"] == $start_pc } {
+	    fail "$test_message (start statement)"
+	} else {
+	    send_gdb "stepi\n" 
+	    exp_continue
+	}
     }
     -re "ENTER CALLEE.*$gdb_prompt $" {
 	send_gdb "stepi\n" 
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 63b6291fc36..37342583e0a 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -7919,7 +7919,7 @@  proc get_integer_valueof { exp default {test ""} } {
 # TEST is the test message to use.  It can be omitted, in which case
 # a test message is built from EXP.
 
-proc get_hexadecimal_valueof { exp default {test ""} } {
+proc get_hexadecimal_valueof { exp default {test ""} {pass true} } {
     global gdb_prompt
 
     if {$test == ""} {
@@ -7930,7 +7930,9 @@  proc get_hexadecimal_valueof { exp default {test ""} } {
     gdb_test_multiple "print /x ${exp}" $test {
 	-re "\\$\[0-9\]* = (0x\[0-9a-zA-Z\]+).*$gdb_prompt $" {
 	    set val $expect_out(1,string)
-	    pass "$test"
+	    if { "$pass" == "true" } {
+		pass "$test"
+	    }
 	}
     }
     return ${val}