public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/2]  fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
       [not found]                                           ` <1d9b21914354bef6a290ac30673741e722e11757.camel@de.ibm.com>
@ 2023-01-11 18:27                                             ` Carl Love
  2023-01-11 18:27                                             ` [PATCH 1/2] " Carl Love
  2023-01-11 18:27                                             ` [PATCH 2/2] " Carl Love
  2 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-11 18:27 UTC (permalink / raw)
  To: Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

GDB maintainers:

This patch set fixes a couple of issues with the gdb.reverse tests
finish-precsave.exp and finish-reverse.exp.

The first issue is when doing a reverse-finish command from a function,
gdb should stop at the first instruction of the source code line where
the call was made.  The behavior should look the same as doing a
reverse-next from the first line of the function.  Currently gdb stops
at the last instruction in the caller source code line.  Issuing
reverse-step or reverse-next stops at the first instruction in the same
source code line.  It then requires a second reverse step or next
command to reach the previous source code line in the caller.  It
should only require one reverse step or next command to reach the
previous line.

The first patch in this series fixes the above issue on X86.  A number
of additional testcases require updating since the output is slightly
different or the test case no longer needs to issue the two reverse
step/next instructions.  The step_until proceedure in test
gdb.reverse/step-indirect-call-thunk.exp was moved to lib/gdb.exp and
renamed cmd_until.  The proceedure is used to test the reverse-finish
command when returning from the entry point of the function.

The second issue with the reverse-finish command is that on PowerPC the
reverse-finish doesn't stop at the function call.  The issue is PowerPC
uses two entry points.  PowerPC calls the two entry points the local
entry point (LEP) and the global entry point (GEP).  The LEP is
normally used when calling a function.  The GEP is used when the table
of contents (TOC) needs to be setup before continuing execution at the
LEP.  GDB is not handling the two entry points correctly.  The second
patch fixes the reverse-finish behavior on PowerPC.  On systems that
don't use two entry points the LEP and the GEP are the same.

A new testcase is added to verify the reverse-finish command works
correctly for X86 when returning from the body of a function and from
the entry point.  Note, the finish_backward function must handle the
two scenarios slightly differently.

The new testcase is expanded in the PPC patch to add tests for the two
scenarios for a function called via the GEP.  The initial set of tests
added in the X86 patch take care of the function being called via the
LEP on PowerPC.

The patches have been tested on PowerPC and X86 with no new
regressions.

Please let me know if the patches are acceptable for mainline.  Thanks.


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH 1/2]  fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
       [not found]                                           ` <1d9b21914354bef6a290ac30673741e722e11757.camel@de.ibm.com>
  2023-01-11 18:27                                             ` [PATCH 0/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp Carl Love
@ 2023-01-11 18:27                                             ` Carl Love
  2023-01-12 16:56                                               ` Tom de Vries
                                                                 ` (2 more replies)
  2023-01-11 18:27                                             ` [PATCH 2/2] " Carl Love
  2 siblings, 3 replies; 105+ messages in thread
From: Carl Love @ 2023-01-11 18:27 UTC (permalink / raw)
  To: Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

GDB maintainers:

This patch fixes the issues with the reverse-finish command on X86. 
The reverse-finish command now correctly stops at the first instruction
in the source code line of the caller.  It now only requires a single
reverse-step or reverse-next instruction to get back to the previous
source code line.

It also adds a new testcase, gdb.reverse/finish-reverse-next.exp, and
updates several existing testcases. 

Please let me know if you have any comments on the patch.  Thanks.

                    Carl 

--------------------------------------------------------------
X86: reverse-finish fix

Currently on X86, when executing the finish command in reverse, gdb does a
single step from the first instruction in the callee to get back to the
caller.  GDB stops on the last instruction in the source code line where
the call was made.  When stopped at the last instruction of the source code
line, a reverse next or step command will stop at the first instruction
of the same source code line thus requiring two step/next commands to
reach the previous source code line.  It should only require one step/next
command to reach the previous source code line.

By contrast, a reverse next or step command from the first line in a
function stops at the first instruction in the source code line where the
call was made.

This patch fixes the reverse finish command so it will stop at the first
instruction of the source line where the function call was made.  The
behavior on X86 for the reverse-finish command now matches doing a
reverse-next from the beginning of the function.

The proceed_to_finish flag in struct thread_control_state is no longer
used.  This patch removes the declaration, initialization and setting of
the flag.

This patch requires a number of regression tests to be updated.  Test
gdb.mi/mi-reverse.exp no longer needs to execute two steps to get to the
previous line.  The gdb output for tests gdb.reverse/until-precsave.exp
and gdb.reverse/until-reverse.exp changed slightly.  The expected result in
tests gdb.reverse/amd64-ailcall-reverse.exp and
gdb.reverse/singlejmp-reverse.exp are updated to the correct expected
result.

This patch adds a new test gdb.reverse/finish-reverse-next.exp to test the
reverse-finish command when returning from the entry point and from the
body of the function.

The step_until proceedure in test gdb.reverse/step-indirect-call-thunk.exp
was moved to lib/gdb.exp and renamed cmd_until.

The patch has been tested on X86 and PowerPC to verify no additional
regression failures occured.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29927
---
 gdb/gdbthread.h                               |   4 -
 gdb/infcall.c                                 |   3 -
 gdb/infcmd.c                                  |  32 +++---
 gdb/infrun.c                                  |  41 +++----
 gdb/testsuite/gdb.mi/mi-reverse.exp           |   9 +-
 .../gdb.reverse/amd64-tailcall-reverse.exp    |   5 +-
 .../gdb.reverse/finish-reverse-next.c         |  48 ++++++++
 .../gdb.reverse/finish-reverse-next.exp       | 108 ++++++++++++++++++
 gdb/testsuite/gdb.reverse/finish-reverse.exp  |   5 +
 .../gdb.reverse/singlejmp-reverse.exp         |   5 +-
 .../gdb.reverse/step-indirect-call-thunk.exp  |  49 ++------
 gdb/testsuite/gdb.reverse/until-precsave.exp  |   2 +-
 gdb/testsuite/gdb.reverse/until-reverse.exp   |   2 +-
 gdb/testsuite/lib/gdb.exp                     |  33 ++++++
 14 files changed, 240 insertions(+), 106 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp

diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 11d69fceab0..e4edff2d621 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -150,10 +150,6 @@ struct thread_control_state
      the finished single step.  */
   int trap_expected = 0;
 
-  /* Nonzero if the thread is being proceeded for a "finish" command
-     or a similar situation when return value should be printed.  */
-  int proceed_to_finish = 0;
-
   /* Nonzero if the thread is being proceeded for an inferior function
      call.  */
   int in_infcall = 0;
diff --git a/gdb/infcall.c b/gdb/infcall.c
index e09904f9a35..116605c43ef 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -625,9 +625,6 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
 
   disable_watchpoints_before_interactive_call_start ();
 
-  /* We want to print return value, please...  */
-  call_thread->control.proceed_to_finish = 1;
-
   try
     {
       /* Infcalls run synchronously, in the foreground.  */
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 0497ad05091..9c42efeae8d 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1721,19 +1721,10 @@ finish_backward (struct finish_command_fsm *sm)
 
   sal = find_pc_line (func_addr, 0);
 
-  tp->control.proceed_to_finish = 1;
-  /* Special case: if we're sitting at the function entry point,
-     then all we need to do is take a reverse singlestep.  We
-     don't need to set a breakpoint, and indeed it would do us
-     no good to do so.
-
-     Note that this can only happen at frame #0, since there's
-     no way that a function up the stack can have a return address
-     that's equal to its entry point.  */
+  frame_info_ptr frame = get_selected_frame (nullptr);
 
   if (sal.pc != pc)
     {
-      frame_info_ptr frame = get_selected_frame (nullptr);
       struct gdbarch *gdbarch = get_frame_arch (frame);
 
       /* Set a step-resume at the function's entry point.  Once that's
@@ -1743,16 +1734,22 @@ finish_backward (struct finish_command_fsm *sm)
       sr_sal.pspace = get_frame_program_space (frame);
       insert_step_resume_breakpoint_at_sal (gdbarch,
 					    sr_sal, null_frame_id);
-
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
   else
     {
-      /* We're almost there -- we just need to back up by one more
-	 single-step.  */
-      tp->control.step_range_start = tp->control.step_range_end = 1;
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
+      /* We are exactly at the function entry point.  Note that this
+	 can only happen at frame #0.
+
+	 When setting a step range, need to call set_step_info
+	 to setup the current_line/symtab fields as well.  */
+      set_step_info (tp, frame, find_pc_line (pc, 0));
+
+      /* Return using a step range so we will keep stepping back
+	 to the first instruction in the source code line.  */
+      tp->control.step_range_start = sal.pc;
+      tp->control.step_range_end = sal.pc;
     }
+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
 /* finish_forward -- helper function for finish_command.  FRAME is the
@@ -1778,9 +1775,6 @@ finish_forward (struct finish_command_fsm *sm, frame_info_ptr frame)
 
   set_longjmp_breakpoint (tp, frame_id);
 
-  /* We want to print return value, please...  */
-  tp->control.proceed_to_finish = 1;
-
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 181d961d80d..8ed538ea9ec 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct thread_info *tp)
 
   tp->control.stop_step = 0;
 
-  tp->control.proceed_to_finish = 0;
-
   tp->control.stepping_command = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
@@ -6737,31 +6735,28 @@ process_event_stop_test (struct execution_control_state *ecs)
 
     case BPSTAT_WHAT_STEP_RESUME:
       infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
-
       delete_step_resume_breakpoint (ecs->event_thread);
-      if (ecs->event_thread->control.proceed_to_finish
-	  && execution_direction == EXEC_REVERSE)
+      fill_in_stop_func (gdbarch, ecs);
+
+      if (execution_direction == EXEC_REVERSE
+	  && ecs->event_thread->stop_pc () == ecs->stop_func_start)
 	{
 	  struct thread_info *tp = ecs->event_thread;
+	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
 
-	  /* We are finishing a function in reverse, and just hit the
-	     step-resume breakpoint at the start address of the
-	     function, and we're almost there -- just need to back up
-	     by one more single-step, which should take us back to the
-	     function call.  */
-	  tp->control.step_range_start = tp->control.step_range_end = 1;
-	  keep_going (ecs);
-	  return;
-	}
-      fill_in_stop_func (gdbarch, ecs);
-      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
-	  && execution_direction == EXEC_REVERSE)
-	{
-	  /* We are stepping over a function call in reverse, and just
-	     hit the step-resume breakpoint at the start address of
-	     the function.  Go back to single-stepping, which should
-	     take us back to the function call.  */
-	  ecs->event_thread->stepping_over_breakpoint = 1;
+	  /* When setting a step range, need to call set_step_info
+	     to setup the current_line/symtab fields as well.  */
+	  set_step_info (tp, frame, stop_pc_sal);
+
+	  /* We are finishing a function in reverse or stepping over a function
+	     call in reverse, and just hit the step-resume breakpoint at the
+	     start address of the function, and we're almost there -- just need
+	     to back up to the function call.
+
+	     Return using a step range so we will keep stepping back to the
+	     first instruction in the source code line.  */
+	  tp->control.step_range_start = ecs->stop_func_start;
+	  tp->control.step_range_end = ecs->stop_func_start;
 	  keep_going (ecs);
 	  return;
 	}
diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
index d631beb17c8..30635ab1754 100644
--- a/gdb/testsuite/gdb.mi/mi-reverse.exp
+++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
@@ -97,15 +97,10 @@ proc test_controlled_execution_reverse {} {
 	"basics.c" $line_main_callme_1 "" \
 	"reverse finish from callme"
 
-    # Test exec-reverse-next
-    #   It takes two steps to get back to the previous line,
-    #   as the first step moves us to the start of the current line,
-    #   and the one after that moves back to the previous line.
-
-    mi_execute_to "exec-next --reverse 2" \
+    mi_execute_to "exec-next --reverse" \
  	"end-stepping-range" "main" "" \
  	"basics.c" $line_main_hello "" \
- 	"reverse next to get over the call to do_nothing"
+	"reverse next to get over the call to do_nothing"
 
     # Test exec-reverse-step
 
diff --git a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
index 52a87faabf7..9964b4f8e4b 100644
--- a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
@@ -44,6 +44,5 @@ if [supports_process_record] {
 gdb_test "next" {f \(\);} "next to f"
 gdb_test "next" {v = 3;} "next to v = 3"
 
-# FAIL was:
-# 29        g ();
-gdb_test "reverse-next" {f \(\);}
+# Reverse step back into f ().  Puts us at call to g () in function f ().
+gdb_test "reverse-next" {g \(\);}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
new file mode 100644
index 00000000000..42e41b5a2e0
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -0,0 +1,48 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2022 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The reverse finish command should return from a function and stop on
+   the first instruction of the source line where the function call is made.
+   Specifically, the behavior should match doing a reverse next from the
+   first instruction in the function.  GDB should only require one reverse
+   step or next statement to reach the previous source code line.
+
+   This test verifies the fix for gdb bugzilla:
+
+   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+*/
+
+int
+function1 (int a, int b)   // FUNCTION1
+{
+  int ret = 0;
+
+  ret = a + b;
+  return ret;
+}
+
+int
+main(int argc, char* argv[])
+{
+  int a, b;
+
+  a = 1;
+  b = 5;
+
+  function1 (a, b);   // CALL FUNCTION
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
new file mode 100644
index 00000000000..7880de10ffc
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -0,0 +1,108 @@
+# Copyright 2008-2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+### TEST 1: reverse finish from the entry point instruction in
+### function1.
+
+# Set breakpoint at call to function1 in main.
+set FUNCTION_test  [gdb_get_line_number "CALL FUNCTION" $srcfile]
+gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at .*" \
+    "set breakpoint on function1 call to stepi into function"
+
+# Continue to break point at function1 call in main.
+gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*" \
+    "stopped at function1 entry point instruction to stepi into function"
+
+# stepi until we see "{" indicating we entered function1
+cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
+
+delete_breakpoints
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
+    "reverse-finish function1 "
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.   If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
+
+# Clear the recorded log.
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+### TEST 2: reverse finish from the body of function1.
+
+# Set breakpoint at call to function1 in main.
+gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at .*" \
+    "set breakpoint on function1 call to step into body of function"
+
+# Continue to break point at function1 call in main.
+gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*" \
+    "stopped at function1 entry point instruction to step to body of function"
+
+delete_breakpoints
+
+# do a step instruction to get to the body of the function
+gdb_test "step" ".*int ret = 0;.*" "step test 1"
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
+    "reverse-finish function1 call from function body"
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse next at b = 5, from function body"
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse.exp b/gdb/testsuite/gdb.reverse/finish-reverse.exp
index 01ba309420c..a05cb81892a 100644
--- a/gdb/testsuite/gdb.reverse/finish-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/finish-reverse.exp
@@ -16,6 +16,11 @@
 # This file is part of the GDB testsuite.  It tests 'finish' with
 # reverse debugging.
 
+# This test verifies the fix for gdb bugzilla:
+
+# https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+
 if ![supports_reverse] {
     return
 }
diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
index 1ca7c2ce559..eb03051625a 100644
--- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
@@ -56,7 +56,4 @@ gdb_test "next" {v = 3;} "next to v = 3"
 # {
 gdb_test "reverse-step" {nodebug \(\);}
 
-# FAIL was:
-# No more reverse-execution history.
-# {
-gdb_test "reverse-next" {f \(\);}
+gdb_test "reverse-next" {g \(\);}
diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index ad637899e5b..1928cdda217 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -39,39 +39,6 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
-proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
-}
-
 gdb_test_no_output "record"
 gdb_test "next" ".*" "record trace"
 
@@ -91,20 +58,20 @@ gdb_test "reverse-next" "apply\.2.*" \
     "reverse-step through thunks and over inc"
 
 # We can use instruction stepping to step into thunks.
-step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
-step_until "stepi" "indirect_thunk" "inc" \
+cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
+cmd_until "stepi" "indirect_thunk" "inc" \
     "stepi out of call thunk into inc"
 set alphanum_re "\[a-zA-Z0-9\]"
 set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
-step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
-step_until "stepi" "return_thunk" "apply" \
+cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
+cmd_until "stepi" "return_thunk" "apply" \
     "stepi out of return thunk back into apply"
 
-step_until "reverse-stepi" "apply" "return_thunk" \
+cmd_until "reverse-stepi" "apply" "return_thunk" \
     "reverse-stepi into return thunk"
-step_until "reverse-stepi" "return_thunk" "inc" \
+cmd_until "reverse-stepi" "return_thunk" "inc" \
     "reverse-stepi out of return thunk into inc"
-step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
+cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
     "reverse-stepi into call thunk"
-step_until "reverse-stepi" "indirect_thunk" "apply" \
+cmd_until "reverse-stepi" "indirect_thunk" "apply" \
     "reverse-stepi out of call thunk into apply"
diff --git a/gdb/testsuite/gdb.reverse/until-precsave.exp b/gdb/testsuite/gdb.reverse/until-precsave.exp
index 0c2d7537cd6..777aec94ac1 100644
--- a/gdb/testsuite/gdb.reverse/until-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/until-precsave.exp
@@ -142,7 +142,7 @@ gdb_test "advance marker2" \
 # Finish out to main scope (backward)
 
 gdb_test "finish" \
-    " in main .*$srcfile:$bp_location20.*" \
+    "main .*$srcfile:$bp_location20.*" \
     "reverse-finish from marker2"
 
 # Advance backward to last line of factorial (outer invocation)
diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp b/gdb/testsuite/gdb.reverse/until-reverse.exp
index 23fc881dbf2..3a05953329f 100644
--- a/gdb/testsuite/gdb.reverse/until-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/until-reverse.exp
@@ -113,7 +113,7 @@ gdb_test "advance marker2" \
 # Finish out to main scope (backward)
 
 gdb_test "finish" \
-    " in main .*$srcfile:$bp_location20.*" \
+    "main .*$srcfile:$bp_location20.*" \
     "reverse-finish from marker2"
 
 # Advance backward to last line of factorial (outer invocation)
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index c41d4698d66..25f42eb5510 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9301,6 +9301,39 @@ proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
     }
 }
 
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND is a stepping command
+#  CURRENT is a string matching the current location
+#  TARGET  is a string matching the target location
+#  TEST    is the test name
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of 100 steps.
+#
+# TEST passes if the resulting location matches TARGET and fails
+# otherwise.
+
+proc cmd_until { command current target test } {
+    global gdb_prompt
+
+    set count 0
+    gdb_test_multiple "$command" "$test" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < 100 } {
+		send_gdb "$command\n"
+		exp_continue
+	    } else {
+		fail "$test"
+	    }
+	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+}
+
 # Check if the compiler emits epilogue information associated
 # with the closing brace or with the last statement line.
 #
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH 2/2]  fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
       [not found]                                           ` <1d9b21914354bef6a290ac30673741e722e11757.camel@de.ibm.com>
  2023-01-11 18:27                                             ` [PATCH 0/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp Carl Love
  2023-01-11 18:27                                             ` [PATCH 1/2] " Carl Love
@ 2023-01-11 18:27                                             ` Carl Love
  2023-01-13 15:55                                               ` Bruno Larsen
  2 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-11 18:27 UTC (permalink / raw)
  To: Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

GDB maintainers:

This patch fixes the issues with the reverse-finish command on
PowerPC.  The reverse-finish command now correctly stops at the first
instruction in the source code line of the caller.  

The patch adds tests for calling a function via the GEP to the new test
gdb.reverse/finish-reverse-next.exp.

Please let me know if you have any comments on the patch.  Thanks.

                    Carl 

--------------------------------------------------------------
PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp

PowerPC uses two entry points called the local entry point (LEP) and the
global entry point (GEP).  Normally the LEP is used when calling a
function.  However, if the table of contents (TOC) value in
register 3 is not valid the GEP is called to setup the TOC before execution
continues at the LEP.  When executing in reverse, the function
finish_backward sets the break point at the alternate entry point (GEP).
However if the forward execution enters via the normal entry point (LEP),
the reverse execution never sees the break point at the GEP of the
function.  Reverse execution continues until the next break point is
encountered or the end of the recorded log is reached causing gdb to stop
at the wrong place.

This patch adds a new address to struct execution_control_state to hold the
address of the alternate function start address, known as the GEP on
PowerPC.  The finish_backwards function is updated.  If the stopping point
is between the two entry points (the LEP and GEP on PowerPC) , the stepping
range is set to execute back to the alternate entry point (GEP on PowerPC).
Otherwise, a breakpoint is inserted at the normal entry point (LEP on
PowerPC).

Function process_event_stop_test checks uses a stepping range to stop
execution in the caller at the first instruction of the source code line.
Note, on systems that only support one entry point, the address of the two
entry points are the same.

Test finish-reverse-next.exp is updated to include tests for the
reverse-finish command when the function is entered via the normal entry
point (i.e. the LEP) and the alternate entry point (i.e. the GEP).

The patch has been tested on X86 and PowerPC with no regressions.
---
 gdb/infcmd.c                                  |  41 ++++---
 gdb/infrun.c                                  |  21 +++-
 .../gdb.reverse/finish-reverse-next.c         |  41 ++++++-
 .../gdb.reverse/finish-reverse-next.exp       | 107 +++++++++++++++---
 4 files changed, 175 insertions(+), 35 deletions(-)

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 9c42efeae8d..8c30af448ce 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1722,22 +1722,28 @@ finish_backward (struct finish_command_fsm *sm)
   sal = find_pc_line (func_addr, 0);
 
   frame_info_ptr frame = get_selected_frame (nullptr);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  CORE_ADDR alt_entry_point = sal.pc;
+  CORE_ADDR entry_point = alt_entry_point;
 
-  if (sal.pc != pc)
+  if (gdbarch_skip_entrypoint_p (gdbarch))
     {
-      struct gdbarch *gdbarch = get_frame_arch (frame);
+      /* Some architectures, like PowerPC use local and global entry
+	 points.  There is only one Entry Point (GEP = LEP) for other
+	 architectures.  The GEP is an alternate entry point that is used
+	 setup the table of contents (TOC) in register r2 before execution
+	 continues at the LEP.  The LEP is the normal entry point.
+	 The value of entry_point was initialized to the alternate entry
+	 point (GEP).  It will be adjusted if the normal entry point
+	 (LEP) was used.  */
+       entry_point = gdbarch_skip_entrypoint (gdbarch, entry_point);
 
-      /* Set a step-resume at the function's entry point.  Once that's
-	 hit, we'll do one more step backwards.  */
-      symtab_and_line sr_sal;
-      sr_sal.pc = sal.pc;
-      sr_sal.pspace = get_frame_program_space (frame);
-      insert_step_resume_breakpoint_at_sal (gdbarch,
-					    sr_sal, null_frame_id);
     }
-  else
+
+  if (alt_entry_point <= pc && pc <= entry_point)
     {
-      /* We are exactly at the function entry point.  Note that this
+      /* We are exactly at the function entry point, or between the entry
+	 point on platforms that have two (like PowerPC).  Note that this
 	 can only happen at frame #0.
 
 	 When setting a step range, need to call set_step_info
@@ -1746,8 +1752,17 @@ finish_backward (struct finish_command_fsm *sm)
 
       /* Return using a step range so we will keep stepping back
 	 to the first instruction in the source code line.  */
-      tp->control.step_range_start = sal.pc;
-      tp->control.step_range_end = sal.pc;
+      tp->control.step_range_start = alt_entry_point;
+      tp->control.step_range_end = alt_entry_point;
+    }
+  else
+    {
+      symtab_and_line sr_sal;
+      /* Set a step-resume at the function's entry point.  */
+      sr_sal.pc = entry_point;
+      sr_sal.pspace = get_frame_program_space (frame);
+      insert_step_resume_breakpoint_at_sal (gdbarch,
+					    sr_sal, null_frame_id);
     }
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 8ed538ea9ec..89423556ec0 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1868,6 +1868,7 @@ struct execution_control_state
 
   struct target_waitstatus ws;
   int stop_func_filled_in = 0;
+  CORE_ADDR stop_func_alt_start = 0;
   CORE_ADDR stop_func_start = 0;
   CORE_ADDR stop_func_end = 0;
   const char *stop_func_name = nullptr;
@@ -4663,6 +4664,14 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 				    &block);
       ecs->stop_func_name = gsi == nullptr ? nullptr : gsi->print_name ();
 
+      /* PowerPC functions have a Local Entry Point and a Global Entry
+	 Point.  There is only one Entry Point (GEP = LEP) for other
+	 architectures.  The GEP is an alternate entry point that is used
+	 setup the table of contents (TOC) in register r2 before execution
+	 continues at the LEP.  Save the alternate entry point address for
+	 use later.  */
+      ecs->stop_func_alt_start = ecs->stop_func_start;
+
       /* The call to find_pc_partial_function, above, will set
 	 stop_func_start and stop_func_end to the start and end
 	 of the range containing the stop pc.  If this range
@@ -4679,6 +4688,9 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 	    += gdbarch_deprecated_function_start_offset (gdbarch);
 
 	  if (gdbarch_skip_entrypoint_p (gdbarch))
+	    /* The PowerPC architecture uses two entry points.  Stop at the
+	       regular entry point (LEP on PowerPC) initially.  Will setup a
+	       breakpoint for the alternate entry point (GEP) later.  */
 	    ecs->stop_func_start
 	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
 	}
@@ -6738,8 +6750,7 @@ process_event_stop_test (struct execution_control_state *ecs)
       delete_step_resume_breakpoint (ecs->event_thread);
       fill_in_stop_func (gdbarch, ecs);
 
-      if (execution_direction == EXEC_REVERSE
-	  && ecs->event_thread->stop_pc () == ecs->stop_func_start)
+      if (execution_direction == EXEC_REVERSE)
 	{
 	  struct thread_info *tp = ecs->event_thread;
 	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
@@ -6755,7 +6766,7 @@ process_event_stop_test (struct execution_control_state *ecs)
 
 	     Return using a step range so we will keep stepping back to the
 	     first instruction in the source code line.  */
-	  tp->control.step_range_start = ecs->stop_func_start;
+	  tp->control.step_range_start = ecs->stop_func_alt_start;
 	  tp->control.step_range_end = ecs->stop_func_start;
 	  keep_going (ecs);
 	  return;
@@ -6892,8 +6903,10 @@ process_event_stop_test (struct execution_control_state *ecs)
 	 (unless it's the function entry point, in which case
 	 keep going back to the call point).  */
       CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
+
       if (stop_pc == ecs->event_thread->control.step_range_start
-	  && stop_pc != ecs->stop_func_start
+	  && (stop_pc < ecs->stop_func_alt_start
+	      || stop_pc > ecs->stop_func_start)
 	  && execution_direction == EXEC_REVERSE)
 	end_stepping_range (ecs);
       else
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
index 42e41b5a2e0..55f81d2bc01 100644
--- a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -1,4 +1,4 @@
-/* This testcase is part of GDB, the GNU debugger.
+j/* This testcase is part of GDB, the GNU debugger.
 
    Copyright 2012-2022 Free Software Foundation, Inc.
 
@@ -24,11 +24,37 @@
    This test verifies the fix for gdb bugzilla:
 
    https://sourceware.org/bugzilla/show_bug.cgi?id=29927
-*/
+
+   PowerPC supports two entry points to a function.  The normal entry point
+   is called the local entry point (LEP).  The alternat entry point is called
+   the global entry point (GEP).  The GEP is only used if the table of
+   contents (TOC) value stored in register r2 needs to be setup prior to
+   execution starting at the LEP.  A function call via a function pointer
+   will entry via the GEP.  A normal function call will enter via the LEP.
+
+   This test has been expanded to include tests to verify the reverse-finish
+   command works properly if the function is called via the GEP.  The original
+   test only verified the reverse-finish command for a normal call that used
+   the LEP.  */
 
 int
 function1 (int a, int b)   // FUNCTION1
 {
+  /* The assembly code for this function when compiled for PowerPC is as
+     follows:
+
+     0000000010000758 <function1>:
+     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
+     1000075c:	00 7f 42 38 	addi    r2,r2,32512
+     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
+     10000764:	10 00 01 f8 	std     r0,16(r1)
+     ....
+
+     When the function is called on PowerPC with function1 (a, b) the call
+     enters at the Local Entry Point (LEP).  When the function is called via
+     a function pointer, the Global Entry Point (GEP) for function1 is used.
+     The GEP sets up register 2 before reaching the LEP.
+  */
   int ret = 0;
 
   ret = a + b;
@@ -39,10 +65,19 @@ int
 main(int argc, char* argv[])
 {
   int a, b;
+  int (*funp) (int, int) = &function1;
+
+  /* Call function via Local Entry Point (LEP).  */
 
   a = 1;
   b = 5;
 
-  function1 (a, b);   // CALL FUNCTION
+  function1 (a, b);   // CALL VIA LEP
+
+  /* Call function via Global Entry Point (GEP).  */
+  a = 10;
+  b = 50;
+
+  funp (a, b);        // CALL VIA GEP
   return 0;
 }
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
index 7880de10ffc..fbc024b48b9 100644
--- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -31,6 +31,18 @@
 # This test verifies the fix for gdb bugzilla:
 #   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
 
+# PowerPC supports two entry points to a function.  The normal entry point
+# is called the local entry point (LEP).  The alternat entry point is called
+# the global entry point (GEP).  The GEP is only used if the table of
+# contents (TOC) value stored in register r2 needs to be setup prior to
+# execution starting at the LEP.  A function call via a function pointer
+# will entry via the GEP.  A normal function call will enter via the LEP.
+#
+# This test has been expanded to include tests to verify the reverse-finish
+# command works properly if the function is called via the GEP.  The original
+# test only verified the reverse-finish command for a normal call that used
+# the LEP.
+
 if ![supports_reverse] {
     return
 }
@@ -50,32 +62,32 @@ if [supports_process_record] {
 }
 
 
-### TEST 1: reverse finish from the entry point instruction in
-### function1.
+### TEST 1: reverse finish from the entry point instruction (LEP) in
+### function1 when called using the normal entry point (LEP).
 
 # Set breakpoint at call to function1 in main.
-set FUNCTION_test  [gdb_get_line_number "CALL FUNCTION" $srcfile]
-gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at .*" \
-    "set breakpoint on function1 call to stepi into function"
+set LEP_test  [gdb_get_line_number "CALL VIA LEP" $srcfile]
+gdb_test "break $srcfile:$LEP_test" "Breakpoint $decimal at .*" \
+    "set breakpoint on function1 LEP call to stepi into function"
 
 # Continue to break point at function1 call in main.
 gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*" \
     "stopped at function1 entry point instruction to stepi into function"
 
 # stepi until we see "{" indicating we entered function1
-cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
+cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call"
 
 delete_breakpoints
 
-gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
-    "reverse-finish function1 "
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from LEP "
 
 # Check to make sure we stopped at the first instruction in the source code
 # line.  It should only take one reverse next command to get to the previous
 # source line.   If GDB stops at the last instruction in the source code line
 # it will take two reverse next instructions to get to the previous source
 # line.
-gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from LEP"
 
 # Clear the recorded log.
 gdb_test "record stop"  "Process record is stopped.*" \
@@ -83,26 +95,91 @@ gdb_test "record stop"  "Process record is stopped.*" \
 gdb_test_no_output "record" "turn on process record for test2"
 
 
-### TEST 2: reverse finish from the body of function1.
+### TEST 2: reverse finish from the body of function1 when called using the
+### normal entry point (LEP).
 
 # Set breakpoint at call to function1 in main.
-gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at .*" \
-    "set breakpoint on function1 call to step into body of function"
+gdb_test "break $srcfile:$LEP_test" "Breakpoint $decimal at .*" \
+    "set breakpoint on function1 LEP call to step into body of function"
 
 # Continue to break point at function1 call in main.
 gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*" \
-    "stopped at function1 entry point instruction to step to body of function"
+    "stopped at function1 entry point instruction to step body of function"
 
 delete_breakpoints
 
 # do a step instruction to get to the body of the function
 gdb_test "step" ".*int ret = 0;.*" "step test 1"
 
-gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
-    "reverse-finish function1 call from function body"
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from function body"
 
 # Check to make sure we stopped at the first instruction in the source code
 # line.  It should only take one reverse next command to get to the previous
 # source line.
 gdb_test "reverse-next" ".*b = 5;.*" \
     "reverse next at b = 5, from function body"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test2"
+gdb_test_no_output "record" "turn on process record for test3"
+
+
+### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_test "break $srcfile:$GEP_test" "Breakpoint $decimal at .*" \
+    "set breakpoint on function1 GEP call to stepi into function"
+
+# Continue to break point at funp call in main.
+gdb_test "continue" "Breakpoint $decimal.*funp \\(a, b\\).*" \
+    "stopped at funp entry point instruction"
+
+# stepi until we see "{" indicating we entered function.
+cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
+
+delete_breakpoints
+
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP"
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.  If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 50;.*" "reverse next at b = 50, call from GEP"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test3"
+gdb_test_no_output "record" "turn on process record for test4"
+
+
+### TEST 4: reverse finish from the body of function 1 when calling using the
+### alternate entrypoint (GEP).
+gdb_test "break $srcfile:$GEP_test" "Breakpoint $decimal at .*" \
+    "set breakpoint on funp GEP call to step into body of function"
+
+# Continue to break point at funp call.
+gdb_test "continue" "Breakpoint $decimal,.*funp \\(a, b\\).*" \
+    "stopped at funp call"
+
+# Step into body of funp, called via GEP.
+gdb_test "step" ".*int ret = 0;.*" "step test 2"
+
+delete_breakpoints
+
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "reverse-finish function1 GEP call, from function body  "
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.  If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next at b = 50 from function body"
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-11 18:27                                             ` [PATCH 1/2] " Carl Love
@ 2023-01-12 16:56                                               ` Tom de Vries
  2023-01-12 18:54                                                 ` Carl Love
  2023-01-13 13:33                                               ` Bruno Larsen
  2023-01-13 15:42                                               ` [PATCH 1/2] " Bruno Larsen
  2 siblings, 1 reply; 105+ messages in thread
From: Tom de Vries @ 2023-01-12 16:56 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 1/11/23 19:27, Carl Love via Gdb-patches wrote:
> This patch requires a number of regression tests to be updated.  Test
> gdb.mi/mi-reverse.exp no longer needs to execute two steps to get to the
> previous line.

Hi Carl,

FYI, I stumbled upon a FAIL (not related to reverse-finish) in 
gdb.reverse/step-reverse.exp, see PR29962 ( 
https://sourceware.org/bugzilla/show_bug.cgi?id=29962 ) and wrote a 
tentative patch for it  ( 
https://sourceware.org/bugzilla/attachment.cgi?id=14588 ), and ended up 
making the same fix in the gdb.mi/mi-reverse.exp test-case.

I'll test the patch a bit further before posting it.

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-12 16:56                                               ` Tom de Vries
@ 2023-01-12 18:54                                                 ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-12 18:54 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

Tom:



On Thu, 2023-01-12 at 17:56 +0100, Tom de Vries wrote:
> On 1/11/23 19:27, Carl Love via Gdb-patches wrote:
> > This patch requires a number of regression tests to be
> > updated.  Test
> > gdb.mi/mi-reverse.exp no longer needs to execute two steps to get
> > to the
> > previous line.
> 
> Hi Carl,
> 
> FYI, I stumbled upon a FAIL (not related to reverse-finish) in 
> gdb.reverse/step-reverse.exp, see PR29962 ( 
> https://sourceware.org/bugzilla/show_bug.cgi?id=29962  ) and wrote
> a 
> tentative patch for it  ( 
> https://sourceware.org/bugzilla/attachment.cgi?id=14588  ), and ended
> up 
> making the same fix in the gdb.mi/mi-reverse.exp test-case.
> 
> I'll test the patch a bit further before posting it.

On PPC64 there are also issues with reverse stepping over a line that
has multiple executable statements in it.  Not sure if this is related
to what you are seeing.  

There is a patch that I have worked on with Luis Machado to fix.  We
have posted versions of it to the mailing list.  The subject line is:

Fix reverse stepping multiple contiguous PC ranges over the line table

which might be relevant.  Unfortunately, work on this patch has been
stalled for awhile.  The patch fixes 5 failures in  gdb.reverse/solib-
precsave.exp and 5 failures in gdb.reverse/solib-reverse.exp.  

You might want to take a look at it to see if it helps.

                            Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-11 18:27                                             ` [PATCH 1/2] " Carl Love
  2023-01-12 16:56                                               ` Tom de Vries
@ 2023-01-13 13:33                                               ` Bruno Larsen
  2023-01-13 16:43                                                 ` Carl Love
  2023-01-14 18:08                                                 ` Carl Love
  2023-01-13 15:42                                               ` [PATCH 1/2] " Bruno Larsen
  2 siblings, 2 replies; 105+ messages in thread
From: Bruno Larsen @ 2023-01-13 13:33 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 11/01/2023 19:27, Carl Love via Gdb-patches wrote:
> GDB maintainers:
>
> This patch fixes the issues with the reverse-finish command on X86.
> The reverse-finish command now correctly stops at the first instruction
> in the source code line of the caller.  It now only requires a single
> reverse-step or reverse-next instruction to get back to the previous
> source code line.
>
> It also adds a new testcase, gdb.reverse/finish-reverse-next.exp, and
> updates several existing testcases.
>
> Please let me know if you have any comments on the patch.  Thanks.
Thanks for looking at this, this is a nice change. I just have a couple 
of comments, mostly related to the testsuite side.
>                      Carl
>
> --------------------------------------------------------------
> X86: reverse-finish fix
>
> Currently on X86, when executing the finish command in reverse, gdb does a
> single step from the first instruction in the callee to get back to the
> caller.  GDB stops on the last instruction in the source code line where
> the call was made.  When stopped at the last instruction of the source code
> line, a reverse next or step command will stop at the first instruction
> of the same source code line thus requiring two step/next commands to
> reach the previous source code line.  It should only require one step/next
> command to reach the previous source code line.
>
> By contrast, a reverse next or step command from the first line in a
> function stops at the first instruction in the source code line where the
> call was made.
>
> This patch fixes the reverse finish command so it will stop at the first
> instruction of the source line where the function call was made.  The
> behavior on X86 for the reverse-finish command now matches doing a
> reverse-next from the beginning of the function.
>
> The proceed_to_finish flag in struct thread_control_state is no longer
> used.  This patch removes the declaration, initialization and setting of
> the flag.
>
> This patch requires a number of regression tests to be updated.  Test
> gdb.mi/mi-reverse.exp no longer needs to execute two steps to get to the
> previous line.  The gdb output for tests gdb.reverse/until-precsave.exp
> and gdb.reverse/until-reverse.exp changed slightly.  The expected result in
> tests gdb.reverse/amd64-ailcall-reverse.exp and
s/ailcall/tailcall
> gdb.reverse/singlejmp-reverse.exp are updated to the correct expected
> result.
>
> This patch adds a new test gdb.reverse/finish-reverse-next.exp to test the
> reverse-finish command when returning from the entry point and from the
> body of the function.
>
> The step_until proceedure in test gdb.reverse/step-indirect-call-thunk.exp
> was moved to lib/gdb.exp and renamed cmd_until.
I'm not a big fan of the name cmd_until, because it sounded to me like 
you were testing the GDB command until. I think repeat_cmd_until or 
repeat_until would avoid this possible confusion.
>
> The patch has been tested on X86 and PowerPC to verify no additional
> regression failures occured.
>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29927
If you add record/29927 somewhere along the text of your commit message, 
there is some automation that will comment on the bugzilla bug 
specifying this commit. Might be worth doing for future reference.
> ---
>   gdb/gdbthread.h                               |   4 -
>   gdb/infcall.c                                 |   3 -
>   gdb/infcmd.c                                  |  32 +++---
>   gdb/infrun.c                                  |  41 +++----
>   gdb/testsuite/gdb.mi/mi-reverse.exp           |   9 +-
>   .../gdb.reverse/amd64-tailcall-reverse.exp    |   5 +-
>   .../gdb.reverse/finish-reverse-next.c         |  48 ++++++++
>   .../gdb.reverse/finish-reverse-next.exp       | 108 ++++++++++++++++++
>   gdb/testsuite/gdb.reverse/finish-reverse.exp  |   5 +
>   .../gdb.reverse/singlejmp-reverse.exp         |   5 +-
>   .../gdb.reverse/step-indirect-call-thunk.exp  |  49 ++------
>   gdb/testsuite/gdb.reverse/until-precsave.exp  |   2 +-
>   gdb/testsuite/gdb.reverse/until-reverse.exp   |   2 +-
>   gdb/testsuite/lib/gdb.exp                     |  33 ++++++
>   14 files changed, 240 insertions(+), 106 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
>   create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp
>
> diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
> index 11d69fceab0..e4edff2d621 100644
> --- a/gdb/gdbthread.h
> +++ b/gdb/gdbthread.h
> @@ -150,10 +150,6 @@ struct thread_control_state
>        the finished single step.  */
>     int trap_expected = 0;
>   
> -  /* Nonzero if the thread is being proceeded for a "finish" command
> -     or a similar situation when return value should be printed.  */
> -  int proceed_to_finish = 0;
> -
>     /* Nonzero if the thread is being proceeded for an inferior function
>        call.  */
>     int in_infcall = 0;
> diff --git a/gdb/infcall.c b/gdb/infcall.c
> index e09904f9a35..116605c43ef 100644
> --- a/gdb/infcall.c
> +++ b/gdb/infcall.c
> @@ -625,9 +625,6 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
>   
>     disable_watchpoints_before_interactive_call_start ();
>   
> -  /* We want to print return value, please...  */
> -  call_thread->control.proceed_to_finish = 1;
> -
>     try
>       {
>         /* Infcalls run synchronously, in the foreground.  */
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 0497ad05091..9c42efeae8d 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1721,19 +1721,10 @@ finish_backward (struct finish_command_fsm *sm)
>   
>     sal = find_pc_line (func_addr, 0);
>   
> -  tp->control.proceed_to_finish = 1;
> -  /* Special case: if we're sitting at the function entry point,
> -     then all we need to do is take a reverse singlestep.  We
> -     don't need to set a breakpoint, and indeed it would do us
> -     no good to do so.
> -
> -     Note that this can only happen at frame #0, since there's
> -     no way that a function up the stack can have a return address
> -     that's equal to its entry point.  */
> +  frame_info_ptr frame = get_selected_frame (nullptr);
>   
>     if (sal.pc != pc)
>       {
> -      frame_info_ptr frame = get_selected_frame (nullptr);
>         struct gdbarch *gdbarch = get_frame_arch (frame);
>   
>         /* Set a step-resume at the function's entry point.  Once that's
> @@ -1743,16 +1734,22 @@ finish_backward (struct finish_command_fsm *sm)
>         sr_sal.pspace = get_frame_program_space (frame);
>         insert_step_resume_breakpoint_at_sal (gdbarch,
>   					    sr_sal, null_frame_id);
> -
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>       }
>     else
>       {
> -      /* We're almost there -- we just need to back up by one more
> -	 single-step.  */
> -      tp->control.step_range_start = tp->control.step_range_end = 1;
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> +      /* We are exactly at the function entry point.  Note that this
> +	 can only happen at frame #0.
> +
> +	 When setting a step range, need to call set_step_info
> +	 to setup the current_line/symtab fields as well.  */
> +      set_step_info (tp, frame, find_pc_line (pc, 0));
> +
> +      /* Return using a step range so we will keep stepping back
> +	 to the first instruction in the source code line.  */
> +      tp->control.step_range_start = sal.pc;
> +      tp->control.step_range_end = sal.pc;
>       }
> +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>   }
>   
>   /* finish_forward -- helper function for finish_command.  FRAME is the
> @@ -1778,9 +1775,6 @@ finish_forward (struct finish_command_fsm *sm, frame_info_ptr frame)
>   
>     set_longjmp_breakpoint (tp, frame_id);
>   
> -  /* We want to print return value, please...  */
> -  tp->control.proceed_to_finish = 1;
> -
>     proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>   }
>   
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 181d961d80d..8ed538ea9ec 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct thread_info *tp)
>   
>     tp->control.stop_step = 0;
>   
> -  tp->control.proceed_to_finish = 0;
> -
>     tp->control.stepping_command = 0;
>   
>     /* Discard any remaining commands or status from previous stop.  */
> @@ -6737,31 +6735,28 @@ process_event_stop_test (struct execution_control_state *ecs)
>   
>       case BPSTAT_WHAT_STEP_RESUME:
>         infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
> -
>         delete_step_resume_breakpoint (ecs->event_thread);
> -      if (ecs->event_thread->control.proceed_to_finish
> -	  && execution_direction == EXEC_REVERSE)
> +      fill_in_stop_func (gdbarch, ecs);
> +
> +      if (execution_direction == EXEC_REVERSE
> +	  && ecs->event_thread->stop_pc () == ecs->stop_func_start)
Is there any reason to invert the order of checks here? The second if 
clause is the same and keeping that would make the changes easier to parse.
>   	{
>   	  struct thread_info *tp = ecs->event_thread;
> +	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
>   
> -	  /* We are finishing a function in reverse, and just hit the
> -	     step-resume breakpoint at the start address of the
> -	     function, and we're almost there -- just need to back up
> -	     by one more single-step, which should take us back to the
> -	     function call.  */
> -	  tp->control.step_range_start = tp->control.step_range_end = 1;
> -	  keep_going (ecs);
> -	  return;
> -	}
> -      fill_in_stop_func (gdbarch, ecs);
> -      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
> -	  && execution_direction == EXEC_REVERSE)
> -	{
> -	  /* We are stepping over a function call in reverse, and just
> -	     hit the step-resume breakpoint at the start address of
> -	     the function.  Go back to single-stepping, which should
> -	     take us back to the function call.  */
> -	  ecs->event_thread->stepping_over_breakpoint = 1;
> +	  /* When setting a step range, need to call set_step_info
> +	     to setup the current_line/symtab fields as well.  */
> +	  set_step_info (tp, frame, stop_pc_sal);
> +
> +	  /* We are finishing a function in reverse or stepping over a function
> +	     call in reverse, and just hit the step-resume breakpoint at the
> +	     start address of the function, and we're almost there -- just need
> +	     to back up to the function call.
> +
> +	     Return using a step range so we will keep stepping back to the
> +	     first instruction in the source code line.  */
> +	  tp->control.step_range_start = ecs->stop_func_start;
> +	  tp->control.step_range_end = ecs->stop_func_start;
>   	  keep_going (ecs);
>   	  return;
>   	}
> diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
> index d631beb17c8..30635ab1754 100644
> --- a/gdb/testsuite/gdb.mi/mi-reverse.exp
> +++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
> @@ -97,15 +97,10 @@ proc test_controlled_execution_reverse {} {
>   	"basics.c" $line_main_callme_1 "" \
>   	"reverse finish from callme"
>   
> -    # Test exec-reverse-next
> -    #   It takes two steps to get back to the previous line,
> -    #   as the first step moves us to the start of the current line,
> -    #   and the one after that moves back to the previous line.
> -
> -    mi_execute_to "exec-next --reverse 2" \
> +    mi_execute_to "exec-next --reverse" \
>    	"end-stepping-range" "main" "" \
>    	"basics.c" $line_main_hello "" \
> - 	"reverse next to get over the call to do_nothing"
> +	"reverse next to get over the call to do_nothing"
>   
>       # Test exec-reverse-step
>   
> diff --git a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> index 52a87faabf7..9964b4f8e4b 100644
> --- a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> +++ b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> @@ -44,6 +44,5 @@ if [supports_process_record] {
>   gdb_test "next" {f \(\);} "next to f"
>   gdb_test "next" {v = 3;} "next to v = 3"
>   
> -# FAIL was:
> -# 29        g ();
> -gdb_test "reverse-next" {f \(\);}
> +# Reverse step back into f ().  Puts us at call to g () in function f ().
> +gdb_test "reverse-next" {g \(\);}
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> new file mode 100644
> index 00000000000..42e41b5a2e0
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> @@ -0,0 +1,48 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2012-2022 Free Software Foundation, Inc.
copyright year should be 2023.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +/* The reverse finish command should return from a function and stop on
> +   the first instruction of the source line where the function call is made.
> +   Specifically, the behavior should match doing a reverse next from the
> +   first instruction in the function.  GDB should only require one reverse
> +   step or next statement to reach the previous source code line.
> +
> +   This test verifies the fix for gdb bugzilla:
> +
> +   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +*/
> +
> +int
> +function1 (int a, int b)   // FUNCTION1
> +{
> +  int ret = 0;
> +
> +  ret = a + b;
> +  return ret;
> +}
> +
> +int
> +main(int argc, char* argv[])
> +{
> +  int a, b;
> +
> +  a = 1;
> +  b = 5;
> +
> +  function1 (a, b);   // CALL FUNCTION
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> new file mode 100644
> index 00000000000..7880de10ffc
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> @@ -0,0 +1,108 @@
> +# Copyright 2008-2022 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +# This file is part of the GDB testsuite.  It tests reverse stepping.
> +# Lots of code borrowed from "step-test.exp".
> +
> +# The reverse finish command should return from a function and stop on
> +# the first instruction of the source line where the function call is made.
> +# Specifically, the behavior should match doing a reverse next from the
> +# first instruction in the function.  GDB should only take one reverse step
> +# or next statement to reach the previous source code line.
> +
> +# This testcase verifies the reverse-finish command stops at the first
> +# instruction in the source code line where the function was called.  There
> +# are two scenarios that must be checked:
> +#   1) gdb is at the entry point instruction for the function
> +#   2) gdb is in the body of the function.

While testing locally, I ran into a bug with reverse finish at the 
epilogue of the function, that your patch also fixed. It would be nice 
if the test extended that. And since the bug was that GDB stopped 
responding and even ctrl+c did nothing, I would suggest adding it as the 
last test.

> +
> +# This test verifies the fix for gdb bugzilla:
> +#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +if ![supports_reverse] {
> +    return
> +}
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
> +    return -1
> +}
> +
> +runto_main
> +set target_remote [gdb_is_target_remote]
> +
> +if [supports_process_record] {
> +    # Activate process record/replay.
> +    gdb_test_no_output "record" "turn on process record for test1"
> +}
> +
> +
> +### TEST 1: reverse finish from the entry point instruction in
> +### function1.
> +
> +# Set breakpoint at call to function1 in main.
> +set FUNCTION_test  [gdb_get_line_number "CALL FUNCTION" $srcfile]
> +gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at .*" \
> +    "set breakpoint on function1 call to stepi into function"

There is a proc in lib/gdb.exp called gdb_breakpoint which couldsimplify 
this gdb_test to

gdb_breakpoint $srcfile:$FUNCTION_test temporary

And would remove the need for the delete_breakpoints call later.

> +
> +# Continue to break point at function1 call in main.
> +gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*" \
> +    "stopped at function1 entry point instruction to stepi into function"
You can use gdb_continue_to_breakpoint here instead.
> +
> +# stepi until we see "{" indicating we entered function1
> +cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
> +
> +delete_breakpoints
> +
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
> +    "reverse-finish function1 "
> +
> +# Check to make sure we stopped at the first instruction in the source code
> +# line.  It should only take one reverse next command to get to the previous
> +# source line.   If GDB stops at the last instruction in the source code line
> +# it will take two reverse next instructions to get to the previous source
> +# line.
> +gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
> +
> +# Clear the recorded log.
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test1"
> +gdb_test_no_output "record" "turn on process record for test2"
> +
> +
> +### TEST 2: reverse finish from the body of function1.
> +
> +# Set breakpoint at call to function1 in main.
> +gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at .*" \
> +    "set breakpoint on function1 call to step into body of function"
> +
> +# Continue to break point at function1 call in main.
> +gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*" \
> +    "stopped at function1 entry point instruction to step to body of function"
> +
> +delete_breakpoints
> +
> +# do a step instruction to get to the body of the function
> +gdb_test "step" ".*int ret = 0;.*" "step test 1"
> +
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
> +    "reverse-finish function1 call from function body"
> +
> +# Check to make sure we stopped at the first instruction in the source code
> +# line.  It should only take one reverse next command to get to the previous
> +# source line.
> +gdb_test "reverse-next" ".*b = 5;.*" \
> +    "reverse next at b = 5, from function body"
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse.exp b/gdb/testsuite/gdb.reverse/finish-reverse.exp
> index 01ba309420c..a05cb81892a 100644
> --- a/gdb/testsuite/gdb.reverse/finish-reverse.exp
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse.exp
> @@ -16,6 +16,11 @@
>   # This file is part of the GDB testsuite.  It tests 'finish' with
>   # reverse debugging.
>   
> +# This test verifies the fix for gdb bugzilla:
> +
> +# https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +

Is this comment a left over from an earlier version?

I actually wonder if the whole new test is needed, or if you can just 
add a couple of new tests to finish-reverse.exp; is there any reason you 
went with the new test instead?

>   if ![supports_reverse] {
>       return
>   }
> diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> index 1ca7c2ce559..eb03051625a 100644
> --- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> +++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> @@ -56,7 +56,4 @@ gdb_test "next" {v = 3;} "next to v = 3"
>   # {
>   gdb_test "reverse-step" {nodebug \(\);}
>   
> -# FAIL was:
> -# No more reverse-execution history.
> -# {
> -gdb_test "reverse-next" {f \(\);}
> +gdb_test "reverse-next" {g \(\);}
> diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> index ad637899e5b..1928cdda217 100644
> --- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> +++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> @@ -39,39 +39,6 @@ if { ![runto_main] } {
>       return -1
>   }
>   
> -# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
> -#
> -#  COMMAND is a stepping command
> -#  CURRENT is a string matching the current location
> -#  TARGET  is a string matching the target location
> -#  TEST    is the test name
> -#
> -# The function issues repeated COMMANDs as long as the location matches
> -# CURRENT up to a maximum of 100 steps.
> -#
> -# TEST passes if the resulting location matches TARGET and fails
> -# otherwise.
> -#
> -proc step_until { command current target test } {
> -    global gdb_prompt
> -
> -    set count 0
> -    gdb_test_multiple "$command" "$test" {
> -        -re "$current.*$gdb_prompt $" {
> -            incr count
> -            if { $count < 100 } {
> -                send_gdb "$command\n"
> -                exp_continue
> -            } else {
> -                fail "$test"
> -            }
> -        }
> -        -re "$target.*$gdb_prompt $" {
> -            pass "$test"
> -        }
> -    }
> -}
> -
>   gdb_test_no_output "record"
>   gdb_test "next" ".*" "record trace"
>   
> @@ -91,20 +58,20 @@ gdb_test "reverse-next" "apply\.2.*" \
>       "reverse-step through thunks and over inc"
>   
>   # We can use instruction stepping to step into thunks.
> -step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
> -step_until "stepi" "indirect_thunk" "inc" \
> +cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
> +cmd_until "stepi" "indirect_thunk" "inc" \
>       "stepi out of call thunk into inc"
>   set alphanum_re "\[a-zA-Z0-9\]"
>   set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
> -step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
> -step_until "stepi" "return_thunk" "apply" \
> +cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
> +cmd_until "stepi" "return_thunk" "apply" \
>       "stepi out of return thunk back into apply"
>   
> -step_until "reverse-stepi" "apply" "return_thunk" \
> +cmd_until "reverse-stepi" "apply" "return_thunk" \
>       "reverse-stepi into return thunk"
> -step_until "reverse-stepi" "return_thunk" "inc" \
> +cmd_until "reverse-stepi" "return_thunk" "inc" \
>       "reverse-stepi out of return thunk into inc"
> -step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
> +cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
>       "reverse-stepi into call thunk"
> -step_until "reverse-stepi" "indirect_thunk" "apply" \
> +cmd_until "reverse-stepi" "indirect_thunk" "apply" \
>       "reverse-stepi out of call thunk into apply"
> diff --git a/gdb/testsuite/gdb.reverse/until-precsave.exp b/gdb/testsuite/gdb.reverse/until-precsave.exp
> index 0c2d7537cd6..777aec94ac1 100644
> --- a/gdb/testsuite/gdb.reverse/until-precsave.exp
> +++ b/gdb/testsuite/gdb.reverse/until-precsave.exp
> @@ -142,7 +142,7 @@ gdb_test "advance marker2" \
>   # Finish out to main scope (backward)
>   
>   gdb_test "finish" \
> -    " in main .*$srcfile:$bp_location20.*" \
> +    "main .*$srcfile:$bp_location20.*" \
This change doesn't seem connected to anything in this patch, is this 
just a cosmetic change or was there some problem?
>       "reverse-finish from marker2"
>   
>   # Advance backward to last line of factorial (outer invocation)
> diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp b/gdb/testsuite/gdb.reverse/until-reverse.exp
> index 23fc881dbf2..3a05953329f 100644
> --- a/gdb/testsuite/gdb.reverse/until-reverse.exp
> +++ b/gdb/testsuite/gdb.reverse/until-reverse.exp
> @@ -113,7 +113,7 @@ gdb_test "advance marker2" \
>   # Finish out to main scope (backward)
>   
>   gdb_test "finish" \
> -    " in main .*$srcfile:$bp_location20.*" \
> +    "main .*$srcfile:$bp_location20.*" \
same here.
>       "reverse-finish from marker2"
>   
>   # Advance backward to last line of factorial (outer invocation)
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index c41d4698d66..25f42eb5510 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -9301,6 +9301,39 @@ proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
>       }
>   }
>   
> +# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
> +#
> +#  COMMAND is a stepping command
> +#  CURRENT is a string matching the current location
> +#  TARGET  is a string matching the target location
> +#  TEST    is the test name
> +#
> +# The function issues repeated COMMANDs as long as the location matches
> +# CURRENT up to a maximum of 100 steps.
> +#
> +# TEST passes if the resulting location matches TARGET and fails
> +# otherwise.
> +
> +proc cmd_until { command current target test } {
> +    global gdb_prompt
> +
> +    set count 0
> +    gdb_test_multiple "$command" "$test" {
> +	-re "$current.*$gdb_prompt $" {
> +	    incr count
> +	    if { $count < 100 } {
> +		send_gdb "$command\n"
> +		exp_continue
> +	    } else {
> +		fail "$test"
> +	    }
> +	}
> +	-re "$target.*$gdb_prompt $" {
> +	    pass "$test"
> +	}
> +    }
> +}
> +
>   # Check if the compiler emits epilogue information associated
>   # with the closing brace or with the last statement line.
>   #


-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-11 18:27                                             ` [PATCH 1/2] " Carl Love
  2023-01-12 16:56                                               ` Tom de Vries
  2023-01-13 13:33                                               ` Bruno Larsen
@ 2023-01-13 15:42                                               ` Bruno Larsen
  2 siblings, 0 replies; 105+ messages in thread
From: Bruno Larsen @ 2023-01-13 15:42 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 11/01/2023 19:27, Carl Love via Gdb-patches wrote:
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 181d961d80d..8ed538ea9ec 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct thread_info *tp)
>   
>     tp->control.stop_step = 0;
>   
> -  tp->control.proceed_to_finish = 0;
> -
>     tp->control.stepping_command = 0;
>   
>     /* Discard any remaining commands or status from previous stop.  */
> @@ -6737,31 +6735,28 @@ process_event_stop_test (struct execution_control_state *ecs)
>   
>       case BPSTAT_WHAT_STEP_RESUME:
Something else that I failed to notice. Since you removed both comments 
that mention that this case is here for reverse finishing, there is no 
good way to figure out what GDB wants to do when this part of the code 
is reached. Adding a comment here mentioning it would fix that.
>         infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
> -
>         delete_step_resume_breakpoint (ecs->event_thread);
> -      if (ecs->event_thread->control.proceed_to_finish
> -	  && execution_direction == EXEC_REVERSE)
> +      fill_in_stop_func (gdbarch, ecs);
> +
> +      if (execution_direction == EXEC_REVERSE
> +	  && ecs->event_thread->stop_pc () == ecs->stop_func_start)
>   	{
>   	  struct thread_info *tp = ecs->event_thread;
> +	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
>   
> -	  /* We are finishing a function in reverse, and just hit the
> -	     step-resume breakpoint at the start address of the
> -	     function, and we're almost there -- just need to back up
> -	     by one more single-step, which should take us back to the
> -	     function call.  */
> -	  tp->control.step_range_start = tp->control.step_range_end = 1;
> -	  keep_going (ecs);
> -	  return;
> -	}
> -      fill_in_stop_func (gdbarch, ecs);
> -      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
> -	  && execution_direction == EXEC_REVERSE)
> -	{
> -	  /* We are stepping over a function call in reverse, and just
> -	     hit the step-resume breakpoint at the start address of
> -	     the function.  Go back to single-stepping, which should
> -	     take us back to the function call.  */
> -	  ecs->event_thread->stepping_over_breakpoint = 1;
> +	  /* When setting a step range, need to call set_step_info
> +	     to setup the current_line/symtab fields as well.  */
> +	  set_step_info (tp, frame, stop_pc_sal);
> +
> +	  /* We are finishing a function in reverse or stepping over a function
> +	     call in reverse, and just hit the step-resume breakpoint at the
> +	     start address of the function, and we're almost there -- just need
> +	     to back up to the function call.
> +
> +	     Return using a step range so we will keep stepping back to the
> +	     first instruction in the source code line.  */
> +	  tp->control.step_range_start = ecs->stop_func_start;
> +	  tp->control.step_range_end = ecs->stop_func_start;
>   	  keep_going (ecs);
>   	  return;
>   	}


-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-11 18:27                                             ` [PATCH 2/2] " Carl Love
@ 2023-01-13 15:55                                               ` Bruno Larsen
  2023-01-14 18:08                                                 ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-01-13 15:55 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 11/01/2023 19:27, Carl Love via Gdb-patches wrote:
> GDB maintainers:
>
> This patch fixes the issues with the reverse-finish command on
> PowerPC.  The reverse-finish command now correctly stops at the first
> instruction in the source code line of the caller.
>
> The patch adds tests for calling a function via the GEP to the new test
> gdb.reverse/finish-reverse-next.exp.
>
> Please let me know if you have any comments on the patch.  Thanks.
I'm not all that familiar with PowerPC ABI and I dont have a computer 
handy to test that the patch fixes the problem, but the logic seems 
sound. Just a few nits inlined.
>
>                      Carl
>
> --------------------------------------------------------------
> PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
>
> PowerPC uses two entry points called the local entry point (LEP) and the
> global entry point (GEP).  Normally the LEP is used when calling a
> function.  However, if the table of contents (TOC) value in
> register 3 is not valid the GEP is called to setup the TOC before execution
> continues at the LEP.  When executing in reverse, the function
> finish_backward sets the break point at the alternate entry point (GEP).
> However if the forward execution enters via the normal entry point (LEP),
> the reverse execution never sees the break point at the GEP of the
> function.  Reverse execution continues until the next break point is
> encountered or the end of the recorded log is reached causing gdb to stop
> at the wrong place.
>
> This patch adds a new address to struct execution_control_state to hold the
> address of the alternate function start address, known as the GEP on
> PowerPC.  The finish_backwards function is updated.  If the stopping point
> is between the two entry points (the LEP and GEP on PowerPC) , the stepping
> range is set to execute back to the alternate entry point (GEP on PowerPC).
> Otherwise, a breakpoint is inserted at the normal entry point (LEP on
> PowerPC).
>
> Function process_event_stop_test checks uses a stepping range to stop
> execution in the caller at the first instruction of the source code line.
> Note, on systems that only support one entry point, the address of the two
> entry points are the same.
>
> Test finish-reverse-next.exp is updated to include tests for the
> reverse-finish command when the function is entered via the normal entry
> point (i.e. the LEP) and the alternate entry point (i.e. the GEP).
>
> The patch has been tested on X86 and PowerPC with no regressions.
> ---
>   gdb/infcmd.c                                  |  41 ++++---
>   gdb/infrun.c                                  |  21 +++-
>   .../gdb.reverse/finish-reverse-next.c         |  41 ++++++-
>   .../gdb.reverse/finish-reverse-next.exp       | 107 +++++++++++++++---
>   4 files changed, 175 insertions(+), 35 deletions(-)
>
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 9c42efeae8d..8c30af448ce 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1722,22 +1722,28 @@ finish_backward (struct finish_command_fsm *sm)
>     sal = find_pc_line (func_addr, 0);
>   
>     frame_info_ptr frame = get_selected_frame (nullptr);
> +  struct gdbarch *gdbarch = get_frame_arch (frame);
> +  CORE_ADDR alt_entry_point = sal.pc;
> +  CORE_ADDR entry_point = alt_entry_point;
>   
> -  if (sal.pc != pc)
> +  if (gdbarch_skip_entrypoint_p (gdbarch))
>       {
> -      struct gdbarch *gdbarch = get_frame_arch (frame);
> +      /* Some architectures, like PowerPC use local and global entry
> +	 points.  There is only one Entry Point (GEP = LEP) for other
> +	 architectures.  The GEP is an alternate entry point that is used
> +	 setup the table of contents (TOC) in register r2 before execution
> +	 continues at the LEP.  The LEP is the normal entry point.
I don't think an explanation on why there are 2 entry points is 
necessary.  just mentioning that both exist is enough IMHO.
> +	 The value of entry_point was initialized to the alternate entry
> +	 point (GEP).  It will be adjusted if the normal entry point
> +	 (LEP) was used.  */
> +       entry_point = gdbarch_skip_entrypoint (gdbarch, entry_point);
>   
> -      /* Set a step-resume at the function's entry point.  Once that's
> -	 hit, we'll do one more step backwards.  */
> -      symtab_and_line sr_sal;
> -      sr_sal.pc = sal.pc;
> -      sr_sal.pspace = get_frame_program_space (frame);
> -      insert_step_resume_breakpoint_at_sal (gdbarch,
> -					    sr_sal, null_frame_id);
>       }
> -  else
> +
> +  if (alt_entry_point <= pc && pc <= entry_point)
>       {
> -      /* We are exactly at the function entry point.  Note that this
> +      /* We are exactly at the function entry point, or between the entry
> +	 point on platforms that have two (like PowerPC).  Note that this
>   	 can only happen at frame #0.
>   
>   	 When setting a step range, need to call set_step_info
> @@ -1746,8 +1752,17 @@ finish_backward (struct finish_command_fsm *sm)
>   
>         /* Return using a step range so we will keep stepping back
>   	 to the first instruction in the source code line.  */
> -      tp->control.step_range_start = sal.pc;
> -      tp->control.step_range_end = sal.pc;
> +      tp->control.step_range_start = alt_entry_point;
> +      tp->control.step_range_end = alt_entry_point;
I'm hesitant in this part. What if there is one instruction between the 
GEP and the LEP and the inferior happens to be stopped there? Could this 
happen? Like I said, I'm not familiar with the PPC abi, so excuse me if 
the answer is obvious, but it seems to me that the step_range_end could 
be set to the entry_point and we'd avoid this possibility.
> +    }
> +  else
> +    {
> +      symtab_and_line sr_sal;
> +      /* Set a step-resume at the function's entry point.  */
> +      sr_sal.pc = entry_point;
> +      sr_sal.pspace = get_frame_program_space (frame);
> +      insert_step_resume_breakpoint_at_sal (gdbarch,
> +					    sr_sal, null_frame_id);
>       }
>     proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>   }
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 8ed538ea9ec..89423556ec0 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -1868,6 +1868,7 @@ struct execution_control_state
>   
>     struct target_waitstatus ws;
>     int stop_func_filled_in = 0;
> +  CORE_ADDR stop_func_alt_start = 0;
>     CORE_ADDR stop_func_start = 0;
>     CORE_ADDR stop_func_end = 0;
>     const char *stop_func_name = nullptr;
> @@ -4663,6 +4664,14 @@ fill_in_stop_func (struct gdbarch *gdbarch,
>   				    &block);
>         ecs->stop_func_name = gsi == nullptr ? nullptr : gsi->print_name ();
>   
> +      /* PowerPC functions have a Local Entry Point and a Global Entry
> +	 Point.  There is only one Entry Point (GEP = LEP) for other
> +	 architectures.  The GEP is an alternate entry point that is used
> +	 setup the table of contents (TOC) in register r2 before execution
> +	 continues at the LEP.  Save the alternate entry point address for
Ditto here about explaining LEP and GEP. Just saying that GEP is the 
alternate is probably enough.
> +	 use later.  */
> +      ecs->stop_func_alt_start = ecs->stop_func_start;
> +
>         /* The call to find_pc_partial_function, above, will set
>   	 stop_func_start and stop_func_end to the start and end
>   	 of the range containing the stop pc.  If this range
> @@ -4679,6 +4688,9 @@ fill_in_stop_func (struct gdbarch *gdbarch,
>   	    += gdbarch_deprecated_function_start_offset (gdbarch);
>   
>   	  if (gdbarch_skip_entrypoint_p (gdbarch))
> +	    /* The PowerPC architecture uses two entry points.  Stop at the
> +	       regular entry point (LEP on PowerPC) initially.  Will setup a
> +	       breakpoint for the alternate entry point (GEP) later.  */
>   	    ecs->stop_func_start
>   	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
>   	}
> @@ -6738,8 +6750,7 @@ process_event_stop_test (struct execution_control_state *ecs)
>         delete_step_resume_breakpoint (ecs->event_thread);
>         fill_in_stop_func (gdbarch, ecs);
>   
> -      if (execution_direction == EXEC_REVERSE
> -	  && ecs->event_thread->stop_pc () == ecs->stop_func_start)
> +      if (execution_direction == EXEC_REVERSE)
Why is this change not in the previous patch?
>   	{
>   	  struct thread_info *tp = ecs->event_thread;
>   	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
> @@ -6755,7 +6766,7 @@ process_event_stop_test (struct execution_control_state *ecs)
>   
>   	     Return using a step range so we will keep stepping back to the
>   	     first instruction in the source code line.  */
> -	  tp->control.step_range_start = ecs->stop_func_start;
> +	  tp->control.step_range_start = ecs->stop_func_alt_start;
>   	  tp->control.step_range_end = ecs->stop_func_start;
>   	  keep_going (ecs);
>   	  return;
> @@ -6892,8 +6903,10 @@ process_event_stop_test (struct execution_control_state *ecs)
>   	 (unless it's the function entry point, in which case
>   	 keep going back to the call point).  */
>         CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
> +
>         if (stop_pc == ecs->event_thread->control.step_range_start
> -	  && stop_pc != ecs->stop_func_start
> +	  && (stop_pc < ecs->stop_func_alt_start
> +	      || stop_pc > ecs->stop_func_start)
>   	  && execution_direction == EXEC_REVERSE)
>   	end_stepping_range (ecs);
>         else
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> index 42e41b5a2e0..55f81d2bc01 100644
> --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> @@ -1,4 +1,4 @@
> -/* This testcase is part of GDB, the GNU debugger.
> +j/* This testcase is part of GDB, the GNU debugger.
>   
>      Copyright 2012-2022 Free Software Foundation, Inc.
>   
> @@ -24,11 +24,37 @@
>      This test verifies the fix for gdb bugzilla:
>   
>      https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> -*/
> +
> +   PowerPC supports two entry points to a function.  The normal entry point
> +   is called the local entry point (LEP).  The alternat entry point is called
> +   the global entry point (GEP).  The GEP is only used if the table of
> +   contents (TOC) value stored in register r2 needs to be setup prior to
> +   execution starting at the LEP.  A function call via a function pointer
> +   will entry via the GEP.  A normal function call will enter via the LEP.
> +
> +   This test has been expanded to include tests to verify the reverse-finish
> +   command works properly if the function is called via the GEP.  The original
> +   test only verified the reverse-finish command for a normal call that used
> +   the LEP.  */
>   
>   int
>   function1 (int a, int b)   // FUNCTION1
>   {
> +  /* The assembly code for this function when compiled for PowerPC is as
> +     follows:
> +
> +     0000000010000758 <function1>:
> +     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
> +     1000075c:	00 7f 42 38 	addi    r2,r2,32512
> +     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
> +     10000764:	10 00 01 f8 	std     r0,16(r1)
> +     ....
> +
> +     When the function is called on PowerPC with function1 (a, b) the call
> +     enters at the Local Entry Point (LEP).  When the function is called via
> +     a function pointer, the Global Entry Point (GEP) for function1 is used.
> +     The GEP sets up register 2 before reaching the LEP.
> +  */
>     int ret = 0;
>   
>     ret = a + b;
> @@ -39,10 +65,19 @@ int
>   main(int argc, char* argv[])
>   {
>     int a, b;
> +  int (*funp) (int, int) = &function1;
> +
> +  /* Call function via Local Entry Point (LEP).  */
>   
>     a = 1;
>     b = 5;
>   
> -  function1 (a, b);   // CALL FUNCTION
> +  function1 (a, b);   // CALL VIA LEP
> +
> +  /* Call function via Global Entry Point (GEP).  */
> +  a = 10;
> +  b = 50;
> +
> +  funp (a, b);        // CALL VIA GEP
>     return 0;
>   }
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> index 7880de10ffc..fbc024b48b9 100644
> --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> @@ -31,6 +31,18 @@
>   # This test verifies the fix for gdb bugzilla:
>   #   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
>   
> +# PowerPC supports two entry points to a function.  The normal entry point
> +# is called the local entry point (LEP).  The alternat entry point is called
> +# the global entry point (GEP).  The GEP is only used if the table of
> +# contents (TOC) value stored in register r2 needs to be setup prior to
> +# execution starting at the LEP.  A function call via a function pointer
> +# will entry via the GEP.  A normal function call will enter via the LEP.
> +#
> +# This test has been expanded to include tests to verify the reverse-finish
> +# command works properly if the function is called via the GEP.  The original
> +# test only verified the reverse-finish command for a normal call that used
> +# the LEP.
> +
>   if ![supports_reverse] {
>       return
>   }
> @@ -50,32 +62,32 @@ if [supports_process_record] {
>   }
>   
>   
> -### TEST 1: reverse finish from the entry point instruction in
> -### function1.
> +### TEST 1: reverse finish from the entry point instruction (LEP) in
> +### function1 when called using the normal entry point (LEP).
>   
>   # Set breakpoint at call to function1 in main.
> -set FUNCTION_test  [gdb_get_line_number "CALL FUNCTION" $srcfile]
> -gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at .*" \
> -    "set breakpoint on function1 call to stepi into function"
> +set LEP_test  [gdb_get_line_number "CALL VIA LEP" $srcfile]
> +gdb_test "break $srcfile:$LEP_test" "Breakpoint $decimal at .*" \
> +    "set breakpoint on function1 LEP call to stepi into function"
>   
>   # Continue to break point at function1 call in main.
>   gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*" \
>       "stopped at function1 entry point instruction to stepi into function"
>   
>   # stepi until we see "{" indicating we entered function1
> -cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
> +cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call"
>   
>   delete_breakpoints
>   
> -gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
> -    "reverse-finish function1 "
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +    "reverse-finish function1 LEP call from LEP "
>   
>   # Check to make sure we stopped at the first instruction in the source code
>   # line.  It should only take one reverse next command to get to the previous
>   # source line.   If GDB stops at the last instruction in the source code line
>   # it will take two reverse next instructions to get to the previous source
>   # line.
> -gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
> +gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from LEP"
>   
>   # Clear the recorded log.
>   gdb_test "record stop"  "Process record is stopped.*" \
> @@ -83,26 +95,91 @@ gdb_test "record stop"  "Process record is stopped.*" \
>   gdb_test_no_output "record" "turn on process record for test2"
>   
>   
> -### TEST 2: reverse finish from the body of function1.
> +### TEST 2: reverse finish from the body of function1 when called using the
> +### normal entry point (LEP).
>   
>   # Set breakpoint at call to function1 in main.
> -gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at .*" \
> -    "set breakpoint on function1 call to step into body of function"
> +gdb_test "break $srcfile:$LEP_test" "Breakpoint $decimal at .*" \
> +    "set breakpoint on function1 LEP call to step into body of function"
>   
>   # Continue to break point at function1 call in main.
>   gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*" \
> -    "stopped at function1 entry point instruction to step to body of function"
> +    "stopped at function1 entry point instruction to step body of function"
>   
>   delete_breakpoints
>   
>   # do a step instruction to get to the body of the function
>   gdb_test "step" ".*int ret = 0;.*" "step test 1"
>   
> -gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
> -    "reverse-finish function1 call from function body"
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +    "reverse-finish function1 LEP call from function body"
>   
>   # Check to make sure we stopped at the first instruction in the source code
>   # line.  It should only take one reverse next command to get to the previous
>   # source line.
>   gdb_test "reverse-next" ".*b = 5;.*" \
>       "reverse next at b = 5, from function body"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test2"
> +gdb_test_no_output "record" "turn on process record for test3"
> +
> +
> +### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
> +### function1 when called using the alternate entry point (GEP).
> +
> +# Set breakpoint at call to funp in main.
> +set GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> +gdb_test "break $srcfile:$GEP_test" "Breakpoint $decimal at .*" \
> +    "set breakpoint on function1 GEP call to stepi into function"
> +
> +# Continue to break point at funp call in main.
> +gdb_test "continue" "Breakpoint $decimal.*funp \\(a, b\\).*" \
> +    "stopped at funp entry point instruction"
> +
> +# stepi until we see "{" indicating we entered function.
> +cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
> +
> +delete_breakpoints
> +
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "function1 GEP call call from GEP"
> +
> +# Check to make sure we stopped at the first instruction in the source code
> +# line.  It should only take one reverse next command to get to the previous
> +# source line.  If GDB stops at the last instruction in the source code line
> +# it will take two reverse next instructions to get to the previous source
> +# line.
> +gdb_test "reverse-next" ".*b = 50;.*" "reverse next at b = 50, call from GEP"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test3"
> +gdb_test_no_output "record" "turn on process record for test4"
> +
> +
> +### TEST 4: reverse finish from the body of function 1 when calling using the
> +### alternate entrypoint (GEP).
> +gdb_test "break $srcfile:$GEP_test" "Breakpoint $decimal at .*" \
> +    "set breakpoint on funp GEP call to step into body of function"
> +
> +# Continue to break point at funp call.
> +gdb_test "continue" "Breakpoint $decimal,.*funp \\(a, b\\).*" \
> +    "stopped at funp call"
> +
> +# Step into body of funp, called via GEP.
> +gdb_test "step" ".*int ret = 0;.*" "step test 2"
> +
> +delete_breakpoints
> +
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "reverse-finish function1 GEP call, from function body  "
> +
> +# Check to make sure we stopped at the first instruction in the source code
> +# line.  It should only take one reverse next command to get to the previous
> +# source line.  If GDB stops at the last instruction in the source code line
> +# it will take two reverse next instructions to get to the previous source
> +# line.
> +gdb_test "reverse-next" ".*b = 50;.*" \
> +    "reverse next at b = 50 from function body"


-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-13 13:33                                               ` Bruno Larsen
@ 2023-01-13 16:43                                                 ` Carl Love
  2023-01-13 17:04                                                   ` Bruno Larsen
  2023-01-14 18:08                                                 ` Carl Love
  1 sibling, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-13 16:43 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

Bruno:

On Fri, 2023-01-13 at 14:33 +0100, Bruno Larsen wrote:
> > +# This file is part of the GDB testsuite.  It tests reverse
> > stepping.
> > +# Lots of code borrowed from "step-test.exp".
> > +
> > +# The reverse finish command should return from a function and
> > stop on
> > +# the first instruction of the source line where the function call
> > is made.
> > +# Specifically, the behavior should match doing a reverse next
> > from the
> > +# first instruction in the function.  GDB should only take one
> > reverse step
> > +# or next statement to reach the previous source code line.
> > +
> > +# This testcase verifies the reverse-finish command stops at the
> > first
> > +# instruction in the source code line where the function was
> > called.  There
> > +# are two scenarios that must be checked:
> > +#   1) gdb is at the entry point instruction for the function
> > +#   2) gdb is in the body of the function.
> 
> While testing locally, I ran into a bug with reverse finish at the 
> epilogue of the function, that your patch also fixed. It would be
> nice 
> if the test extended that. And since the bug was that GDB stopped 
> responding and even ctrl+c did nothing, I would suggest adding it as
> the 
> last test.

I haven't run into the issue that mentioned about GDB not responding in
the epilogue.  I will have to go play with that to see if I can
reproduce it.  If you have any specific instructions on how you ran
into it that would be interesting and helpful.

I have read thru the other comments and will work on them and update
you on those fixes later.  Thanks for the feedback.

                        Carl


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-13 16:43                                                 ` Carl Love
@ 2023-01-13 17:04                                                   ` Bruno Larsen
  2023-01-13 19:10                                                     ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-01-13 17:04 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 13/01/2023 17:43, Carl Love wrote:
> Bruno:
>
> On Fri, 2023-01-13 at 14:33 +0100, Bruno Larsen wrote:
>>> +# This file is part of the GDB testsuite.  It tests reverse
>>> stepping.
>>> +# Lots of code borrowed from "step-test.exp".
>>> +
>>> +# The reverse finish command should return from a function and
>>> stop on
>>> +# the first instruction of the source line where the function call
>>> is made.
>>> +# Specifically, the behavior should match doing a reverse next
>>> from the
>>> +# first instruction in the function.  GDB should only take one
>>> reverse step
>>> +# or next statement to reach the previous source code line.
>>> +
>>> +# This testcase verifies the reverse-finish command stops at the
>>> first
>>> +# instruction in the source code line where the function was
>>> called.  There
>>> +# are two scenarios that must be checked:
>>> +#   1) gdb is at the entry point instruction for the function
>>> +#   2) gdb is in the body of the function.
>> While testing locally, I ran into a bug with reverse finish at the
>> epilogue of the function, that your patch also fixed. It would be
>> nice
>> if the test extended that. And since the bug was that GDB stopped
>> responding and even ctrl+c did nothing, I would suggest adding it as
>> the
>> last test.
> I haven't run into the issue that mentioned about GDB not responding in
> the epilogue.  I will have to go play with that to see if I can
> reproduce it.  If you have any specific instructions on how you ran
> into it that would be interesting and helpful.

I manually ran gdb.reverse/finish-precsave (setting recording, of 
course), set a temporary breakpoint on void_func, nexted once to be in 
the epilogue and tried to reverse finish. I'm not sure if it was some 
stale file before I recompiled the test, though.

Anyway, sorry if I was unclear, but that is not a regression of your 
patch. Rather, you patch fixed that issue, I just want that test to 
confirm that we don't accidentally regress it.

-- 
Cheers,
Bruno

>
> I have read thru the other comments and will work on them and update
> you on those fixes later.  Thanks for the feedback.
>
>                          Carl
>


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-13 17:04                                                   ` Bruno Larsen
@ 2023-01-13 19:10                                                     ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-13 19:10 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

Bruno:

On Fri, 2023-01-13 at 18:04 +0100, Bruno Larsen wrote:
> > I haven't run into the issue that mentioned about GDB not
> > responding in
> > the epilogue.  I will have to go play with that to see if I can
> > reproduce it.  If you have any specific instructions on how you ran
> > into it that would be interesting and helpful.
> 
> I manually ran gdb.reverse/finish-precsave (setting recording, of 
> course), set a temporary breakpoint on void_func, nexted once to be
> in 
> the epilogue and tried to reverse finish. I'm not sure if it was
> some 
> stale file before I recompiled the test, though.
> 
> Anyway, sorry if I was unclear, but that is not a regression of your 
> patch. Rather, you patch fixed that issue, I just want that test to 
> confirm that we don't accidentally regress it.

You were clear that you saw this as an existing issue before applying
my patches, i.e. not a regression due to my patch.  But rather my patch
fixed an existing issue.

I have been playing around on my X86 box trying to reproduce the issue.

I have an X86 box running Ubuntu 22.04.1 LTS, gcc version Ubuntu
11.3.0-1ubuntu1~22.04.

Here is the log of what I did trying to reproduce the issue as you
described:

Note, I started by running 

 make check RUNTESTFLAGS='GDB=/home/carll/bin/gdb gdb.reverse/finish-precsave.exp'

to generate the binary for the test.  I then cd'd to 

~/GDB/build-finish-precsave/gdb/testsuite/outputs/gdb.reverse/finish-precsave

where the binary was saved.  

Then I ran the test.  The following is the results with the path names
to the files shortened to improve readability.

gdb ./finish-precsave
GNU gdb (GDB) 14.0.50.20230111-git

<snip>

Reading symbols from ./finish-precsave...
(gdb) break main
Breakpoint 1 at 0x11d3: file .../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/finish-reverse.c, line 95.
(gdb) r
Starting program: .../gdb/testsuite/outputs/gdb.reverse/finish-precsave/finish-precsave 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main (argc=1, argv=0x7fffffffe798)
    at .../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/finish-reverse.c:95
95	  for (i = 0; i < sizeof (testval.ffff); i++)
(gdb) record
(gdb) tb void_func
Temporary breakpoint 2 at 0x555555555131: file .../binutils-gdb-finishrecsave/gdb/testsuite/gdb.reverse/finish-reverse.c, line 44.
(gdb) c
Continuing.

Temporary breakpoint 2, void_func ()
    at .../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/finish-reverse.c:44
44	  void_test = 1;		/* VOID FUNC */
(gdb) next
45	}
(gdb) reverse-finish
Run back to call of #0  void_func ()
    at .../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/finish-reverse.c:45
0x00005555555551fd in main (argc=1, argv=0x7fffffffe798)
    at ../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/finish-reverse.c:98
98	  void_func (); 				/* call to void_func */
(gdb) reverse-step
98	  void_func (); 				/* call to void_func */
(gdb) q

I have tried stopping in the other functions as well.  The reverse-
finish still seems to work fine.  I also tried setting layout-asm once
I reached the function and then did si to reach various instructions in
the epilog.  Didn't seem to matter which instruction in the function I
was at when I issued the reverse-finish instruction, I was not able to
get gdb to hang.  Unfortunately, I was not able to reproduce the issue
on X86.  I have also tried reproducing the error on PowerPC without 
success.

I created a new test case to do the above tests.  My thought is if we
can get this new test case to reliably fail on your system without my
proposed patches, then we can add it to the new test case in the patch.
The test case passes on my X86 machine.  Of course it fails on my PPC
machine due to the existing reverse finish issues. What do you think?

                            Carl
-------------------------------------------
reverse-finish hang test

---
 .../gdb.reverse/gdb-reverse-finish-hang.exp   | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 gdb/testsuite/gdb.reverse/gdb-reverse-finish-hang.exp

diff --git a/gdb/testsuite/gdb.reverse/gdb-reverse-finish-hang.exp b/gdb/testsuite/gdb.reverse/gdb-reverse-finish-hang.exp
new file mode 100644
index 00000000000..14a3991c9b9
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/gdb-reverse-finish-hang.exp
@@ -0,0 +1,54 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests 'finish' with
+# reverse debugging.
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile finish-reverse.c
+set precsave [standard_output_file finish.precsave]
+
+if { [prepare_for_testing "failed to prepare" "$testfile" $srcfile] } {
+    return -1
+}
+
+runto_main
+
+if [supports_process_record] {
+    # Activate process record/replay
+    gdb_test_no_output "record" "turn on process record"
+}
+
+# Test reverse finish from void func to see if gdb hangs.
+set breakloc [gdb_get_line_number "VOID FUNC" "$srcfile"]
+gdb_test "tbreak void_func" \
+    "Temporary breakpoint $decimal at .*$srcfile, line $breakloc\." \
+    "set breakpoint on void_func"
+gdb_continue_to_breakpoint "void_func" ".*$srcfile:$breakloc.*"
+
+# Step into epilogue of void_func.
+gdb_test "step" ".*}.*" "step to epilog"
+
+# Test to see if gdb hangs when doing a reverse-finish from the epilogue.
+gdb_test "reverse-finish" "$decimal.*void_func.*" \
+    "return to caller of void_func ()" 
+
+# Do reverse-next, should stay on void_func function due to existing bug
+# in reverse-finish.
+gdb_test "reverse-next" "$decimal.*void_func.*" \
+    "reverse next in main"
-- 
2.34.1




^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-13 13:33                                               ` Bruno Larsen
  2023-01-13 16:43                                                 ` Carl Love
@ 2023-01-14 18:08                                                 ` Carl Love
  2023-01-16 12:31                                                   ` Bruno Larsen
  1 sibling, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-14 18:08 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

On Fri, 2023-01-13 at 14:33 +0100, Bruno Larsen wrote:
> On 11/01/2023 19:27, Carl Love via Gdb-patches wrote:
> > GDB maintainers:
> > 
> > This patch fixes the issues with the reverse-finish command on X86.
> > The reverse-finish command now correctly stops at the first
> > instruction
> > in the source code line of the caller.  It now only requires a
> > single
> > reverse-step or reverse-next instruction to get back to the
> > previous
> > source code line.
> > 
> > It also adds a new testcase, gdb.reverse/finish-reverse-next.exp,
> > and
> > updates several existing testcases.
> > 
> > Please let me know if you have any comments on the patch.  Thanks.
> Thanks for looking at this, this is a nice change. I just have a
> couple 
> of comments, mostly related to the testsuite side.
> >                      Carl
> > 
> > --------------------------------------------------------------
> > X86: reverse-finish fix
> > 
> > Currently on X86, when executing the finish command in reverse, gdb
> > does a
> > single step from the first instruction in the callee to get back to
> > the
> > caller.  GDB stops on the last instruction in the source code line
> > where
> > the call was made.  When stopped at the last instruction of the
> > source code
> > line, a reverse next or step command will stop at the first
> > instruction
> > of the same source code line thus requiring two step/next commands
> > to
> > reach the previous source code line.  It should only require one
> > step/next
> > command to reach the previous source code line.
> > 
> > By contrast, a reverse next or step command from the first line in
> > a
> > function stops at the first instruction in the source code line
> > where the
> > call was made.
> > 
> > This patch fixes the reverse finish command so it will stop at the
> > first
> > instruction of the source line where the function call was
> > made.  The
> > behavior on X86 for the reverse-finish command now matches doing a
> > reverse-next from the beginning of the function.
> > 
> > The proceed_to_finish flag in struct thread_control_state is no
> > longer
> > used.  This patch removes the declaration, initialization and
> > setting of
> > the flag.
> > 
> > This patch requires a number of regression tests to be
> > updated.  Test
> > gdb.mi/mi-reverse.exp no longer needs to execute two steps to get
> > to the
> > previous line.  The gdb output for tests gdb.reverse/until-
> > precsave.exp
> > and gdb.reverse/until-reverse.exp changed slightly.  The expected
> > result in
> > tests gdb.reverse/amd64-ailcall-reverse.exp and
> s/ailcall/tailcall

Fixed

> > gdb.reverse/singlejmp-reverse.exp are updated to the correct
> > expected
> > result.
> > 
> > This patch adds a new test gdb.reverse/finish-reverse-next.exp to
> > test the
> > reverse-finish command when returning from the entry point and from
> > the
> > body of the function.
> > 
> > The step_until proceedure in test gdb.reverse/step-indirect-call-
> > thunk.exp
> > was moved to lib/gdb.exp and renamed cmd_until.
> I'm not a big fan of the name cmd_until, because it sounded to me
> like 
> you were testing the GDB command until. I think repeat_cmd_until or 
> repeat_until would avoid this possible confusion.

Changed cmd_until to repeat_cmd_until.

> > The patch has been tested on X86 and PowerPC to verify no
> > additional
> > regression failures occured.
> > 
> > Bug: 
> > https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> >  
> If you add record/29927 somewhere along the text of your commit
> message, 
> there is some automation that will comment on the bugzilla bug 
> specifying this commit. Might be worth doing for future reference.

Added.  I realized I had forgotten to do that after I sent the email.  
I added it to both patches.

> > ---
> >   gdb/gdbthread.h                               |   4 -
> >   gdb/infcall.c                                 |   3 -
> >   gdb/infcmd.c                                  |  32 +++---
> >   gdb/infrun.c                                  |  41 +++----
> >   gdb/testsuite/gdb.mi/mi-reverse.exp           |   9 +-
> >   .../gdb.reverse/amd64-tailcall-reverse.exp    |   5 +-
> >   .../gdb.reverse/finish-reverse-next.c         |  48 ++++++++
> >   .../gdb.reverse/finish-reverse-next.exp       | 108
> > ++++++++++++++++++
> >   gdb/testsuite/gdb.reverse/finish-reverse.exp  |   5 +
> >   .../gdb.reverse/singlejmp-reverse.exp         |   5 +-
> >   .../gdb.reverse/step-indirect-call-thunk.exp  |  49 ++------
> >   gdb/testsuite/gdb.reverse/until-precsave.exp  |   2 +-
> >   gdb/testsuite/gdb.reverse/until-reverse.exp   |   2 +-
> >   gdb/testsuite/lib/gdb.exp                     |  33 ++++++
> >   14 files changed, 240 insertions(+), 106 deletions(-)
> >   create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-
> > next.c
> >   create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-
> > next.exp
> > 
> > diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
> > index 11d69fceab0..e4edff2d621 100644
> > --- a/gdb/gdbthread.h
> > +++ b/gdb/gdbthread.h
> > @@ -150,10 +150,6 @@ struct thread_control_state
> >        the finished single step.  */
> >     int trap_expected = 0;
> >   
> > -  /* Nonzero if the thread is being proceeded for a "finish"
> > command
> > -     or a similar situation when return value should be
> > printed.  */
> > -  int proceed_to_finish = 0;
> > -
> >     /* Nonzero if the thread is being proceeded for an inferior
> > function
> >        call.  */
> >     int in_infcall = 0;
> > diff --git a/gdb/infcall.c b/gdb/infcall.c
> > index e09904f9a35..116605c43ef 100644
> > --- a/gdb/infcall.c
> > +++ b/gdb/infcall.c
> > @@ -625,9 +625,6 @@ run_inferior_call
> > (std::unique_ptr<call_thread_fsm> sm,
> >   
> >     disable_watchpoints_before_interactive_call_start ();
> >   
> > -  /* We want to print return value, please...  */
> > -  call_thread->control.proceed_to_finish = 1;
> > -
> >     try
> >       {
> >         /* Infcalls run synchronously, in the foreground.  */
> > diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> > index 0497ad05091..9c42efeae8d 100644
> > --- a/gdb/infcmd.c
> > +++ b/gdb/infcmd.c
> > @@ -1721,19 +1721,10 @@ finish_backward (struct finish_command_fsm
> > *sm)
> >   
> >     sal = find_pc_line (func_addr, 0);
> >   
> > -  tp->control.proceed_to_finish = 1;
> > -  /* Special case: if we're sitting at the function entry point,
> > -     then all we need to do is take a reverse singlestep.  We
> > -     don't need to set a breakpoint, and indeed it would do us
> > -     no good to do so.
> > -
> > -     Note that this can only happen at frame #0, since there's
> > -     no way that a function up the stack can have a return address
> > -     that's equal to its entry point.  */
> > +  frame_info_ptr frame = get_selected_frame (nullptr);
> >   
> >     if (sal.pc != pc)
> >       {
> > -      frame_info_ptr frame = get_selected_frame (nullptr);
> >         struct gdbarch *gdbarch = get_frame_arch (frame);
> >   
> >         /* Set a step-resume at the function's entry point.  Once
> > that's
> > @@ -1743,16 +1734,22 @@ finish_backward (struct finish_command_fsm
> > *sm)
> >         sr_sal.pspace = get_frame_program_space (frame);
> >         insert_step_resume_breakpoint_at_sal (gdbarch,
> >   					    sr_sal, null_frame_id);
> > -
> > -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> >       }
> >     else
> >       {
> > -      /* We're almost there -- we just need to back up by one more
> > -	 single-step.  */
> > -      tp->control.step_range_start = tp->control.step_range_end =
> > 1;
> > -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> > +      /* We are exactly at the function entry point.  Note that
> > this
> > +	 can only happen at frame #0.
> > +
> > +	 When setting a step range, need to call set_step_info
> > +	 to setup the current_line/symtab fields as well.  */
> > +      set_step_info (tp, frame, find_pc_line (pc, 0));
> > +
> > +      /* Return using a step range so we will keep stepping back
> > +	 to the first instruction in the source code line.  */
> > +      tp->control.step_range_start = sal.pc;
> > +      tp->control.step_range_end = sal.pc;
> >       }
> > +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> >   }
> >   
> >   /* finish_forward -- helper function for finish_command.  FRAME
> > is the
> > @@ -1778,9 +1775,6 @@ finish_forward (struct finish_command_fsm
> > *sm, frame_info_ptr frame)
> >   
> >     set_longjmp_breakpoint (tp, frame_id);
> >   
> > -  /* We want to print return value, please...  */
> > -  tp->control.proceed_to_finish = 1;
> > -
> >     proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> >   }
> >   
> > diff --git a/gdb/infrun.c b/gdb/infrun.c
> > index 181d961d80d..8ed538ea9ec 100644
> > --- a/gdb/infrun.c
> > +++ b/gdb/infrun.c
> > @@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct
> > thread_info *tp)
> >   
> >     tp->control.stop_step = 0;
> >   
> > -  tp->control.proceed_to_finish = 0;
> > -
> >     tp->control.stepping_command = 0;
> >   
> >     /* Discard any remaining commands or status from previous
> > stop.  */
> > @@ -6737,31 +6735,28 @@ process_event_stop_test (struct
> > execution_control_state *ecs)
> >   
> >       case BPSTAT_WHAT_STEP_RESUME:
> >         infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
> > -
> >         delete_step_resume_breakpoint (ecs->event_thread);
> > -      if (ecs->event_thread->control.proceed_to_finish
> > -	  && execution_direction == EXEC_REVERSE)
> > +      fill_in_stop_func (gdbarch, ecs);
> > +
> > +      if (execution_direction == EXEC_REVERSE
> > +	  && ecs->event_thread->stop_pc () == ecs->stop_func_start)
> Is there any reason to invert the order of checks here? The second
> if 
> clause is the same and keeping that would make the changes easier to
> parse.

No, must have inadvertently swizzled it as part of the patch
development.  Per comments for the second patch, PowerPC, the  "cs-
>event_thread->stop_pc () == ecs->stop_func_start" check should be
removed in this patch not the PowerPC patch.  Probably got missed when
I switched the order of the patches.

 Fixed, removed the "ecs->event_thread->stop_pc () == ecs-
>stop_func_start" test here.

> >   	{
> >   	  struct thread_info *tp = ecs->event_thread;
> > +	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (),
> > 0);
> >   
> > -	  /* We are finishing a function in reverse, and just hit the
> > -	     step-resume breakpoint at the start address of the
> > -	     function, and we're almost there -- just need to back up
> > -	     by one more single-step, which should take us back to the
> > -	     function call.  */
> > -	  tp->control.step_range_start = tp->control.step_range_end =
> > 1;
> > -	  keep_going (ecs);
> > -	  return;
> > -	}
> > -      fill_in_stop_func (gdbarch, ecs);
> > -      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
> > -	  && execution_direction == EXEC_REVERSE)
> > -	{
> > -	  /* We are stepping over a function call in reverse, and just
> > -	     hit the step-resume breakpoint at the start address of
> > -	     the function.  Go back to single-stepping, which should
> > -	     take us back to the function call.  */
> > -	  ecs->event_thread->stepping_over_breakpoint = 1;

The following comment was from the second email.

 >      case BPSTAT_WHAT_STEP_RESUME:> Something else that I failed to
notice. Since you removed both
> comments 
> that mention that this case is here for reverse finishing, there is
> no 
> good way to figure out what GDB wants to do when this part of the
> code 
> is reached. Adding a comment here mentioning it would fix that.
> >          infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");

There were two separate if statements, each with a comment about what
they were for.  Those comments were removed and a new, similar, comment
was added in the single new if statement.  Admittedly, the new comment
is a bit farther into the function and thus easy to miss.  So, I moved
the initial comment about what is going on "We are finishing a function
in reverse or..." up to the beginning of the if statement.  Hopefully
that helps make it quicker/easier for the reader to see what the
purpose of the case statement/if statement.  Please let me know if that
helps address your concerns. 

> > +	  /* When setting a step range, need to call set_step_info
> > +	     to setup the current_line/symtab fields as well.  */
> > +	  set_step_info (tp, frame, stop_pc_sal);
> > +
> > +	  /* We are finishing a function in reverse or stepping over a
> > function
> > +	     call in reverse, and just hit the step-resume breakpoint
> > at the
> > +	     start address of the function, and we're almost there --
> > just need
> > +	     to back up to the function call.
> > +
> > +	     Return using a step range so we will keep stepping back to
> > the
> > +	     first instruction in the source code line.  */
> > +	  tp->control.step_range_start = ecs->stop_func_start;
> > +	  tp->control.step_range_end = ecs->stop_func_start;
> >   	  keep_going (ecs);
> >   	  return;
> >   	}
> > diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp
> > b/gdb/testsuite/gdb.mi/mi-reverse.exp
> > index d631beb17c8..30635ab1754 100644
> > --- a/gdb/testsuite/gdb.mi/mi-reverse.exp
> > +++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
> > @@ -97,15 +97,10 @@ proc test_controlled_execution_reverse {} {
> >   	"basics.c" $line_main_callme_1 "" \
> >   	"reverse finish from callme"
> >   
> > -    # Test exec-reverse-next
> > -    #   It takes two steps to get back to the previous line,
> > -    #   as the first step moves us to the start of the current
> > line,
> > -    #   and the one after that moves back to the previous line.
> > -
> > -    mi_execute_to "exec-next --reverse 2" \
> > +    mi_execute_to "exec-next --reverse" \
> >    	"end-stepping-range" "main" "" \
> >    	"basics.c" $line_main_hello "" \
> > - 	"reverse next to get over the call to do_nothing"
> > +	"reverse next to get over the call to do_nothing"
> >   
> >       # Test exec-reverse-step
> >   
> > diff --git a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> > b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> > index 52a87faabf7..9964b4f8e4b 100644
> > --- a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> > +++ b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> > @@ -44,6 +44,5 @@ if [supports_process_record] {
> >   gdb_test "next" {f \(\);} "next to f"
> >   gdb_test "next" {v = 3;} "next to v = 3"
> >   
> > -# FAIL was:
> > -# 29        g ();
> > -gdb_test "reverse-next" {f \(\);}
> > +# Reverse step back into f ().  Puts us at call to g () in
> > function f ().
> > +gdb_test "reverse-next" {g \(\);}
> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > new file mode 100644
> > index 00000000000..42e41b5a2e0
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > @@ -0,0 +1,48 @@
> > +/* This testcase is part of GDB, the GNU debugger.
> > +
> > +   Copyright 2012-2022 Free Software Foundation, Inc.
> copyright year should be 2023.
> > +
> > +   This program is free software; you can redistribute it and/or
> > modify
> > +   it under the terms of the GNU General Public License as
> > published by
> > +   the Free Software Foundation; either version 3 of the License,
> > or
> > +   (at your option) any later version.
> > +
> > +   This program is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +   GNU General Public License for more details.
> > +
> > +   You should have received a copy of the GNU General Public
> > License
> > +   along with this program.  If not, see <
> > http://www.gnu.org/licenses/
> >  >.  */
> > +
> > +/* The reverse finish command should return from a function and
> > stop on
> > +   the first instruction of the source line where the function
> > call is made.
> > +   Specifically, the behavior should match doing a reverse next
> > from the
> > +   first instruction in the function.  GDB should only require one
> > reverse
> > +   step or next statement to reach the previous source code line.
> > +
> > +   This test verifies the fix for gdb bugzilla:
> > +
> > +   
> > https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> >  
> > +*/
> > +
> > +int
> > +function1 (int a, int b)   // FUNCTION1
> > +{
> > +  int ret = 0;
> > +
> > +  ret = a + b;
> > +  return ret;
> > +}
> > +
> > +int
> > +main(int argc, char* argv[])
> > +{
> > +  int a, b;
> > +
> > +  a = 1;
> > +  b = 5;
> > +
> > +  function1 (a, b);   // CALL FUNCTION
> > +  return 0;
> > +}
> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > new file mode 100644
> > index 00000000000..7880de10ffc
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > @@ -0,0 +1,108 @@
> > +# Copyright 2008-2022 Free Software Foundation, Inc.

Fixed copyright so it reads 2008-2023.  Fixed in finish-reverse-
next.exp and finish-reverse-next.c.

> > +
> > +# This program is free software; you can redistribute it and/or
> > modify
> > +# it under the terms of the GNU General Public License as
> > published by
> > +# the Free Software Foundation; either version 3 of the License,
> > or
> > +# (at your option) any later version.
> > +#
> > +# This program is distributed in the hope that it will be useful,
> > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +# GNU General Public License for more details.
> > +#
> > +# You should have received a copy of the GNU General Public
> > License
> > +# along with this program.  If not, see <
> > http://www.gnu.org/licenses/
> >  >.  */
> > +
> > +# This file is part of the GDB testsuite.  It tests reverse
> > stepping.
> > +# Lots of code borrowed from "step-test.exp".
> > +
> > +# The reverse finish command should return from a function and
> > stop on
> > +# the first instruction of the source line where the function call
> > is made.
> > +# Specifically, the behavior should match doing a reverse next
> > from the
> > +# first instruction in the function.  GDB should only take one
> > reverse step
> > +# or next statement to reach the previous source code line.
> > +
> > +# This testcase verifies the reverse-finish command stops at the
> > first
> > +# instruction in the source code line where the function was
> > called.  There
> > +# are two scenarios that must be checked:
> > +#   1) gdb is at the entry point instruction for the function
> > +#   2) gdb is in the body of the function.
> 
> While testing locally, I ran into a bug with reverse finish at the 
> epilogue of the function, that your patch also fixed. It would be
> nice 
> if the test extended that. And since the bug was that GDB stopped 
> responding and even ctrl+c did nothing, I would suggest adding it as
> the 
> last test.

Discussed this additional bug in earlier emails.  Waiting to hear if
the new test I sent reliably exposes the gdb hang that Bruno reported. 
If it does, I will add the new test to the new test case before posting
the updated patch set. Per the discussions, I have not been able to
reproduce the issue on my X86 or PowerPC machines.

> 
> > +
> > +# This test verifies the fix for gdb bugzilla:
> > +#   
> > https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> >  
> > +
> > +if ![supports_reverse] {
> > +    return
> > +}
> > +
> > +standard_testfile
> > +
> > +if { [prepare_for_testing "failed to prepare" $testfile $srcfile]
> > } {
> > +    return -1
> > +}
> > +
> > +runto_main
> > +set target_remote [gdb_is_target_remote]
> > +
> > +if [supports_process_record] {
> > +    # Activate process record/replay.
> > +    gdb_test_no_output "record" "turn on process record for test1"
> > +}
> > +
> > +
> > +### TEST 1: reverse finish from the entry point instruction in
> > +### function1.
> > +
> > +# Set breakpoint at call to function1 in main.
> > +set FUNCTION_test  [gdb_get_line_number "CALL FUNCTION" $srcfile]
> > +gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at
> > .*" \his
> > +    "set breakpoint on function1 call to stepi into function"
> 
> There is a proc in lib/gdb.exp called gdb_breakpoint which
> couldsimplify 
> this gdb_test to
> 
> gdb_breakpoint $srcfile:$FUNCTION_test temporary
> 
> And would remove the need for the delete_breakpoints call later.
> 

OK, made the change in both tests.  Made the same change in the PowerPC
patch that adds additional tests.


> > +
> > +# Continue to break point at function1 call in main.
> > +gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*"
> > \
> > +    "stopped at function1 entry point instruction to stepi into
> > function"
> You can use gdb_continue_to_breakpoint here instead.

OK, made the change in both tests.  Made the same change in the PowerPC
patch that adds additional tests.

> > +
> > +# stepi until we see "{" indicating we entered function1
> > +cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
> > +
> > +delete_breakpoints
> > +
> > +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL
> > FUNCTION.*" \
> > +    "reverse-finish function1 "
> > +
> > +# Check to make sure we stopped at the first instruction in the
> > source code
> > +# line.  It should only take one reverse next command to get to
> > the previous
> > +# source line.   If GDB stops at the last instruction in the
> > source code line
> > +# it will take two reverse next instructions to get to the
> > previous source
> > +# line.
> > +gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call
> > from function"
> > +
> > +# Clear the recorded log.
> > +gdb_test "record stop"  "Process record is stopped.*" \
> > +    "turn off process record for test1"
> > +gdb_test_no_output "record" "turn on process record for test2"
> > +
> > +
> > +### TEST 2: reverse finish from the body of function1.
> > +
> > +# Set breakpoint at call to function1 in main.
> > +gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at
> > .*" \
> > +    "set breakpoint on function1 call to step into body of
> > function"
> > +
> > +# Continue to break point at function1 call in main.
> > +gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*"
> > \
> > +    "stopped at function1 entry point instruction to step to body
> > of function"
> > +
> > +delete_breakpoints
> > +
> > +# do a step instruction to get to the body of the function
> > +gdb_test "step" ".*int ret = 0;.*" "step test 1"
> > +
> > +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL
> > FUNCTION.*" \
> > +    "reverse-finish function1 call from function body"
> > +
> > +# Check to make sure we stopped at the first instruction in the
> > source code
> > +# line.  It should only take one reverse next command to get to
> > the previous
> > +# source line.
> > +gdb_test "reverse-next" ".*b = 5;.*" \
> > +    "reverse next at b = 5, from function body"
> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse.exp
> > b/gdb/testsuite/gdb.reverse/finish-reverse.exp
> > index 01ba309420c..a05cb81892a 100644
> > --- a/gdb/testsuite/gdb.reverse/finish-reverse.exp
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse.exp
> > @@ -16,6 +16,11 @@
> >   # This file is part of the GDB testsuite.  It tests 'finish' with
> >   # reverse debugging.
> >   
> > +# This test verifies the fix for gdb bugzilla:
> > +
> > +# 
> > https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> >  
> > +
> > +
> 
> Is this comment a left over from an earlier version?
> 
> I actually wonder if the whole new test is needed, or if you can
> just 
> add a couple of new tests to finish-reverse.exp; is there any reason
> you 
> went with the new test instead

Yes, it is left over.  Initially I just added an additional test to
finish-reverse.exp for the PowerPC fix.  But as work progressed, I kept
adding more tests for PowerPC then for X86.  I felt that it was better
to have a new test file that was tied to the Bugzilla.  The existing
test file has a different focus from the new tests.  The bugzilla
change didn't get removed from finish-reverse.exp when the tests were
moved to the new file.  We can combine the tests again if that is
preferable?   My preference would be to have separate test files. 
Please let me know if you would prefer a single file and I will merge
them before re-posting the patches. 

> 
> >   if ![supports_reverse] {
> >       return
> >   }
> > diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> > b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> > index 1ca7c2ce559..eb03051625a 100644
> > --- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> > +++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> > @@ -56,7 +56,4 @@ gdb_test "next" {v = 3;} "next to v = 3"
> >   # {
> >   gdb_test "reverse-step" {nodebug \(\);}
> >   
> > -# FAIL was:
> > -# No more reverse-execution history.
> > -# {
> > -gdb_test "reverse-next" {f \(\);}
> > +gdb_test "reverse-next" {g \(\);}
> > diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp 
> > b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> > index ad637899e5b..1928cdda217 100644
> > --- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> > +++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> > @@ -39,39 +39,6 @@ if { ![runto_main] } {
> >       return -1
> >   }
> >   
> > -# Do repeated stepping COMMANDs in order to reach TARGET from
> > CURRENT
> > -#
> > -#  COMMAND is a stepping command
> > -#  CURRENT is a string matching the current location
> > -#  TARGET  is a string matching the target location
> > -#  TEST    is the test name
> > -#
> > -# The function issues repeated COMMANDs as long as the location
> > matches
> > -# CURRENT up to a maximum of 100 steps.
> > -#
> > -# TEST passes if the resulting location matches TARGET and fails
> > -# otherwise.
> > -#
> > -proc step_until { command current target test } {
> > -    global gdb_prompt
> > -
> > -    set count 0
> > -    gdb_test_multiple "$command" "$test" {
> > -        -re "$current.*$gdb_prompt $" {
> > -            incr count
> > -            if { $count < 100 } {
> > -                send_gdb "$command\n"
> > -                exp_continue
> > -            } else {
> > -                fail "$test"
> > -            }
> > -        }
> > -        -re "$target.*$gdb_prompt $" {
> > -            pass "$test"
> > -        }
> > -    }
> > -}
> > -
> >   gdb_test_no_output "record"
> >   gdb_test "next" ".*" "record trace"
> >   
> > @@ -91,20 +58,20 @@ gdb_test "reverse-next" "apply\.2.*" \
> >       "reverse-step through thunks and over inc"
> >   
> >   # We can use instruction stepping to step into thunks.
> > -step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call
> > thunk"
> > -step_until "stepi" "indirect_thunk" "inc" \
> > +cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call
> > thunk"
> > +cmd_until "stepi" "indirect_thunk" "inc" \
> >       "stepi out of call thunk into inc"
> >   set alphanum_re "\[a-zA-Z0-9\]"
> >   set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re*
> > \\(\\)"
> > -step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi
> > into return thunk"
> > -step_until "stepi" "return_thunk" "apply" \
> > +cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into
> > return thunk"
> > +cmd_until "stepi" "return_thunk" "apply" \
> >       "stepi out of return thunk back into apply"
> >   
> > -step_until "reverse-stepi" "apply" "return_thunk" \
> > +cmd_until "reverse-stepi" "apply" "return_thunk" \
> >       "reverse-stepi into return thunk"
> > -step_until "reverse-stepi" "return_thunk" "inc" \
> > +cmd_until "reverse-stepi" "return_thunk" "inc" \
> >       "reverse-stepi out of return thunk into inc"
> > -step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk"
> > \
> > +cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
> >       "reverse-stepi into call thunk"
> > -step_until "reverse-stepi" "indirect_thunk" "apply" \
> > +cmd_until "reverse-stepi" "indirect_thunk" "apply" \
> >       "reverse-stepi out of call thunk into apply"
> > diff --git a/gdb/testsuite/gdb.reverse/until-precsave.exp
> > b/gdb/testsuite/gdb.reverse/until-precsave.exp
> > index 0c2d7537cd6..777aec94ac1 100644
> > --- a/gdb/testsuite/gdb.reverse/until-precsave.exp
> > +++ b/gdb/testsuite/gdb.reverse/until-precsave.exp
> > @@ -142,7 +142,7 @@ gdb_test "advance marker2" \
> >   # Finish out to main scope (backward)
> >   
> >   gdb_test "finish" \
> > -    " in main .*$srcfile:$bp_location20.*" \
> > +    "main .*$srcfile:$bp_location20.*" \
> This change doesn't seem connected to anything in this patch, is
> this 
> just a cosmetic change or was there some problem?
> >       "reverse-finish from marker2"
> >   

The output changes due to the functional changes in infrun.c.  Instead
of stepping back one instruction i.e. ecs->event_thread-
>stepping_over_breakpoint = 1 we step back using a range.  Apparently
this causes the gdb output message to change. 

Without the patch the output looks like:
  Run back to call of #0  marker2 (a=43) at.../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/ur1.c:30

  0x0000000010000838 in main (argc=1, argv=0x7fffffffcc58, envp=0x7fffffffcc68) at /.../gdb/testsuite/gdb.reverse/until-reverse.c:48^

With the patch the output looks like:

  Run back to call of #0  marker2 (a=43) at .../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/ur1.c:30

  main (argc=1, argv=0x7fffffffcc58, envp=0x7fffffffcc68) at .../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/until-reverse.c:48

Basically, you lose the hex value and "in" with the patch applied. 
This is true in the until-reverse.exp tes, below, as well.  The output
change was mentioned in the commit message as well.


> >   # Advance backward to last line of factorial (outer invocation)
> > diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp
> > b/gdb/testsuite/gdb.reverse/until-reverse.exp
> > index 23fc881dbf2..3a05953329f 100644
> > --- a/gdb/testsuite/gdb.reverse/until-reverse.exp
> > +++ b/gdb/testsuite/gdb.reverse/until-reverse.exp
> > @@ -113,7 +113,7 @@ gdb_test "advance marker2" \
> >   # Finish out to main scope (backward)
> >   
> >   gdb_test "finish" \
> > -    " in main .*$srcfile:$bp_location20.*" \
> > +    "main .*$srcfile:$bp_location20.*" \
> same here.

Yup, see above.

> >       "reverse-finish from marker2"
> >   
> >   # Advance backward to last line of factorial (outer invocation)
> > diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> > index c41d4698d66..25f42eb5510 100644
> > --- a/gdb/testsuite/lib/gdb.exp
> > +++ b/gdb/testsuite/lib/gdb.exp
> > @@ -9301,6 +9301,39 @@ proc gdb_step_until { regexp {test_name ""}
> > {max_steps 10} } {
> >       }
> >   }
> >   
> > +# Do repeated stepping COMMANDs in order to reach TARGET from
> > CURRENT
> > +#
> > +#  COMMAND is a stepping command
> > +#  CURRENT is a string matching the current location
> > +#  TARGET  is a string matching the target location
> > +#  TEST    is the test name
> > +#
> > +# The function issues repeated COMMANDs as long as the location
> > matches
> > +# CURRENT up to a maximum of 100 steps.
> > +#
> > +# TEST passes if the resulting location matches TARGET and fails
> > +# otherwise.
> > +
> > +proc cmd_until { command current target test } {
> > +    global gdb_prompt
> > +
> > +    set count 0
> > +    gdb_test_multiple "$command" "$test" {
> > +	-re "$current.*$gdb_prompt $" {
> > +	    incr count
> > +	    if { $count < 100 } {
> > +		send_gdb "$command\n"
> > +		exp_continue
> > +	    } else {
> > +		fail "$test"
> > +	    }
> > +	}
> > +	-re "$target.*$gdb_prompt $" {
> > +	    pass "$test"
> > +	}
> > +    }
> > +}
> > +
> >   # Check if the compiler emits epilogue information associated
> >   # with the closing brace or with the last statement line.
> >   #
> 
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-13 15:55                                               ` Bruno Larsen
@ 2023-01-14 18:08                                                 ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-14 18:08 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

On Fri, 2023-01-13 at 16:55 +0100, Bruno Larsen wrote:
> On 11/01/2023 19:27, Carl Love via Gdb-patches wrote:
> > GDB maintainers:
> > 
> > This patch fixes the issues with the reverse-finish command on
> > PowerPC.  The reverse-finish command now correctly stops at the
> > first
> > instruction in the source code line of the caller.
> > 
> > The patch adds tests for calling a function via the GEP to the new
> > test
> > gdb.reverse/finish-reverse-next.exp.
> > 
> > Please let me know if you have any comments on the patch.  Thanks.
> I'm not all that familiar with PowerPC ABI and I dont have a
> computer 
> handy to test that the patch fixes the problem, but the logic seems 
> sound. Just a few nits inlined.
> >                      Carl
> > 
> > --------------------------------------------------------------
> > PowerPC: fix for gdb.reverse/finish-precsave.exp and
> > gdb.reverse/finish-reverse.exp
> > 
> > PowerPC uses two entry points called the local entry point (LEP)
> > and the
> > global entry point (GEP).  Normally the LEP is used when calling a
> > function.  However, if the table of contents (TOC) value in
> > register 3 is not valid the GEP is called to setup the TOC before
> > execution
> > continues at the LEP.  When executing in reverse, the function
> > finish_backward sets the break point at the alternate entry point
> > (GEP).
> > However if the forward execution enters via the normal entry point
> > (LEP),
> > the reverse execution never sees the break point at the GEP of the
> > function.  Reverse execution continues until the next break point
> > is
> > encountered or the end of the recorded log is reached causing gdb
> > to stop
> > at the wrong place.
> > 
> > This patch adds a new address to struct execution_control_state to
> > hold the
> > address of the alternate function start address, known as the GEP
> > on
> > PowerPC.  The finish_backwards function is updated.  If the
> > stopping point
> > is between the two entry points (the LEP and GEP on PowerPC) , the
> > stepping
> > range is set to execute back to the alternate entry point (GEP on
> > PowerPC).
> > Otherwise, a breakpoint is inserted at the normal entry point (LEP
> > on
> > PowerPC).
> > 
> > Function process_event_stop_test checks uses a stepping range to
> > stop
> > execution in the caller at the first instruction of the source code
> > line.
> > Note, on systems that only support one entry point, the address of
> > the two
> > entry points are the same.
> > 
> > Test finish-reverse-next.exp is updated to include tests for the
> > reverse-finish command when the function is entered via the normal
> > entry
> > point (i.e. the LEP) and the alternate entry point (i.e. the GEP).
> > 
> > The patch has been tested on X86 and PowerPC with no regressions.
> > ---
> >   gdb/infcmd.c                                  |  41 ++++---
> >   gdb/infrun.c                                  |  21 +++-
> >   .../gdb.reverse/finish-reverse-next.c         |  41 ++++++-
> >   .../gdb.reverse/finish-reverse-next.exp       | 107
> > +++++++++++++++---
> >   4 files changed, 175 insertions(+), 35 deletions(-)
> > 
> > diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> > index 9c42efeae8d..8c30af448ce 100644
> > --- a/gdb/infcmd.c
> > +++ b/gdb/infcmd.c
> > @@ -1722,22 +1722,28 @@ finish_backward (struct finish_command_fsm
> > *sm)
> >     sal = find_pc_line (func_addr, 0);
> >   
> >     frame_info_ptr frame = get_selected_frame (nullptr);
> > +  struct gdbarch *gdbarch = get_frame_arch (frame);
> > +  CORE_ADDR alt_entry_point = sal.pc;
> > +  CORE_ADDR entry_point = alt_entry_point;
> >   
> > -  if (sal.pc != pc)
> > +  if (gdbarch_skip_entrypoint_p (gdbarch))
> >       {
> > -      struct gdbarch *gdbarch = get_frame_arch (frame);
> > +      /* Some architectures, like PowerPC use local and global
> > entry
> > +	 points.  There is only one Entry Point (GEP = LEP) for other
> > +	 architectures.  The GEP is an alternate entry point that is
> > used
> > +	 setup the table of contents (TOC) in register r2 before
> > execution
> > +	 continues at the LEP.  The LEP is the normal entry point.
> I don't think an explanation on why there are 2 entry points is 
> necessary.  just mentioning that both exist is enough IMHO.

OK, took out the additional detail in the comment.

> > +	 The value of entry_point was initialized to the alternate
> > entry
> > +	 point (GEP).  It will be adjusted if the normal entry point
> > +	 (LEP) was used.  */
> > +       entry_point = gdbarch_skip_entrypoint (gdbarch,
> > entry_point);
> >   
> > -      /* Set a step-resume at the function's entry point.  Once
> > that's
> > -	 hit, we'll do one more step backwards.  */
> > -      symtab_and_line sr_sal;
> > -      sr_sal.pc = sal.pc;
> > -      sr_sal.pspace = get_frame_program_space (frame);
> > -      insert_step_resume_breakpoint_at_sal (gdbarch,
> > -					    sr_sal, null_frame_id);
> >       }
> > -  else
> > +
> > +  if (alt_entry_point <= pc && pc <= entry_point)
> >       {
> > -      /* We are exactly at the function entry point.  Note that
> > this
> > +      /* We are exactly at the function entry point, or between
> > the entry
> > +	 point on platforms that have two (like PowerPC).  Note that
> > this
> >   	 can only happen at frame #0.
> >   
> >   	 When setting a step range, need to call set_step_info
> > @@ -1746,8 +1752,17 @@ finish_backward (struct finish_command_fsm
> > *sm)
> >   
> >         /* Return using a step range so we will keep stepping back
> >   	 to the first instruction in the source code line.  */
> > -      tp->control.step_range_start = sal.pc;
> > -      tp->control.step_range_end = sal.pc;
> > +      tp->control.step_range_start = alt_entry_point;
> > +      tp->control.step_range_end = alt_entry_point;
> I'm hesitant in this part. What if there is one instruction between
> the 
> GEP and the LEP and the inferior happens to be stopped there? Could
> this 
> happen? 

Yes, if the user did a step instruction from the caller and stopped on
the second instruction in the function.  Note, there is actually one
instruction between the GEP instruction and the LEP instruction. 

> Like I said, I'm not familiar with the PPC abi, so excuse me if 
> the answer is obvious, but it seems to me that the step_range_end
> could 
> be set to the entry_point and we'd avoid this possibility.

Yes, that might be a little safer.  Changed to set step_range_end to
entry_point. the LEP which occurs two instructions after the GEP.

> > +    }
> > +  else
> > +    {
> > +      symtab_and_line sr_sal;
> > +      /* Set a step-resume at the function's entry point.  */
> > +      sr_sal.pc = entry_point;
> > +      sr_sal.pspace = get_frame_program_space (frame);
> > +      insert_step_resume_breakpoint_at_sal (gdbarch,
> > +					    sr_sal, null_frame_id);
> >       }
> >     proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> >   }
> > diff --git a/gdb/infrun.c b/gdb/infrun.c
> > index 8ed538ea9ec..89423556ec0 100644
> > --- a/gdb/infrun.c
> > +++ b/gdb/infrun.c
> > @@ -1868,6 +1868,7 @@ struct execution_control_state
> >   
> >     struct target_waitstatus ws;
> >     int stop_func_filled_in = 0;
> > +  CORE_ADDR stop_func_alt_start = 0;
> >     CORE_ADDR stop_func_start = 0;
> >     CORE_ADDR stop_func_end = 0;
> >     const char *stop_func_name = nullptr;
> > @@ -4663,6 +4664,14 @@ fill_in_stop_func (struct gdbarch *gdbarch,
> >   				    &block);
> >         ecs->stop_func_name = gsi == nullptr ? nullptr : gsi-
> > >print_name ();
> >   
> > +      /* PowerPC functions have a Local Entry Point and a Global
> > Entry
> > +	 Point.  There is only one Entry Point (GEP = LEP) for other
> > +	 architectures.  The GEP is an alternate entry point that is
> > used
> > +	 setup the table of contents (TOC) in register r2 before
> > execution
> > +	 continues at the LEP.  Save the alternate entry point address
> > for
> Ditto here about explaining LEP and GEP. Just saying that GEP is the 
> alternate is probably enough.

OK, removed the additional explanation from both places in the GDB
code.  I did leave the extra descripion in the test case where I gave
the sample assembly code.  My feeling is having that extra information
is useful in the test case to explain what the specific test scenarios
are doing and why is helpful.  Having the extra detail repeated three
times in the gdb source code and test case is probably a bit much.   

> > +	 use later.  */
> > +      ecs->stop_func_alt_start = ecs->stop_func_start;
> > +
> >         /* The call to find_pc_partial_function, above, will set
> >   	 stop_func_start and stop_func_end to the start and end
> >   	 of the range containing the stop pc.  If this range
> > @@ -4679,6 +4688,9 @@ fill_in_stop_func (struct gdbarch *gdbarch,
> >   	    += gdbarch_deprecated_function_start_offset (gdbarch);
> >   
> >   	  if (gdbarch_skip_entrypoint_p (gdbarch))
> > +	    /* The PowerPC architecture uses two entry points.  Stop at
> > the
> > +	       regular entry point (LEP on PowerPC) initially.  Will
> > setup a
> > +	       breakpoint for the alternate entry point (GEP)
> > later.  */
> >   	    ecs->stop_func_start
> >   	      = gdbarch_skip_entrypoint (gdbarch, ecs-
> > >stop_func_start);
> >   	}
> > @@ -6738,8 +6750,7 @@ process_event_stop_test (struct
> > execution_control_state *ecs)
> >         delete_step_resume_breakpoint (ecs->event_thread);
> >         fill_in_stop_func (gdbarch, ecs);
> >   
> > -      if (execution_direction == EXEC_REVERSE
> > -	  && ecs->event_thread->stop_pc () == ecs->stop_func_start)
> > +      if (execution_direction == EXEC_REVERSE)
> Why is this change not in the previous patch?

Looks like it didn't get moved when I was reversing the order of the
patches. 

Moved the change to the previous patch.

> >   	{
> >   	  struct thread_info *tp = ecs->event_thread;
> >   	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (),
> > 0);
> > @@ -6755,7 +6766,7 @@ process_event_stop_test (struct
> > execution_control_state *ecs)
> >   
> >   	     Return using a step range so we will keep stepping back to
> > the
> >   	     first instruction in the source code line.  */
> > -	  tp->control.step_range_start = ecs->stop_func_start;
> > +	  tp->control.step_range_start = ecs->stop_func_alt_start;
> >   	  tp->control.step_range_end = ecs->stop_func_start;
> >   	  keep_going (ecs);
> >   	  return;
> > @@ -6892,8 +6903,10 @@ process_event_stop_test (struct
> > execution_control_state *ecs)
> >   	 (unless it's the function entry point, in which case
> >   	 keep going back to the call point).  */
> >         CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
> > +
> >         if (stop_pc == ecs->event_thread->control.step_range_start
> > -	  && stop_pc != ecs->stop_func_start
> > +	  && (stop_pc < ecs->stop_func_alt_start
> > +	      || stop_pc > ecs->stop_func_start)
> >   	  && execution_direction == EXEC_REVERSE)
> >   	end_stepping_range (ecs);
> >         else
> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > index 42e41b5a2e0..55f81d2bc01 100644
> > --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > @@ -1,4 +1,4 @@
> > 

<snip>

> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > index 7880de10ffc..fbc024b48b9 100644
> > --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp

<snip>

The comments for patch 1/2 about using gdb_breakpoint and
gdb_continue_to_breakpoint were also applied to the two new tests.

> > +
> > +### TEST 3: reverse finish from the alternate entry point
> > instruction (GEP) in
> > +### function1 when called using the alternate entry point (GEP).
> > +
> > +# Set breakpoint at call to funp in main.
> > +set GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> > +gdb_test "break $srcfile:$GEP_test" "Breakpoint $decimal at .*" \
> > +    "set breakpoint on function1 GEP call to stepi into function"
> > +
> > +# Continue to break point at funp call in main.
> > +gdb_test "continue" "Breakpoint $decimal.*funp \\(a, b\\).*" \
> > +    "stopped at funp entry point instruction"
> > +
> > +# stepi until we see "{" indicating we entered function.
> > +cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
> > +
> > +delete_breakpoints
> > +
> > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> > +    "function1 GEP call call from GEP"
> > +
> > +# Check to make sure we stopped at the first instruction in the
> > source code
> > +# line.  It should only take one reverse next command to get to
> > the previous
> > +# source line.  If GDB stops at the last instruction in the source
> > code line
> > +# it will take two reverse next instructions to get to the
> > previous source
> > +# line.
> > +gdb_test "reverse-next" ".*b = 50;.*" "reverse next at b = 50,
> > call from GEP"
> > +
> > +# Turn off record to clear logs and turn on again
> > +gdb_test "record stop"  "Process record is stopped.*" \
> > +    "turn off process record for test3"
> > +gdb_test_no_output "record" "turn on process record for test4"
> > +
> > +
> > +### TEST 4: reverse finish from the body of function 1 when
> > calling using the
> > +### alternate entrypoint (GEP).
> > +gdb_test "break $srcfile:$GEP_test" "Breakpoint $decimal at .*" \
> > +    "set breakpoint on funp GEP call to step into body of
> > function"
> > +
> > +# Continue to break point at funp call.
> > +gdb_test "continue" "Breakpoint $decimal,.*funp \\(a, b\\).*" \
> > +    "stopped at funp call"
> > +
> > +# Step into body of funp, called via GEP.
> > +gdb_test "step" ".*int ret = 0;.*" "step test 2"
> > +
> > +delete_breakpoints
> > +
> > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> > +    "reverse-finish function1 GEP call, from function body  "
> > +
> > +# Check to make sure we stopped at the first instruction in the
> > source code
> > +# line.  It should only take one reverse next command to get to
> > the previous
> > +# source line.  If GDB stops at the last instruction in the source
> > code line
> > +# it will take two reverse next instructions to get to the
> > previous source
> > +# line.
> > +gdb_test "reverse-next" ".*b = 50;.*" \
> > +    "reverse next at b = 50 from function body"
> 
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-14 18:08                                                 ` Carl Love
@ 2023-01-16 12:31                                                   ` Bruno Larsen
  2023-01-16 16:37                                                     ` [PATCH 0/2 version 2] " Carl Love
                                                                       ` (2 more replies)
  0 siblings, 3 replies; 105+ messages in thread
From: Bruno Larsen @ 2023-01-16 12:31 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 14/01/2023 19:08, Carl Love wrote:
> On Fri, 2023-01-13 at 14:33 +0100, Bruno Larsen wrote:
>> On 11/01/2023 19:27, Carl Love via Gdb-patches wrote:
>>> GDB maintainers:
>>>
>>> This patch fixes the issues with the reverse-finish command on X86.
>>> The reverse-finish command now correctly stops at the first
>>> instruction
>>> in the source code line of the caller.  It now only requires a
>>> single
>>> reverse-step or reverse-next instruction to get back to the
>>> previous
>>> source code line.
>>>
>>> It also adds a new testcase, gdb.reverse/finish-reverse-next.exp,
>>> and
>>> updates several existing testcases.
>>>
>>> Please let me know if you have any comments on the patch.  Thanks.
>> Thanks for looking at this, this is a nice change. I just have a
>> couple
>> of comments, mostly related to the testsuite side.
>>>                       Carl
>>>
>>> --------------------------------------------------------------
>>> X86: reverse-finish fix
>>>
>>> Currently on X86, when executing the finish command in reverse, gdb
>>> does a
>>> single step from the first instruction in the callee to get back to
>>> the
>>> caller.  GDB stops on the last instruction in the source code line
>>> where
>>> the call was made.  When stopped at the last instruction of the
>>> source code
>>> line, a reverse next or step command will stop at the first
>>> instruction
>>> of the same source code line thus requiring two step/next commands
>>> to
>>> reach the previous source code line.  It should only require one
>>> step/next
>>> command to reach the previous source code line.
>>>
>>> By contrast, a reverse next or step command from the first line in
>>> a
>>> function stops at the first instruction in the source code line
>>> where the
>>> call was made.
>>>
>>> This patch fixes the reverse finish command so it will stop at the
>>> first
>>> instruction of the source line where the function call was
>>> made.  The
>>> behavior on X86 for the reverse-finish command now matches doing a
>>> reverse-next from the beginning of the function.
>>>
>>> The proceed_to_finish flag in struct thread_control_state is no
>>> longer
>>> used.  This patch removes the declaration, initialization and
>>> setting of
>>> the flag.
>>>
>>> This patch requires a number of regression tests to be
>>> updated.  Test
>>> gdb.mi/mi-reverse.exp no longer needs to execute two steps to get
>>> to the
>>> previous line.  The gdb output for tests gdb.reverse/until-
>>> precsave.exp
>>> and gdb.reverse/until-reverse.exp changed slightly.  The expected
>>> result in
>>> tests gdb.reverse/amd64-ailcall-reverse.exp and
>> s/ailcall/tailcall
> Fixed
>
>>> gdb.reverse/singlejmp-reverse.exp are updated to the correct
>>> expected
>>> result.
>>>
>>> This patch adds a new test gdb.reverse/finish-reverse-next.exp to
>>> test the
>>> reverse-finish command when returning from the entry point and from
>>> the
>>> body of the function.
>>>
>>> The step_until proceedure in test gdb.reverse/step-indirect-call-
>>> thunk.exp
>>> was moved to lib/gdb.exp and renamed cmd_until.
>> I'm not a big fan of the name cmd_until, because it sounded to me
>> like
>> you were testing the GDB command until. I think repeat_cmd_until or
>> repeat_until would avoid this possible confusion.
> Changed cmd_until to repeat_cmd_until.
>
>>> The patch has been tested on X86 and PowerPC to verify no
>>> additional
>>> regression failures occured.
>>>
>>> Bug:
>>> https://sourceware.org/bugzilla/show_bug.cgi?id=29927
>>>   
>> If you add record/29927 somewhere along the text of your commit
>> message,
>> there is some automation that will comment on the bugzilla bug
>> specifying this commit. Might be worth doing for future reference.
> Added.  I realized I had forgotten to do that after I sent the email.
> I added it to both patches.
>
>>> ---
>>>    gdb/gdbthread.h                               |   4 -
>>>    gdb/infcall.c                                 |   3 -
>>>    gdb/infcmd.c                                  |  32 +++---
>>>    gdb/infrun.c                                  |  41 +++----
>>>    gdb/testsuite/gdb.mi/mi-reverse.exp           |   9 +-
>>>    .../gdb.reverse/amd64-tailcall-reverse.exp    |   5 +-
>>>    .../gdb.reverse/finish-reverse-next.c         |  48 ++++++++
>>>    .../gdb.reverse/finish-reverse-next.exp       | 108
>>> ++++++++++++++++++
>>>    gdb/testsuite/gdb.reverse/finish-reverse.exp  |   5 +
>>>    .../gdb.reverse/singlejmp-reverse.exp         |   5 +-
>>>    .../gdb.reverse/step-indirect-call-thunk.exp  |  49 ++------
>>>    gdb/testsuite/gdb.reverse/until-precsave.exp  |   2 +-
>>>    gdb/testsuite/gdb.reverse/until-reverse.exp   |   2 +-
>>>    gdb/testsuite/lib/gdb.exp                     |  33 ++++++
>>>    14 files changed, 240 insertions(+), 106 deletions(-)
>>>    create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-
>>> next.c
>>>    create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-
>>> next.exp
>>>
>>> diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
>>> index 11d69fceab0..e4edff2d621 100644
>>> --- a/gdb/gdbthread.h
>>> +++ b/gdb/gdbthread.h
>>> @@ -150,10 +150,6 @@ struct thread_control_state
>>>         the finished single step.  */
>>>      int trap_expected = 0;
>>>    
>>> -  /* Nonzero if the thread is being proceeded for a "finish"
>>> command
>>> -     or a similar situation when return value should be
>>> printed.  */
>>> -  int proceed_to_finish = 0;
>>> -
>>>      /* Nonzero if the thread is being proceeded for an inferior
>>> function
>>>         call.  */
>>>      int in_infcall = 0;
>>> diff --git a/gdb/infcall.c b/gdb/infcall.c
>>> index e09904f9a35..116605c43ef 100644
>>> --- a/gdb/infcall.c
>>> +++ b/gdb/infcall.c
>>> @@ -625,9 +625,6 @@ run_inferior_call
>>> (std::unique_ptr<call_thread_fsm> sm,
>>>    
>>>      disable_watchpoints_before_interactive_call_start ();
>>>    
>>> -  /* We want to print return value, please...  */
>>> -  call_thread->control.proceed_to_finish = 1;
>>> -
>>>      try
>>>        {
>>>          /* Infcalls run synchronously, in the foreground.  */
>>> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
>>> index 0497ad05091..9c42efeae8d 100644
>>> --- a/gdb/infcmd.c
>>> +++ b/gdb/infcmd.c
>>> @@ -1721,19 +1721,10 @@ finish_backward (struct finish_command_fsm
>>> *sm)
>>>    
>>>      sal = find_pc_line (func_addr, 0);
>>>    
>>> -  tp->control.proceed_to_finish = 1;
>>> -  /* Special case: if we're sitting at the function entry point,
>>> -     then all we need to do is take a reverse singlestep.  We
>>> -     don't need to set a breakpoint, and indeed it would do us
>>> -     no good to do so.
>>> -
>>> -     Note that this can only happen at frame #0, since there's
>>> -     no way that a function up the stack can have a return address
>>> -     that's equal to its entry point.  */
>>> +  frame_info_ptr frame = get_selected_frame (nullptr);
>>>    
>>>      if (sal.pc != pc)
>>>        {
>>> -      frame_info_ptr frame = get_selected_frame (nullptr);
>>>          struct gdbarch *gdbarch = get_frame_arch (frame);
>>>    
>>>          /* Set a step-resume at the function's entry point.  Once
>>> that's
>>> @@ -1743,16 +1734,22 @@ finish_backward (struct finish_command_fsm
>>> *sm)
>>>          sr_sal.pspace = get_frame_program_space (frame);
>>>          insert_step_resume_breakpoint_at_sal (gdbarch,
>>>    					    sr_sal, null_frame_id);
>>> -
>>> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>>>        }
>>>      else
>>>        {
>>> -      /* We're almost there -- we just need to back up by one more
>>> -	 single-step.  */
>>> -      tp->control.step_range_start = tp->control.step_range_end =
>>> 1;
>>> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>>> +      /* We are exactly at the function entry point.  Note that
>>> this
>>> +	 can only happen at frame #0.
>>> +
>>> +	 When setting a step range, need to call set_step_info
>>> +	 to setup the current_line/symtab fields as well.  */
>>> +      set_step_info (tp, frame, find_pc_line (pc, 0));
>>> +
>>> +      /* Return using a step range so we will keep stepping back
>>> +	 to the first instruction in the source code line.  */
>>> +      tp->control.step_range_start = sal.pc;
>>> +      tp->control.step_range_end = sal.pc;
>>>        }
>>> +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>>>    }
>>>    
>>>    /* finish_forward -- helper function for finish_command.  FRAME
>>> is the
>>> @@ -1778,9 +1775,6 @@ finish_forward (struct finish_command_fsm
>>> *sm, frame_info_ptr frame)
>>>    
>>>      set_longjmp_breakpoint (tp, frame_id);
>>>    
>>> -  /* We want to print return value, please...  */
>>> -  tp->control.proceed_to_finish = 1;
>>> -
>>>      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>>>    }
>>>    
>>> diff --git a/gdb/infrun.c b/gdb/infrun.c
>>> index 181d961d80d..8ed538ea9ec 100644
>>> --- a/gdb/infrun.c
>>> +++ b/gdb/infrun.c
>>> @@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct
>>> thread_info *tp)
>>>    
>>>      tp->control.stop_step = 0;
>>>    
>>> -  tp->control.proceed_to_finish = 0;
>>> -
>>>      tp->control.stepping_command = 0;
>>>    
>>>      /* Discard any remaining commands or status from previous
>>> stop.  */
>>> @@ -6737,31 +6735,28 @@ process_event_stop_test (struct
>>> execution_control_state *ecs)
>>>    
>>>        case BPSTAT_WHAT_STEP_RESUME:
>>>          infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
>>> -
>>>          delete_step_resume_breakpoint (ecs->event_thread);
>>> -      if (ecs->event_thread->control.proceed_to_finish
>>> -	  && execution_direction == EXEC_REVERSE)
>>> +      fill_in_stop_func (gdbarch, ecs);
>>> +
>>> +      if (execution_direction == EXEC_REVERSE
>>> +	  && ecs->event_thread->stop_pc () == ecs->stop_func_start)
>> Is there any reason to invert the order of checks here? The second
>> if
>> clause is the same and keeping that would make the changes easier to
>> parse.
> No, must have inadvertently swizzled it as part of the patch
> development.  Per comments for the second patch, PowerPC, the  "cs-
>> event_thread->stop_pc () == ecs->stop_func_start" check should be
> removed in this patch not the PowerPC patch.  Probably got missed when
> I switched the order of the patches.
>
>   Fixed, removed the "ecs->event_thread->stop_pc () == ecs-
>> stop_func_start" test here.
>>>    	{
>>>    	  struct thread_info *tp = ecs->event_thread;
>>> +	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (),
>>> 0);
>>>    
>>> -	  /* We are finishing a function in reverse, and just hit the
>>> -	     step-resume breakpoint at the start address of the
>>> -	     function, and we're almost there -- just need to back up
>>> -	     by one more single-step, which should take us back to the
>>> -	     function call.  */
>>> -	  tp->control.step_range_start = tp->control.step_range_end =
>>> 1;
>>> -	  keep_going (ecs);
>>> -	  return;
>>> -	}
>>> -      fill_in_stop_func (gdbarch, ecs);
>>> -      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
>>> -	  && execution_direction == EXEC_REVERSE)
>>> -	{
>>> -	  /* We are stepping over a function call in reverse, and just
>>> -	     hit the step-resume breakpoint at the start address of
>>> -	     the function.  Go back to single-stepping, which should
>>> -	     take us back to the function call.  */
>>> -	  ecs->event_thread->stepping_over_breakpoint = 1;
> The following comment was from the second email.
>
>   >      case BPSTAT_WHAT_STEP_RESUME:> Something else that I failed to
> notice. Since you removed both
>> comments
>> that mention that this case is here for reverse finishing, there is
>> no
>> good way to figure out what GDB wants to do when this part of the
>> code
>> is reached. Adding a comment here mentioning it would fix that.
>>>           infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
> There were two separate if statements, each with a comment about what
> they were for.  Those comments were removed and a new, similar, comment
> was added in the single new if statement.  Admittedly, the new comment
> is a bit farther into the function and thus easy to miss.  So, I moved
> the initial comment about what is going on "We are finishing a function
> in reverse or..." up to the beginning of the if statement.  Hopefully
> that helps make it quicker/easier for the reader to see what the
> purpose of the case statement/if statement.  Please let me know if that
> helps address your concerns.
Yeah, this works. It is mostly so that we don't end up with a comment 
kinda far away or in a situation where it's hard to understand the point 
of this case statement.
>
>>> +	  /* When setting a step range, need to call set_step_info
>>> +	     to setup the current_line/symtab fields as well.  */
>>> +	  set_step_info (tp, frame, stop_pc_sal);
>>> +
>>> +	  /* We are finishing a function in reverse or stepping over a
>>> function
>>> +	     call in reverse, and just hit the step-resume breakpoint
>>> at the
>>> +	     start address of the function, and we're almost there --
>>> just need
>>> +	     to back up to the function call.
>>> +
>>> +	     Return using a step range so we will keep stepping back to
>>> the
>>> +	     first instruction in the source code line.  */
>>> +	  tp->control.step_range_start = ecs->stop_func_start;
>>> +	  tp->control.step_range_end = ecs->stop_func_start;
>>>    	  keep_going (ecs);
>>>    	  return;
>>>    	}
>>> diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp
>>> b/gdb/testsuite/gdb.mi/mi-reverse.exp
>>> index d631beb17c8..30635ab1754 100644
>>> --- a/gdb/testsuite/gdb.mi/mi-reverse.exp
>>> +++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
>>> @@ -97,15 +97,10 @@ proc test_controlled_execution_reverse {} {
>>>    	"basics.c" $line_main_callme_1 "" \
>>>    	"reverse finish from callme"
>>>    
>>> -    # Test exec-reverse-next
>>> -    #   It takes two steps to get back to the previous line,
>>> -    #   as the first step moves us to the start of the current
>>> line,
>>> -    #   and the one after that moves back to the previous line.
>>> -
>>> -    mi_execute_to "exec-next --reverse 2" \
>>> +    mi_execute_to "exec-next --reverse" \
>>>     	"end-stepping-range" "main" "" \
>>>     	"basics.c" $line_main_hello "" \
>>> - 	"reverse next to get over the call to do_nothing"
>>> +	"reverse next to get over the call to do_nothing"
>>>    
>>>        # Test exec-reverse-step
>>>    
>>> diff --git a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
>>> b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
>>> index 52a87faabf7..9964b4f8e4b 100644
>>> --- a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
>>> +++ b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
>>> @@ -44,6 +44,5 @@ if [supports_process_record] {
>>>    gdb_test "next" {f \(\);} "next to f"
>>>    gdb_test "next" {v = 3;} "next to v = 3"
>>>    
>>> -# FAIL was:
>>> -# 29        g ();
>>> -gdb_test "reverse-next" {f \(\);}
>>> +# Reverse step back into f ().  Puts us at call to g () in
>>> function f ().
>>> +gdb_test "reverse-next" {g \(\);}
>>> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
>>> b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
>>> new file mode 100644
>>> index 00000000000..42e41b5a2e0
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
>>> @@ -0,0 +1,48 @@
>>> +/* This testcase is part of GDB, the GNU debugger.
>>> +
>>> +   Copyright 2012-2022 Free Software Foundation, Inc.
>> copyright year should be 2023.
>>> +
>>> +   This program is free software; you can redistribute it and/or
>>> modify
>>> +   it under the terms of the GNU General Public License as
>>> published by
>>> +   the Free Software Foundation; either version 3 of the License,
>>> or
>>> +   (at your option) any later version.
>>> +
>>> +   This program is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +   GNU General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU General Public
>>> License
>>> +   along with this program.  If not, see <
>>> http://www.gnu.org/licenses/
>>>   >.  */
>>> +
>>> +/* The reverse finish command should return from a function and
>>> stop on
>>> +   the first instruction of the source line where the function
>>> call is made.
>>> +   Specifically, the behavior should match doing a reverse next
>>> from the
>>> +   first instruction in the function.  GDB should only require one
>>> reverse
>>> +   step or next statement to reach the previous source code line.
>>> +
>>> +   This test verifies the fix for gdb bugzilla:
>>> +
>>> +
>>> https://sourceware.org/bugzilla/show_bug.cgi?id=29927
>>>   
>>> +*/
>>> +
>>> +int
>>> +function1 (int a, int b)   // FUNCTION1
>>> +{
>>> +  int ret = 0;
>>> +
>>> +  ret = a + b;
>>> +  return ret;
>>> +}
>>> +
>>> +int
>>> +main(int argc, char* argv[])
>>> +{
>>> +  int a, b;
>>> +
>>> +  a = 1;
>>> +  b = 5;
>>> +
>>> +  function1 (a, b);   // CALL FUNCTION
>>> +  return 0;
>>> +}
>>> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
>>> b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
>>> new file mode 100644
>>> index 00000000000..7880de10ffc
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
>>> @@ -0,0 +1,108 @@
>>> +# Copyright 2008-2022 Free Software Foundation, Inc.
> Fixed copyright so it reads 2008-2023.  Fixed in finish-reverse-
> next.exp and finish-reverse-next.c.
>
>>> +
>>> +# This program is free software; you can redistribute it and/or
>>> modify
>>> +# it under the terms of the GNU General Public License as
>>> published by
>>> +# the Free Software Foundation; either version 3 of the License,
>>> or
>>> +# (at your option) any later version.
>>> +#
>>> +# This program is distributed in the hope that it will be useful,
>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +# GNU General Public License for more details.
>>> +#
>>> +# You should have received a copy of the GNU General Public
>>> License
>>> +# along with this program.  If not, see <
>>> http://www.gnu.org/licenses/
>>>   >.  */
>>> +
>>> +# This file is part of the GDB testsuite.  It tests reverse
>>> stepping.
>>> +# Lots of code borrowed from "step-test.exp".
>>> +
>>> +# The reverse finish command should return from a function and
>>> stop on
>>> +# the first instruction of the source line where the function call
>>> is made.
>>> +# Specifically, the behavior should match doing a reverse next
>>> from the
>>> +# first instruction in the function.  GDB should only take one
>>> reverse step
>>> +# or next statement to reach the previous source code line.
>>> +
>>> +# This testcase verifies the reverse-finish command stops at the
>>> first
>>> +# instruction in the source code line where the function was
>>> called.  There
>>> +# are two scenarios that must be checked:
>>> +#   1) gdb is at the entry point instruction for the function
>>> +#   2) gdb is in the body of the function.
>> While testing locally, I ran into a bug with reverse finish at the
>> epilogue of the function, that your patch also fixed. It would be
>> nice
>> if the test extended that. And since the bug was that GDB stopped
>> responding and even ctrl+c did nothing, I would suggest adding it as
>> the
>> last test.
> Discussed this additional bug in earlier emails.  Waiting to hear if
> the new test I sent reliably exposes the gdb hang that Bruno reported.
> If it does, I will add the new test to the new test case before posting
> the updated patch set. Per the discussions, I have not been able to
> reproduce the issue on my X86 or PowerPC machines.
I just tried reproducing it again on my end and failed, even my original 
test. It must have been a fluke, maybe I forgot to compile something 
after pulling from upstream.  Thanks for all the thought you put into 
it, though!
>
>>> +
>>> +# This test verifies the fix for gdb bugzilla:
>>> +#
>>> https://sourceware.org/bugzilla/show_bug.cgi?id=29927
>>>   
>>> +
>>> +if ![supports_reverse] {
>>> +    return
>>> +}
>>> +
>>> +standard_testfile
>>> +
>>> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile]
>>> } {
>>> +    return -1
>>> +}
>>> +
>>> +runto_main
>>> +set target_remote [gdb_is_target_remote]
>>> +
>>> +if [supports_process_record] {
>>> +    # Activate process record/replay.
>>> +    gdb_test_no_output "record" "turn on process record for test1"
>>> +}
>>> +
>>> +
>>> +### TEST 1: reverse finish from the entry point instruction in
>>> +### function1.
>>> +
>>> +# Set breakpoint at call to function1 in main.
>>> +set FUNCTION_test  [gdb_get_line_number "CALL FUNCTION" $srcfile]
>>> +gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at
>>> .*" \his
>>> +    "set breakpoint on function1 call to stepi into function"
>> There is a proc in lib/gdb.exp called gdb_breakpoint which
>> couldsimplify
>> this gdb_test to
>>
>> gdb_breakpoint $srcfile:$FUNCTION_test temporary
>>
>> And would remove the need for the delete_breakpoints call later.
>>
> OK, made the change in both tests.  Made the same change in the PowerPC
> patch that adds additional tests.
>
>
>>> +
>>> +# Continue to break point at function1 call in main.
>>> +gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*"
>>> \
>>> +    "stopped at function1 entry point instruction to stepi into
>>> function"
>> You can use gdb_continue_to_breakpoint here instead.
> OK, made the change in both tests.  Made the same change in the PowerPC
> patch that adds additional tests.
>
>>> +
>>> +# stepi until we see "{" indicating we entered function1
>>> +cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
>>> +
>>> +delete_breakpoints
>>> +
>>> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL
>>> FUNCTION.*" \
>>> +    "reverse-finish function1 "
>>> +
>>> +# Check to make sure we stopped at the first instruction in the
>>> source code
>>> +# line.  It should only take one reverse next command to get to
>>> the previous
>>> +# source line.   If GDB stops at the last instruction in the
>>> source code line
>>> +# it will take two reverse next instructions to get to the
>>> previous source
>>> +# line.
>>> +gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call
>>> from function"
>>> +
>>> +# Clear the recorded log.
>>> +gdb_test "record stop"  "Process record is stopped.*" \
>>> +    "turn off process record for test1"
>>> +gdb_test_no_output "record" "turn on process record for test2"
>>> +
>>> +
>>> +### TEST 2: reverse finish from the body of function1.
>>> +
>>> +# Set breakpoint at call to functiojust dont get it confused with maftn1 in main.
>>> +gdb_test "break $srcfile:$FUNCTION_test" "Breakpoint $decimal at
>>> .*" \
>>> +    "set breakpoint on function1 call to step into body of
>>> function"
>>> +
>>> +# Continue to break point at function1 call in main.
>>> +gdb_test "continue" "Breakpoint $decimal,.*function1 \\(a, b\\).*"
>>> \
>>> +    "stopped at function1 entry point instruction to step to body
>>> of function"
>>> +
>>> +delete_breakpoints
>>> +
>>> +# do a step instruction to get to the body of the function
>>> +gdb_test "step" ".*int ret = 0;.*" "step test 1"
>>> +
>>> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL
>>> FUNCTION.*" \
>>> +    "reverse-finish function1 call from function body"
>>> +
>>> +# Check to make sure we stopped at the first instruction in the
>>> source code
>>> +# line.  It should only take one reverse next command to get to
>>> the previous
>>> +# source line.
>>> +gdb_test "reverse-next" ".*b = 5;.*" \
>>> +    "reverse next at b = 5, from function body"
>>> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse.exp
>>> b/gdb/testsuite/gdb.reverse/finish-reverse.exp
>>> index 01ba309420c..a05cb81892a 100644
>>> --- a/gdb/testsuite/gdb.reverse/finish-reverse.exp
>>> +++ b/gdb/testsuite/gdb.reverse/finish-reverse.exp
>>> @@ -16,6 +16,11 @@
>>>    # This file is part of the GDB testsuite.  It tests 'finish' with
>>>    # reverse debugging.
>>>    
>>> +# This test verifies the fix for gdb bugzilla:
>>> +
>>> +#
>>> https://sourceware.org/bugzilla/show_bug.cgi?id=29927
>>>   
>>> +
>>> +
>> Is this comment a left over from an earlier version?
>>
>> I actually wonder if the whole new test is needed, or if you can
>> just
>> add a couple of new tests to finish-reverse.exp; is there any reason
>> you
>> went with the new test instead
> Yes, it is left over.  Initially I just added an additional test to
> finish-reverse.exp for the PowerPC fix.  But as work progressed, I kept
> adding more tests for PowerPC then for X86.  I felt that it was better
> to have a new test file that was tied to the Bugzilla.  The existing
> test file has a different focus from the new tests.  The bugzilla
> change didn't get removed from finish-reverse.exp when the tests were
> moved to the new file.  We can combine the tests again if that is
> preferable?   My preference would be to have separate test files.
> Please let me know if you would prefer a single file and I will merge
> them before re-posting the patches.
Oh, ok, the separation makes sense now. I looked only at this patch 
first and asked before looking at patch 2. I'd say its fine, no need to 
merge them.
>
>>>    if ![supports_reverse] {
>>>        return
>>>    }
>>> diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
>>> b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
>>> index 1ca7c2ce559..eb03051625a 100644
>>> --- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
>>> +++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
>>> @@ -56,7 +56,4 @@ gdb_test "next" {v = 3;} "next to v = 3"
>>>    # {
>>>    gdb_test "reverse-step" {nodebug \(\);}
>>>    
>>> -# FAIL was:
>>> -# No more reverse-execution history.
>>> -# {
>>> -gdb_test "reverse-next" {f \(\);}
>>> +gdb_test "reverse-next" {g \(\);}
>>> diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
>>> b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
>>> index ad637899e5b..1928cdda217 100644
>>> --- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
>>> +++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
>>> @@ -39,39 +39,6 @@ if { ![runto_main] } {
>>>        return -1
>>>    }
>>>    
>>> -# Do repeated stepping COMMANDs in order to reach TARGET from
>>> CURRENT
>>> -#
>>> -#  COMMAND is a stepping command
>>> -#  CURRENT is a string matching the current location
>>> -#  TARGET  is a string matching the target location
>>> -#  TEST    is the test name
>>> -#
>>> -# The function issues repeated COMMANDs as long as the location
>>> matches
>>> -# CURRENT up to a maximum of 100 steps.
>>> -#
>>> -# TEST passes if the resulting location matches TARGET and fails
>>> -# otherwise.
>>> -#
>>> -proc step_until { command current target test } {
>>> -    global gdb_prompt
>>> -
>>> -    set count 0
>>> -    gdb_test_multiple "$command" "$test" {
>>> -        -re "$current.*$gdb_prompt $" {
>>> -            incr count
>>> -            if { $count < 100 } {
>>> -                send_gdb "$command\n"
>>> -                exp_continue
>>> -            } else {
>>> -                fail "$test"
>>> -            }
>>> -        }
>>> -        -re "$target.*$gdb_prompt $" {
>>> -            pass "$test"
>>> -        }
>>> -    }
>>> -}
>>> -
>>>    gdb_test_no_output "record"
>>>    gdb_test "next" ".*" "record trace"
>>>    
>>> @@ -91,20 +58,20 @@ gdb_test "reverse-next" "apply\.2.*" \
>>>        "reverse-step through thunks and over inc"
>>>    
>>>    # We can use instruction stepping to step into thunks.
>>> -step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call
>>> thunk"
>>> -step_until "stepi" "indirect_thunk" "inc" \
>>> +cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call
>>> thunk"
>>> +cmd_until "stepi" "indirect_thunk" "inc" \
>>>        "stepi out of call thunk into inc"
>>>    set alphanum_re "\[a-zA-Z0-9\]"
>>>    set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re*
>>> \\(\\)"
>>> -step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi
>>> into return thunk"
>>> -step_until "stepi" "return_thunk" "apply" \
>>> +cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into
>>> return thunk"
>>> +cmd_until "stepi" "return_thunk" "apply" \
>>>        "stepi out of return thunk back into apply"
>>>    
>>> -step_until "reverse-stepi" "apply" "return_thunk" \
>>> +cmd_until "reverse-stepi" "apply" "return_thunk" \
>>>        "reverse-stepi into return thunk"
>>> -step_until "reverse-stepi" "return_thunk" "inc" \
>>> +cmd_until "reverse-stepi" "return_thunk" "inc" \
>>>        "reverse-stepi out of return thunk into inc"
>>> -step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk"
>>> \
>>> +cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
>>>        "reverse-stepi into call thunk"
>>> -step_until "reverse-stepi" "indirect_thunk" "apply" \
>>> +cmd_until "reverse-stepi" "indirect_thunk" "apply" \
>>>        "reverse-stepi out of call thunk into apply"
>>> diff --git a/gdb/testsuite/gdb.reverse/until-precsave.exp
>>> b/gdb/testsuite/gdb.reverse/until-precsave.exp
>>> index 0c2d7537cd6..777aec94ac1 100644
>>> --- a/gdb/testsuite/gdb.reverse/until-precsave.exp
>>> +++ b/gdb/testsuite/gdb.reverse/until-precsave.exp
>>> @@ -142,7 +142,7 @@ gdb_test "advance marker2" \
>>>    # Finish out to main scope (backward)
>>>    
>>>    gdb_test "finish" \
>>> -    " in main .*$srcfile:$bp_location20.*" \
>>> +    "main .*$srcfile:$bp_location20.*" \
>> This change doesn't seem connected to anything in this patch, is
>> this
>> just a cosmetic change or was there some problem?
>>>        "reverse-finish from marker2"
>>>    
> The output changes due to the functional changes in infrun.c.  Instead
> of stepping back one instruction i.e. ecs->event_thread-
>> stepping_over_breakpoint = 1 we step back using a range.  Apparently
> this causes the gdb output message to change.
>
> Without the patch the output looks like:
>    Run back to call of #0  marker2 (a=43) at.../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/ur1.c:30
>
>    0x0000000010000838 in main (argc=1, argv=0x7fffffffcc58, envp=0x7fffffffcc68) at /.../gdb/testsuite/gdb.reverse/until-reverse.c:48^
>
> With the patch the output looks like:
>
>    Run back to call of #0  marker2 (a=43) at .../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/ur1.c:30
>
>    main (argc=1, argv=0x7fffffffcc58, envp=0x7fffffffcc68) at .../binutils-gdb-finish-precsave/gdb/testsuite/gdb.reverse/until-reverse.c:48
>
> Basically, you lose the hex value and "in" with the patch applied.
> This is true in the until-reverse.exp tes, below, as well.  The output
> change was mentioned in the commit message as well.
Oh right, I should have checked the output before asking. Thank you for 
explaining!

-- 
Cheers,
Bruno

>
>>>    # Advance backward to last line of factorial (outer invocation)
>>> diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp
>>> b/gdb/testsuite/gdb.reverse/until-reverse.exp
>>> index 23fc881dbf2..3a05953329f 100644
>>> --- a/gdb/testsuite/gdb.reverse/until-reverse.exp
>>> +++ b/gdb/testsuite/gdb.reverse/until-reverse.exp
>>> @@ -113,7 +113,7 @@ gdb_test "advance marker2" \
>>>    # Finish out to main scope (backward)
>>>    
>>>    gdb_test "finish" \
>>> -    " in main .*$srcfile:$bp_location20.*" \
>>> +    "main .*$srcfile:$bp_location20.*" \
>> same here.
> Yup, see above.
>
>>>        "reverse-finish from marker2"
>>>    
>>>    # Advance backward to last line of factorial (outer invocation)
>>> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
>>> index c41d4698d66..25f42eb5510 100644
>>> --- a/gdb/testsuite/lib/gdb.exp
>>> +++ b/gdb/testsuite/lib/gdb.exp
>>> @@ -9301,6 +9301,39 @@ proc gdb_step_until { regexp {test_name ""}
>>> {max_steps 10} } {
>>>        }
>>>    }
>>>    
>>> +# Do repeated stepping COMMANDs in order to reach TARGET from
>>> CURRENT
>>> +#
>>> +#  COMMAND is a stepping command
>>> +#  CURRENT is a string matching the current location
>>> +#  TARGET  is a string matching the target location
>>> +#  TEST    is the test name
>>> +#
>>> +# The function issues repeated COMMANDs as long as the location
>>> matches
>>> +# CURRENT up to a maximum of 100 steps.
>>> +#
>>> +# TEST passes if the resulting location matches TARGET and fails
>>> +# otherwise.
>>> +
>>> +proc cmd_until { command current target test } {
>>> +    global gdb_prompt
>>> +
>>> +    set count 0
>>> +    gdb_test_multiple "$command" "$test" {
>>> +	-re "$current.*$gdb_prompt $" {
>>> +	    incr count
>>> +	    if { $count < 100 } {
>>> +		send_gdb "$command\n"
>>> +		exp_continue
>>> +	    } else {
>>> +		fail "$test"
>>> +	    }
>>> +	}
>>> +	-re "$target.*$gdb_prompt $" {
>>> +	    pass "$test"
>>> +	}
>>> +    }
>>> +}
>>> +
>>>    # Check if the compiler emits epilogue information associated
>>>    # with the closing brace or with the last statement line.
>>>    #
>>


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 0/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-16 12:31                                                   ` Bruno Larsen
@ 2023-01-16 16:37                                                     ` Carl Love
  2023-01-16 16:37                                                     ` [PATCH 1/2 " Carl Love
  2023-01-16 16:37                                                     ` [PATCH 2/2 version 2] " Carl Love
  2 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-16 16:37 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

GDB maintainers:

Version 2: Addressed various comments from Bruno Larsen.

This patch set fixes a couple of issues with the gdb.reverse tests
finish-precsave.exp and finish-reverse.exp.

The first issue is when doing a reverse-finish command from a function,
gdb should stop at the first instruction of the source code line where
the call was made.  The behavior should look the same as doing a
reverse-next from the first line of the function.  Currently gdb stops
at the last instruction in the caller source code line.  Issuing
reverse-step or reverse-next stops at the first instruction in the same
source code line.  It then requires a second reverse step or next
command to reach the previous source code line in the caller.  It
should only require one reverse step or next command to reach the
previous line.

The first patch in this series fixes the above issue on X86.  A number
of additional testcases require updating since the output is slightly
different or the test case no longer needs to issue the two reverse
step/next instructions.  The step_until proceedure in test
gdb.reverse/step-indirect-call-thunk.exp was moved to lib/gdb.exp and
renamed cmd_until.  The proceedure is used to test the reverse-finish
command when returning from the entry point of the function.

The second issue with the reverse-finish command is that on PowerPC the
reverse-finish doesn't stop at the function call.  The issue is PowerPC
uses two entry points.  PowerPC calls the two entry points the local
entry point (LEP) and the global entry point (GEP).  The LEP is
normally used when calling a function.  The GEP is used when the table
of contents (TOC) needs to be setup before continuing execution at the
LEP.  GDB is not handling the two entry points correctly.  The second
patch fixes the reverse-finish behavior on PowerPC.  On systems that
don't use two entry points the LEP and the GEP are the same.

A new testcase is added to verify the reverse-finish command works
correctly for X86 when returning from the body of a function and from
the entry point.  Note, the finish_backward function must handle the
two scenarios slightly differently.

The new testcase is expanded in the PPC patch to add tests for the two
scenarios for a function called via the GEP.  The initial set of tests
added in the X86 patch take care of the function being called via the
LEP on PowerPC.

The patches have been tested on PowerPC and X86 with no new
regressions.

Please let me know if the patches are acceptable for mainline.  Thanks.


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-16 12:31                                                   ` Bruno Larsen
  2023-01-16 16:37                                                     ` [PATCH 0/2 version 2] " Carl Love
@ 2023-01-16 16:37                                                     ` Carl Love
  2023-01-17 12:35                                                       ` Bruno Larsen
  2023-01-16 16:37                                                     ` [PATCH 2/2 version 2] " Carl Love
  2 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-16 16:37 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

GDB maintainers:

Version 2: Addressed various comments from Bruno Larsen.

This patch fixes the issues with the reverse-finish command on X86. 
The reverse-finish command now correctly stops at the first instruction
in the source code line of the caller.  It now only requires a single
reverse-step or reverse-next instruction to get back to the previous
source code line.

It also adds a new testcase, gdb.reverse/finish-reverse-next.exp, and
updates several existing testcases. 

Version 2 patch changes have been re-verified on PowerPC and X86 with
no regressions.

Please let me know if you have any comments on the patch.  Thanks.

                    Carl 

--------------------------------------------------------
X86: reverse-finish fix

PR record/29927  - reverse-finish requires two reverse next instructions to
reach previous source line

Currently on X86, when executing the finish command in reverse, gdb does a
single step from the first instruction in the callee to get back to the
caller.  GDB stops on the last instruction in the source code line where
the call was made.  When stopped at the last instruction of the source code
line, a reverse next or step command will stop at the first instruction
of the same source code line thus requiring two step/next commands to
reach the previous source code line.  It should only require one step/next
command to reach the previous source code line.

By contrast, a reverse next or step command from the first line in a
function stops at the first instruction in the source code line where the
call was made.

This patch fixes the reverse finish command so it will stop at the first
instruction of the source line where the function call was made.  The
behavior on X86 for the reverse-finish command now matches doing a
reverse-next from the beginning of the function.

The proceed_to_finish flag in struct thread_control_state is no longer
used.  This patch removes the declaration, initialization and setting of
the flag.

This patch requires a number of regression tests to be updated.  Test
gdb.mi/mi-reverse.exp no longer needs to execute two steps to get to the
previous line.  The gdb output for tests gdb.reverse/until-precsave.exp
and gdb.reverse/until-reverse.exp changed slightly.  The expected result in
tests gdb.reverse/amd64-failcall-reverse.exp and
gdb.reverse/singlejmp-reverse.exp are updated to the correct expected
result.

This patch adds a new test gdb.reverse/finish-reverse-next.exp to test the
reverse-finish command when returning from the entry point and from the
body of the function.

The step_until proceedure in test gdb.reverse/step-indirect-call-thunk.exp
was moved to lib/gdb.exp and renamed cmd_until.

The patch has been tested on X86 and PowerPC to verify no additional
regression failures occured.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29927
---
 gdb/gdbthread.h                               |   4 -
 gdb/infcall.c                                 |   3 -
 gdb/infcmd.c                                  |  32 +++---
 gdb/infrun.c                                  |  40 +++----
 gdb/testsuite/gdb.mi/mi-reverse.exp           |   9 +-
 .../gdb.reverse/amd64-tailcall-reverse.exp    |   5 +-
 .../gdb.reverse/finish-reverse-next.c         |  48 ++++++++
 .../gdb.reverse/finish-reverse-next.exp       | 104 ++++++++++++++++++
 .../gdb.reverse/singlejmp-reverse.exp         |   5 +-
 .../gdb.reverse/step-indirect-call-thunk.exp  |  49 ++-------
 gdb/testsuite/gdb.reverse/until-precsave.exp  |   2 +-
 gdb/testsuite/gdb.reverse/until-reverse.exp   |   2 +-
 gdb/testsuite/lib/gdb.exp                     |  33 ++++++
 13 files changed, 230 insertions(+), 106 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp

diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 11d69fceab0..e4edff2d621 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -150,10 +150,6 @@ struct thread_control_state
      the finished single step.  */
   int trap_expected = 0;
 
-  /* Nonzero if the thread is being proceeded for a "finish" command
-     or a similar situation when return value should be printed.  */
-  int proceed_to_finish = 0;
-
   /* Nonzero if the thread is being proceeded for an inferior function
      call.  */
   int in_infcall = 0;
diff --git a/gdb/infcall.c b/gdb/infcall.c
index e09904f9a35..116605c43ef 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -625,9 +625,6 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
 
   disable_watchpoints_before_interactive_call_start ();
 
-  /* We want to print return value, please...  */
-  call_thread->control.proceed_to_finish = 1;
-
   try
     {
       /* Infcalls run synchronously, in the foreground.  */
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 0497ad05091..9c42efeae8d 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1721,19 +1721,10 @@ finish_backward (struct finish_command_fsm *sm)
 
   sal = find_pc_line (func_addr, 0);
 
-  tp->control.proceed_to_finish = 1;
-  /* Special case: if we're sitting at the function entry point,
-     then all we need to do is take a reverse singlestep.  We
-     don't need to set a breakpoint, and indeed it would do us
-     no good to do so.
-
-     Note that this can only happen at frame #0, since there's
-     no way that a function up the stack can have a return address
-     that's equal to its entry point.  */
+  frame_info_ptr frame = get_selected_frame (nullptr);
 
   if (sal.pc != pc)
     {
-      frame_info_ptr frame = get_selected_frame (nullptr);
       struct gdbarch *gdbarch = get_frame_arch (frame);
 
       /* Set a step-resume at the function's entry point.  Once that's
@@ -1743,16 +1734,22 @@ finish_backward (struct finish_command_fsm *sm)
       sr_sal.pspace = get_frame_program_space (frame);
       insert_step_resume_breakpoint_at_sal (gdbarch,
 					    sr_sal, null_frame_id);
-
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
   else
     {
-      /* We're almost there -- we just need to back up by one more
-	 single-step.  */
-      tp->control.step_range_start = tp->control.step_range_end = 1;
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
+      /* We are exactly at the function entry point.  Note that this
+	 can only happen at frame #0.
+
+	 When setting a step range, need to call set_step_info
+	 to setup the current_line/symtab fields as well.  */
+      set_step_info (tp, frame, find_pc_line (pc, 0));
+
+      /* Return using a step range so we will keep stepping back
+	 to the first instruction in the source code line.  */
+      tp->control.step_range_start = sal.pc;
+      tp->control.step_range_end = sal.pc;
     }
+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
 /* finish_forward -- helper function for finish_command.  FRAME is the
@@ -1778,9 +1775,6 @@ finish_forward (struct finish_command_fsm *sm, frame_info_ptr frame)
 
   set_longjmp_breakpoint (tp, frame_id);
 
-  /* We want to print return value, please...  */
-  tp->control.proceed_to_finish = 1;
-
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 181d961d80d..86e5ef1ed12 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct thread_info *tp)
 
   tp->control.stop_step = 0;
 
-  tp->control.proceed_to_finish = 0;
-
   tp->control.stepping_command = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
@@ -6737,31 +6735,27 @@ process_event_stop_test (struct execution_control_state *ecs)
 
     case BPSTAT_WHAT_STEP_RESUME:
       infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
-
       delete_step_resume_breakpoint (ecs->event_thread);
-      if (ecs->event_thread->control.proceed_to_finish
-	  && execution_direction == EXEC_REVERSE)
+      fill_in_stop_func (gdbarch, ecs);
+
+      if (execution_direction == EXEC_REVERSE)
 	{
 	  struct thread_info *tp = ecs->event_thread;
+	  /* We are finishing a function in reverse or stepping over a function
+	     call in reverse, and just hit the step-resume breakpoint at the
+	     start address of the function, and we're almost there -- just need
+	     to back up to the function call.  */
 
-	  /* We are finishing a function in reverse, and just hit the
-	     step-resume breakpoint at the start address of the
-	     function, and we're almost there -- just need to back up
-	     by one more single-step, which should take us back to the
-	     function call.  */
-	  tp->control.step_range_start = tp->control.step_range_end = 1;
-	  keep_going (ecs);
-	  return;
-	}
-      fill_in_stop_func (gdbarch, ecs);
-      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
-	  && execution_direction == EXEC_REVERSE)
-	{
-	  /* We are stepping over a function call in reverse, and just
-	     hit the step-resume breakpoint at the start address of
-	     the function.  Go back to single-stepping, which should
-	     take us back to the function call.  */
-	  ecs->event_thread->stepping_over_breakpoint = 1;
+	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
+
+	  /* When setting a step range, need to call set_step_info
+	     to setup the current_line/symtab fields as well.  */
+	  set_step_info (tp, frame, stop_pc_sal);
+
+	  /* Return using a step range so we will keep stepping back to the
+	     first instruction in the source code line.  */
+	  tp->control.step_range_start = ecs->stop_func_start;
+	  tp->control.step_range_end = ecs->stop_func_start;
 	  keep_going (ecs);
 	  return;
 	}
diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
index d631beb17c8..30635ab1754 100644
--- a/gdb/testsuite/gdb.mi/mi-reverse.exp
+++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
@@ -97,15 +97,10 @@ proc test_controlled_execution_reverse {} {
 	"basics.c" $line_main_callme_1 "" \
 	"reverse finish from callme"
 
-    # Test exec-reverse-next
-    #   It takes two steps to get back to the previous line,
-    #   as the first step moves us to the start of the current line,
-    #   and the one after that moves back to the previous line.
-
-    mi_execute_to "exec-next --reverse 2" \
+    mi_execute_to "exec-next --reverse" \
  	"end-stepping-range" "main" "" \
  	"basics.c" $line_main_hello "" \
- 	"reverse next to get over the call to do_nothing"
+	"reverse next to get over the call to do_nothing"
 
     # Test exec-reverse-step
 
diff --git a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
index 52a87faabf7..9964b4f8e4b 100644
--- a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
@@ -44,6 +44,5 @@ if [supports_process_record] {
 gdb_test "next" {f \(\);} "next to f"
 gdb_test "next" {v = 3;} "next to v = 3"
 
-# FAIL was:
-# 29        g ();
-gdb_test "reverse-next" {f \(\);}
+# Reverse step back into f ().  Puts us at call to g () in function f ().
+gdb_test "reverse-next" {g \(\);}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
new file mode 100644
index 00000000000..f90ecbb93cb
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -0,0 +1,48 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The reverse finish command should return from a function and stop on
+   the first instruction of the source line where the function call is made.
+   Specifically, the behavior should match doing a reverse next from the
+   first instruction in the function.  GDB should only require one reverse
+   step or next statement to reach the previous source code line.
+
+   This test verifies the fix for gdb bugzilla:
+
+   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+*/
+
+int
+function1 (int a, int b)   // FUNCTION1
+{
+  int ret = 0;
+
+  ret = a + b;
+  return ret;
+}
+
+int
+main(int argc, char* argv[])
+{
+  int a, b;
+
+  a = 1;
+  b = 5;
+
+  function1 (a, b);   // CALL FUNCTION
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
new file mode 100644
index 00000000000..63305c109e1
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -0,0 +1,104 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+### TEST 1: reverse finish from the entry point instruction in
+### function1.
+
+# Set breakpoint at call to function1 in main.
+set bp_FUNCTION [gdb_get_line_number "CALL FUNCTION" $srcfile]
+gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_FUNCTION\r\n.*"
+
+# stepi until we see "{" indicating we entered function1
+repeat_cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
+    "reverse-finish function1 "
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.   If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
+
+# Clear the recorded log.
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+### TEST 2: reverse finish from the body of function1.
+
+# Set breakpoint at call to function1 in main.
+gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of function" \
+    ".*$srcfile:$bp_FUNCTION\r\n.*"
+
+# do a step instruction to get to the body of the function
+gdb_test "step" ".*int ret = 0;.*" "step test 1"
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
+    "reverse-finish function1 call from function body"
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse next at b = 5, from function body"
diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
index 1ca7c2ce559..eb03051625a 100644
--- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
@@ -56,7 +56,4 @@ gdb_test "next" {v = 3;} "next to v = 3"
 # {
 gdb_test "reverse-step" {nodebug \(\);}
 
-# FAIL was:
-# No more reverse-execution history.
-# {
-gdb_test "reverse-next" {f \(\);}
+gdb_test "reverse-next" {g \(\);}
diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index ad637899e5b..b82e5663bd5 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -39,39 +39,6 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
-proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
-}
-
 gdb_test_no_output "record"
 gdb_test "next" ".*" "record trace"
 
@@ -91,20 +58,20 @@ gdb_test "reverse-next" "apply\.2.*" \
     "reverse-step through thunks and over inc"
 
 # We can use instruction stepping to step into thunks.
-step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
-step_until "stepi" "indirect_thunk" "inc" \
+repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
+repeat_cmd_until "stepi" "indirect_thunk" "inc" \
     "stepi out of call thunk into inc"
 set alphanum_re "\[a-zA-Z0-9\]"
 set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
-step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
-step_until "stepi" "return_thunk" "apply" \
+repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
+repeat_cmd_until "stepi" "return_thunk" "apply" \
     "stepi out of return thunk back into apply"
 
-step_until "reverse-stepi" "apply" "return_thunk" \
+repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
     "reverse-stepi into return thunk"
-step_until "reverse-stepi" "return_thunk" "inc" \
+repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
     "reverse-stepi out of return thunk into inc"
-step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
+repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
     "reverse-stepi into call thunk"
-step_until "reverse-stepi" "indirect_thunk" "apply" \
+repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
     "reverse-stepi out of call thunk into apply"
diff --git a/gdb/testsuite/gdb.reverse/until-precsave.exp b/gdb/testsuite/gdb.reverse/until-precsave.exp
index 0c2d7537cd6..777aec94ac1 100644
--- a/gdb/testsuite/gdb.reverse/until-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/until-precsave.exp
@@ -142,7 +142,7 @@ gdb_test "advance marker2" \
 # Finish out to main scope (backward)
 
 gdb_test "finish" \
-    " in main .*$srcfile:$bp_location20.*" \
+    "main .*$srcfile:$bp_location20.*" \
     "reverse-finish from marker2"
 
 # Advance backward to last line of factorial (outer invocation)
diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp b/gdb/testsuite/gdb.reverse/until-reverse.exp
index 23fc881dbf2..3a05953329f 100644
--- a/gdb/testsuite/gdb.reverse/until-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/until-reverse.exp
@@ -113,7 +113,7 @@ gdb_test "advance marker2" \
 # Finish out to main scope (backward)
 
 gdb_test "finish" \
-    " in main .*$srcfile:$bp_location20.*" \
+    "main .*$srcfile:$bp_location20.*" \
     "reverse-finish from marker2"
 
 # Advance backward to last line of factorial (outer invocation)
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index c41d4698d66..234c21a04ea 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9301,6 +9301,39 @@ proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
     }
 }
 
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND is a stepping command
+#  CURRENT is a string matching the current location
+#  TARGET  is a string matching the target location
+#  TEST    is the test name
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of 100 steps.
+#
+# TEST passes if the resulting location matches TARGET and fails
+# otherwise.
+
+proc repeat_cmd_until { command current target test } {
+    global gdb_prompt
+
+    set count 0
+    gdb_test_multiple "$command" "$test" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < 100 } {
+		send_gdb "$command\n"
+		exp_continue
+	    } else {
+		fail "$test"
+	    }
+	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+}
+
 # Check if the compiler emits epilogue information associated
 # with the closing brace or with the last statement line.
 #
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-16 12:31                                                   ` Bruno Larsen
  2023-01-16 16:37                                                     ` [PATCH 0/2 version 2] " Carl Love
  2023-01-16 16:37                                                     ` [PATCH 1/2 " Carl Love
@ 2023-01-16 16:37                                                     ` Carl Love
  2023-01-17 14:29                                                       ` Bruno Larsen
  2 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-16 16:37 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

GDB maintainers:

Version 2: Addressed various comments from Bruno Larsen.

This patch fixes the issues with the reverse-finish command on
PowerPC.  The reverse-finish command now correctly stops at the first
instruction in the source code line of the caller.  

The patch adds tests for calling a function via the GEP to the new test
gdb.reverse/finish-reverse-next.exp.

Version 2 patch changes have been re-verified on PowerPC and X86 with
no regressions.

Please let me know if you have any comments on the patch.  Thanks.

                    Carl

---------------------------------------------------------------
PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp

PR record/29927 - reverse-finish requires two reverse next instructions to
reach previous source line

PowerPC uses two entry points called the local entry point (LEP) and the
global entry point (GEP).  Normally the LEP is used when calling a
function.  However, if the table of contents (TOC) value in register 2 is
not valid the GEP is called to setup the TOC before execution continues at
the LEP.  When executing in reverse, the function finish_backward sets the
break point at the alternate entry point (GEP).  However if the forward
execution enters via the normal entry point (LEP), the reverse execution
never sees the break point at the GEP of the function.  Reverse execution
continues until the next break point is encountered or the end of the
recorded log is reached causing gdb to stop at the wrong place.

This patch adds a new address to struct execution_control_state to hold the
address of the alternate function start address, known as the GEP on
PowerPC.  The finish_backwards function is updated.  If the stopping point
is between the two entry points (the LEP and GEP on PowerPC), the stepping
range is set to execute back to the alternate entry point (GEP on PowerPC).
Otherwise, a breakpoint is inserted at the normal entry point (LEP on
PowerPC).

Function process_event_stop_test checks uses a stepping range to stop
execution in the caller at the first instruction of the source code line.
Note, on systems that only support one entry point, the address of the two
entry points are the same.

Test finish-reverse-next.exp is updated to include tests for the
reverse-finish command when the function is entered via the normal entry
point (i.e. the LEP) and the alternate entry point (i.e. the GEP).

The patch has been tested on X86 and PowerPC with no regressions.
---
 gdb/infcmd.c                                  | 40 +++++---
 gdb/infrun.c                                  | 16 +++-
 .../gdb.reverse/finish-reverse-next.c         | 41 +++++++-
 .../gdb.reverse/finish-reverse-next.exp       | 96 ++++++++++++++++---
 4 files changed, 161 insertions(+), 32 deletions(-)

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 9c42efeae8d..6aaed34b1b6 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1722,22 +1722,25 @@ finish_backward (struct finish_command_fsm *sm)
   sal = find_pc_line (func_addr, 0);
 
   frame_info_ptr frame = get_selected_frame (nullptr);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  CORE_ADDR alt_entry_point = sal.pc;
+  CORE_ADDR entry_point = alt_entry_point;
 
-  if (sal.pc != pc)
+  if (gdbarch_skip_entrypoint_p (gdbarch))
     {
-      struct gdbarch *gdbarch = get_frame_arch (frame);
-
-      /* Set a step-resume at the function's entry point.  Once that's
-	 hit, we'll do one more step backwards.  */
-      symtab_and_line sr_sal;
-      sr_sal.pc = sal.pc;
-      sr_sal.pspace = get_frame_program_space (frame);
-      insert_step_resume_breakpoint_at_sal (gdbarch,
-					    sr_sal, null_frame_id);
+      /* Some architectures, like PowerPC use local and global entry points.
+	 There is only one Entry Point (GEP = LEP) for other architectures.
+	 The GEP is an alternate entry point.  The LEP is the normal entry
+	 point.  The value of entry_point was initialized to the alternate
+	 entry point (GEP).  It will be adjusted if the normal entry point
+	 (LEP) was used.  */
+       entry_point = gdbarch_skip_entrypoint (gdbarch, entry_point);
     }
-  else
+
+  if (alt_entry_point <= pc && pc <= entry_point)
     {
-      /* We are exactly at the function entry point.  Note that this
+      /* We are exactly at the function entry point, or between the entry
+	 point on platforms that have two (like PowerPC).  Note that this
 	 can only happen at frame #0.
 
 	 When setting a step range, need to call set_step_info
@@ -1746,8 +1749,17 @@ finish_backward (struct finish_command_fsm *sm)
 
       /* Return using a step range so we will keep stepping back
 	 to the first instruction in the source code line.  */
-      tp->control.step_range_start = sal.pc;
-      tp->control.step_range_end = sal.pc;
+      tp->control.step_range_start = alt_entry_point;
+      tp->control.step_range_end = entry_point;
+    }
+  else
+    {
+      symtab_and_line sr_sal;
+      /* Set a step-resume at the function's entry point.  */
+      sr_sal.pc = entry_point;
+      sr_sal.pspace = get_frame_program_space (frame);
+      insert_step_resume_breakpoint_at_sal (gdbarch,
+					    sr_sal, null_frame_id);
     }
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 86e5ef1ed12..b69f84824a3 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1868,6 +1868,7 @@ struct execution_control_state
 
   struct target_waitstatus ws;
   int stop_func_filled_in = 0;
+  CORE_ADDR stop_func_alt_start = 0;
   CORE_ADDR stop_func_start = 0;
   CORE_ADDR stop_func_end = 0;
   const char *stop_func_name = nullptr;
@@ -4663,6 +4664,12 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 				    &block);
       ecs->stop_func_name = gsi == nullptr ? nullptr : gsi->print_name ();
 
+      /* PowerPC functions have a Local Entry Point and a Global Entry
+	 Point.  There is only one Entry Point (GEP = LEP) for other
+	 architectures.  Save the alternate entry point address (GEP) for
+	 use later.  */
+      ecs->stop_func_alt_start = ecs->stop_func_start;
+
       /* The call to find_pc_partial_function, above, will set
 	 stop_func_start and stop_func_end to the start and end
 	 of the range containing the stop pc.  If this range
@@ -4679,6 +4686,9 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 	    += gdbarch_deprecated_function_start_offset (gdbarch);
 
 	  if (gdbarch_skip_entrypoint_p (gdbarch))
+	    /* The PowerPC architecture uses two entry points.  Stop at the
+	       regular entry point (LEP on PowerPC) initially.  Will setup a
+	       breakpoint for the alternate entry point (GEP) later.  */
 	    ecs->stop_func_start
 	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
 	}
@@ -6754,7 +6764,7 @@ process_event_stop_test (struct execution_control_state *ecs)
 
 	  /* Return using a step range so we will keep stepping back to the
 	     first instruction in the source code line.  */
-	  tp->control.step_range_start = ecs->stop_func_start;
+	  tp->control.step_range_start = ecs->stop_func_alt_start;
 	  tp->control.step_range_end = ecs->stop_func_start;
 	  keep_going (ecs);
 	  return;
@@ -6891,8 +6901,10 @@ process_event_stop_test (struct execution_control_state *ecs)
 	 (unless it's the function entry point, in which case
 	 keep going back to the call point).  */
       CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
+
       if (stop_pc == ecs->event_thread->control.step_range_start
-	  && stop_pc != ecs->stop_func_start
+	  && (stop_pc < ecs->stop_func_alt_start
+	      || stop_pc > ecs->stop_func_start)
 	  && execution_direction == EXEC_REVERSE)
 	end_stepping_range (ecs);
       else
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
index f90ecbb93cb..6bac7c6117a 100644
--- a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -1,4 +1,4 @@
-/* This testcase is part of GDB, the GNU debugger.
+j/* This testcase is part of GDB, the GNU debugger.
 
    Copyright 2012-2023 Free Software Foundation, Inc.
 
@@ -24,11 +24,37 @@
    This test verifies the fix for gdb bugzilla:
 
    https://sourceware.org/bugzilla/show_bug.cgi?id=29927
-*/
+
+   PowerPC supports two entry points to a function.  The normal entry point
+   is called the local entry point (LEP).  The alternat entry point is called
+   the global entry point (GEP).  The GEP is only used if the table of
+   contents (TOC) value stored in register r2 needs to be setup prior to
+   execution starting at the LEP.  A function call via a function pointer
+   will entry via the GEP.  A normal function call will enter via the LEP.
+
+   This test has been expanded to include tests to verify the reverse-finish
+   command works properly if the function is called via the GEP.  The original
+   test only verified the reverse-finish command for a normal call that used
+   the LEP.  */
 
 int
 function1 (int a, int b)   // FUNCTION1
 {
+  /* The assembly code for this function when compiled for PowerPC is as
+     follows:
+
+     0000000010000758 <function1>:
+     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
+     1000075c:	00 7f 42 38 	addi    r2,r2,32512
+     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
+     10000764:	10 00 01 f8 	std     r0,16(r1)
+     ....
+
+     When the function is called on PowerPC with function1 (a, b) the call
+     enters at the Local Entry Point (LEP).  When the function is called via
+     a function pointer, the Global Entry Point (GEP) for function1 is used.
+     The GEP sets up register 2 before reaching the LEP.
+  */
   int ret = 0;
 
   ret = a + b;
@@ -39,10 +65,19 @@ int
 main(int argc, char* argv[])
 {
   int a, b;
+  int (*funp) (int, int) = &function1;
+
+  /* Call function via Local Entry Point (LEP).  */
 
   a = 1;
   b = 5;
 
-  function1 (a, b);   // CALL FUNCTION
+  function1 (a, b);   // CALL VIA LEP
+
+  /* Call function via Global Entry Point (GEP).  */
+  a = 10;
+  b = 50;
+
+  funp (a, b);        // CALL VIA GEP
   return 0;
 }
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
index 63305c109e1..240b7214ed2 100644
--- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -31,6 +31,16 @@
 # This test verifies the fix for gdb bugzilla:
 #   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
 
+# PowerPC supports two entry points to a function.  The normal entry point
+# is called the local entry point (LEP).  The alternat entry point is called
+# the global entry point (GEP).  A function call via a function pointer
+# will entry via the GEP.  A normal function call will enter via the LEP.
+#
+# This test has been expanded to include tests to verify the reverse-finish
+# command works properly if the function is called via the GEP.  The original
+# test only verified the reverse-finish command for a normal call that used
+# the LEP.
+
 if ![supports_reverse] {
     return
 }
@@ -50,30 +60,30 @@ if [supports_process_record] {
 }
 
 
-### TEST 1: reverse finish from the entry point instruction in
-### function1.
+### TEST 1: reverse finish from the entry point instruction (LEP) in
+### function1 when called using the normal entry point (LEP).
 
 # Set breakpoint at call to function1 in main.
-set bp_FUNCTION [gdb_get_line_number "CALL FUNCTION" $srcfile]
-gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
 
 # Continue to break point at function1 call in main.
 gdb_continue_to_breakpoint \
     "stopped at function1 entry point instruction to stepi into function" \
-    ".*$srcfile:$bp_FUNCTION\r\n.*"
+    ".*$srcfile:$bp_LEP_test\r\n.*"
 
 # stepi until we see "{" indicating we entered function1
-repeat_cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
+repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call"
 
-gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
-    "reverse-finish function1 "
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from LEP "
 
 # Check to make sure we stopped at the first instruction in the source code
 # line.  It should only take one reverse next command to get to the previous
 # source line.   If GDB stops at the last instruction in the source code line
 # it will take two reverse next instructions to get to the previous source
 # line.
-gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from LEP"
 
 # Clear the recorded log.
 gdb_test "record stop"  "Process record is stopped.*" \
@@ -84,21 +94,81 @@ gdb_test_no_output "record" "turn on process record for test2"
 ### TEST 2: reverse finish from the body of function1.
 
 # Set breakpoint at call to function1 in main.
-gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
 
 # Continue to break point at function1 call in main.
 gdb_continue_to_breakpoint \
     "at function1 entry point instruction to step to body of function" \
-    ".*$srcfile:$bp_FUNCTION\r\n.*"
+    ".*$srcfile:$bp_LEP_test\r\n.*"
 
 # do a step instruction to get to the body of the function
 gdb_test "step" ".*int ret = 0;.*" "step test 1"
 
-gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
-    "reverse-finish function1 call from function body"
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from function body"
 
 # Check to make sure we stopped at the first instruction in the source code
 # line.  It should only take one reverse next command to get to the previous
 # source line.
 gdb_test "reverse-next" ".*b = 5;.*" \
     "reverse next at b = 5, from function body"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test2"
+gdb_test_no_output "record" "turn on process record for test3"
+
+
+### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
+
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP"
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.  If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 50;.*" "reverse next at b = 50, call from GEP"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test3"
+gdb_test_no_output "record" "turn on process record for test4"
+
+
+### TEST 4: reverse finish from the body of function 1 when calling using the
+### alternate entrypoint (GEP).
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of function" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# Step into body of funp, called via GEP.
+gdb_test "step" ".*int ret = 0;.*" "step test 2"
+
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "reverse-finish function1 GEP call, from function body  "
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.  If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next at b = 50 from function body"
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-16 16:37                                                     ` [PATCH 1/2 " Carl Love
@ 2023-01-17 12:35                                                       ` Bruno Larsen
  2023-01-20  0:03                                                         ` [PATCH 1/2 version 3] " Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-01-17 12:35 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 16/01/2023 17:37, Carl Love wrote:
> GDB maintainers:
>
> Version 2: Addressed various comments from Bruno Larsen.
>
> This patch fixes the issues with the reverse-finish command on X86.
> The reverse-finish command now correctly stops at the first instruction
> in the source code line of the caller.  It now only requires a single
> reverse-step or reverse-next instruction to get back to the previous
> source code line.
>
> It also adds a new testcase, gdb.reverse/finish-reverse-next.exp, and
> updates several existing testcases.
>
> Version 2 patch changes have been re-verified on PowerPC and X86 with
> no regressions.
>
> Please let me know if you have any comments on the patch.  Thanks.
>
>                      Carl
>
> --------------------------------------------------------
> X86: reverse-finish fix
>
> PR record/29927  - reverse-finish requires two reverse next instructions to
> reach previous source line
>
> Currently on X86, when executing the finish command in reverse, gdb does a
> single step from the first instruction in the callee to get back to the
> caller.  GDB stops on the last instruction in the source code line where
> the call was made.  When stopped at the last instruction of the source code
> line, a reverse next or step command will stop at the first instruction
> of the same source code line thus requiring two step/next commands to
> reach the previous source code line.  It should only require one step/next
> command to reach the previous source code line.
>
> By contrast, a reverse next or step command from the first line in a
> function stops at the first instruction in the source code line where the
> call was made.
>
> This patch fixes the reverse finish command so it will stop at the first
> instruction of the source line where the function call was made.  The
> behavior on X86 for the reverse-finish command now matches doing a
> reverse-next from the beginning of the function.
>
> The proceed_to_finish flag in struct thread_control_state is no longer
> used.  This patch removes the declaration, initialization and setting of
> the flag.
>
> This patch requires a number of regression tests to be updated.  Test
> gdb.mi/mi-reverse.exp no longer needs to execute two steps to get to the
> previous line.  The gdb output for tests gdb.reverse/until-precsave.exp
> and gdb.reverse/until-reverse.exp changed slightly.  The expected result in
> tests gdb.reverse/amd64-failcall-reverse.exp and
> gdb.reverse/singlejmp-reverse.exp are updated to the correct expected
> result.
>
> This patch adds a new test gdb.reverse/finish-reverse-next.exp to test the
> reverse-finish command when returning from the entry point and from the
> body of the function.
>
> The step_until proceedure in test gdb.reverse/step-indirect-call-thunk.exp
> was moved to lib/gdb.exp and renamed cmd_until.
>
> The patch has been tested on X86 and PowerPC to verify no additional
> regression failures occured.
>
> Bug:https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> ---

Changes look good now and I also dont see any regressions.

Reviewed-By: Bruno Larsen <blarsen@redhat.com>

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-16 16:37                                                     ` [PATCH 2/2 version 2] " Carl Love
@ 2023-01-17 14:29                                                       ` Bruno Larsen
  2023-01-17 16:36                                                         ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-01-17 14:29 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 16/01/2023 17:37, Carl Love wrote:
> GDB maintainers:
>
> Version 2: Addressed various comments from Bruno Larsen.
>
> This patch fixes the issues with the reverse-finish command on
> PowerPC.  The reverse-finish command now correctly stops at the first
> instruction in the source code line of the caller.
>
> The patch adds tests for calling a function via the GEP to the new test
> gdb.reverse/finish-reverse-next.exp.
>
> Version 2 patch changes have been re-verified on PowerPC and X86 with
> no regressions.
>
> Please let me know if you have any comments on the patch.  Thanks.
>
>                      Carl
>
> ---------------------------------------------------------------
> PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
>
> PR record/29927 - reverse-finish requires two reverse next instructions to
> reach previous source line
>
> PowerPC uses two entry points called the local entry point (LEP) and the
> global entry point (GEP).  Normally the LEP is used when calling a
> function.  However, if the table of contents (TOC) value in register 2 is
> not valid the GEP is called to setup the TOC before execution continues at
> the LEP.  When executing in reverse, the function finish_backward sets the
> break point at the alternate entry point (GEP).  However if the forward
> execution enters via the normal entry point (LEP), the reverse execution
> never sees the break point at the GEP of the function.  Reverse execution
> continues until the next break point is encountered or the end of the
> recorded log is reached causing gdb to stop at the wrong place.
>
> This patch adds a new address to struct execution_control_state to hold the
> address of the alternate function start address, known as the GEP on
> PowerPC.  The finish_backwards function is updated.  If the stopping point
> is between the two entry points (the LEP and GEP on PowerPC), the stepping
> range is set to execute back to the alternate entry point (GEP on PowerPC).
> Otherwise, a breakpoint is inserted at the normal entry point (LEP on
> PowerPC).
>
> Function process_event_stop_test checks uses a stepping range to stop
> execution in the caller at the first instruction of the source code line.
> Note, on systems that only support one entry point, the address of the two
> entry points are the same.
>
> Test finish-reverse-next.exp is updated to include tests for the
> reverse-finish command when the function is entered via the normal entry
> point (i.e. the LEP) and the alternate entry point (i.e. the GEP).
>
> The patch has been tested on X86 and PowerPC with no regressions.

I will reiterate that I don't know much about PPC, so the best I can do 
is check for style and tests, but apart from a few minor nits inlined, 
it looks ok

Tested-By: Bruno Larsen <blarsen@redhat.com>

> ---
>   gdb/infcmd.c                                  | 40 +++++---
>   gdb/infrun.c                                  | 16 +++-
>   .../gdb.reverse/finish-reverse-next.c         | 41 +++++++-
>   .../gdb.reverse/finish-reverse-next.exp       | 96 ++++++++++++++++---
>   4 files changed, 161 insertions(+), 32 deletions(-)
>
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 9c42efeae8d..6aaed34b1b6 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1722,22 +1722,25 @@ finish_backward (struct finish_command_fsm *sm)
>     sal = find_pc_line (func_addr, 0);
>   
>     frame_info_ptr frame = get_selected_frame (nullptr);
> +  struct gdbarch *gdbarch = get_frame_arch (frame);
> +  CORE_ADDR alt_entry_point = sal.pc;
> +  CORE_ADDR entry_point = alt_entry_point;
>   
> -  if (sal.pc != pc)
> +  if (gdbarch_skip_entrypoint_p (gdbarch))
>       {
> -      struct gdbarch *gdbarch = get_frame_arch (frame);
> -
> -      /* Set a step-resume at the function's entry point.  Once that's
> -	 hit, we'll do one more step backwards.  */
> -      symtab_and_line sr_sal;
> -      sr_sal.pc = sal.pc;
> -      sr_sal.pspace = get_frame_program_space (frame);
> -      insert_step_resume_breakpoint_at_sal (gdbarch,
> -					    sr_sal, null_frame_id);
> +      /* Some architectures, like PowerPC use local and global entry points.
> +	 There is only one Entry Point (GEP = LEP) for other architectures.
> +	 The GEP is an alternate entry point.  The LEP is the normal entry
> +	 point.  The value of entry_point was initialized to the alternate
> +	 entry point (GEP).  It will be adjusted if the normal entry point
> +	 (LEP) was used.  */
> +       entry_point = gdbarch_skip_entrypoint (gdbarch, entry_point);
>       }
> -  else
> +
> +  if (alt_entry_point <= pc && pc <= entry_point)
>       {
> -      /* We are exactly at the function entry point.  Note that this
> +      /* We are exactly at the function entry point, or between the entry
> +	 point on platforms that have two (like PowerPC).  Note that this
>   	 can only happen at frame #0.
>   
>   	 When setting a step range, need to call set_step_info
> @@ -1746,8 +1749,17 @@ finish_backward (struct finish_command_fsm *sm)
>   
>         /* Return using a step range so we will keep stepping back
>   	 to the first instruction in the source code line.  */
> -      tp->control.step_range_start = sal.pc;
> -      tp->control.step_range_end = sal.pc;
> +      tp->control.step_range_start = alt_entry_point;
> +      tp->control.step_range_end = entry_point;
> +    }
> +  else
> +    {
> +      symtab_and_line sr_sal;
> +      /* Set a step-resume at the function's entry point.  */
> +      sr_sal.pc = entry_point;
> +      sr_sal.pspace = get_frame_program_space (frame);
> +      insert_step_resume_breakpoint_at_sal (gdbarch,
> +					    sr_sal, null_frame_id);
>       }
>     proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>   }
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 86e5ef1ed12..b69f84824a3 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -1868,6 +1868,7 @@ struct execution_control_state
>   
>     struct target_waitstatus ws;
>     int stop_func_filled_in = 0;
> +  CORE_ADDR stop_func_alt_start = 0;
>     CORE_ADDR stop_func_start = 0;
>     CORE_ADDR stop_func_end = 0;
>     const char *stop_func_name = nullptr;
> @@ -4663,6 +4664,12 @@ fill_in_stop_func (struct gdbarch *gdbarch,
>   				    &block);
>         ecs->stop_func_name = gsi == nullptr ? nullptr : gsi->print_name ();
>   
> +      /* PowerPC functions have a Local Entry Point and a Global Entry
> +	 Point.  There is only one Entry Point (GEP = LEP) for other
> +	 architectures.  Save the alternate entry point address (GEP) for
> +	 use later.  */
> +      ecs->stop_func_alt_start = ecs->stop_func_start;
> +
>         /* The call to find_pc_partial_function, above, will set
>   	 stop_func_start and stop_func_end to the start and end
>   	 of the range containing the stop pc.  If this range
> @@ -4679,6 +4686,9 @@ fill_in_stop_func (struct gdbarch *gdbarch,
>   	    += gdbarch_deprecated_function_start_offset (gdbarch);
>   
>   	  if (gdbarch_skip_entrypoint_p (gdbarch))
> +	    /* The PowerPC architecture uses two entry points.  Stop at the
> +	       regular entry point (LEP on PowerPC) initially.  Will setup a
> +	       breakpoint for the alternate entry point (GEP) later.  */
>   	    ecs->stop_func_start
>   	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
>   	}
> @@ -6754,7 +6764,7 @@ process_event_stop_test (struct execution_control_state *ecs)
>   
>   	  /* Return using a step range so we will keep stepping back to the
>   	     first instruction in the source code line.  */
> -	  tp->control.step_range_start = ecs->stop_func_start;
> +	  tp->control.step_range_start = ecs->stop_func_alt_start;
>   	  tp->control.step_range_end = ecs->stop_func_start;
>   	  keep_going (ecs);
>   	  return;
> @@ -6891,8 +6901,10 @@ process_event_stop_test (struct execution_control_state *ecs)
>   	 (unless it's the function entry point, in which case
>   	 keep going back to the call point).  */
>         CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
> +
>         if (stop_pc == ecs->event_thread->control.step_range_start
> -	  && stop_pc != ecs->stop_func_start
> +	  && (stop_pc < ecs->stop_func_alt_start
> +	      || stop_pc > ecs->stop_func_start)
>   	  && execution_direction == EXEC_REVERSE)
>   	end_stepping_range (ecs);
>         else
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> index f90ecbb93cb..6bac7c6117a 100644
> --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> @@ -1,4 +1,4 @@
> -/* This testcase is part of GDB, the GNU debugger.
> +j/* This testcase is part of GDB, the GNU debugger.
Accidental change that breaks the test here.
>   
>      Copyright 2012-2023 Free Software Foundation, Inc.
>   
> @@ -24,11 +24,37 @@
>      This test verifies the fix for gdb bugzilla:
>   
>      https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> -*/
> +
> +   PowerPC supports two entry points to a function.  The normal entry point
> +   is called the local entry point (LEP).  The alternat entry point is called
> +   the global entry point (GEP).  The GEP is only used if the table of
> +   contents (TOC) value stored in register r2 needs to be setup prior to
> +   execution starting at the LEP.  A function call via a function pointer
> +   will entry via the GEP.  A normal function call will enter via the LEP.
> +
> +   This test has been expanded to include tests to verify the reverse-finish
> +   command works properly if the function is called via the GEP.  The original
> +   test only verified the reverse-finish command for a normal call that used
> +   the LEP.  */
>   
>   int
>   function1 (int a, int b)   // FUNCTION1
>   {
> +  /* The assembly code for this function when compiled for PowerPC is as
> +     follows:
> +
> +     0000000010000758 <function1>:
> +     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
> +     1000075c:	00 7f 42 38 	addi    r2,r2,32512
> +     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
> +     10000764:	10 00 01 f8 	std     r0,16(r1)
> +     ....
> +
> +     When the function is called on PowerPC with function1 (a, b) the call
> +     enters at the Local Entry Point (LEP).  When the function is called via
> +     a function pointer, the Global Entry Point (GEP) for function1 is used.
> +     The GEP sets up register 2 before reaching the LEP.
> +  */
>     int ret = 0;
>   
>     ret = a + b;
> @@ -39,10 +65,19 @@ int
>   main(int argc, char* argv[])
>   {
>     int a, b;
> +  int (*funp) (int, int) = &function1;
> +
> +  /* Call function via Local Entry Point (LEP).  */
>   
>     a = 1;
>     b = 5;
>   
> -  function1 (a, b);   // CALL FUNCTION
> +  function1 (a, b);   // CALL VIA LEP
> +
> +  /* Call function via Global Entry Point (GEP).  */
> +  a = 10;
> +  b = 50;
> +
> +  funp (a, b);        // CALL VIA GEP
>     return 0;
>   }
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> index 63305c109e1..240b7214ed2 100644
> --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> @@ -31,6 +31,16 @@
>   # This test verifies the fix for gdb bugzilla:
>   #   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
>   
> +# PowerPC supports two entry points to a function.  The normal entry point
> +# is called the local entry point (LEP).  The alternat entry point is called
> +# the global entry point (GEP).  A function call via a function pointer
> +# will entry via the GEP.  A normal function call will enter via the LEP.
> +#
> +# This test has been expanded to include tests to verify the reverse-finish
> +# command works properly if the function is called via the GEP.  The original
> +# test only verified the reverse-finish command for a normal call that used
> +# the LEP.
> +
>   if ![supports_reverse] {
>       return
>   }
> @@ -50,30 +60,30 @@ if [supports_process_record] {
>   }
>   
>   
> -### TEST 1: reverse finish from the entry point instruction in
> -### function1.
> +### TEST 1: reverse finish from the entry point instruction (LEP) in
> +### function1 when called using the normal entry point (LEP).
>   
>   # Set breakpoint at call to function1 in main.
> -set bp_FUNCTION [gdb_get_line_number "CALL FUNCTION" $srcfile]
> -gdb_breakpoint $srcfile:$bp_FUNCTION temporary
> +set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
>   
>   # Continue to break point at function1 call in main.
>   gdb_continue_to_breakpoint \
>       "stopped at function1 entry point instruction to stepi into function" \
> -    ".*$srcfile:$bp_FUNCTION\r\n.*"
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
>   
>   # stepi until we see "{" indicating we entered function1
> -repeat_cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
> +repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call"
>   
> -gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
> -    "reverse-finish function1 "
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +    "reverse-finish function1 LEP call from LEP "
>   
>   # Check to make sure we stopped at the first instruction in the source code
>   # line.  It should only take one reverse next command to get to the previous
>   # source line.   If GDB stops at the last instruction in the source code line
>   # it will take two reverse next instructions to get to the previous source
>   # line.
> -gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
> +gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from LEP"
>   
>   # Clear the recorded log.
>   gdb_test "record stop"  "Process record is stopped.*" \
> @@ -84,21 +94,81 @@ gdb_test_no_output "record" "turn on process record for test2"
>   ### TEST 2: reverse finish from the body of function1.
>   
>   # Set breakpoint at call to function1 in main.
> -gdb_breakpoint $srcfile:$bp_FUNCTION temporary
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
>   
>   # Continue to break point at function1 call in main.
>   gdb_continue_to_breakpoint \
>       "at function1 entry point instruction to step to body of function" \
> -    ".*$srcfile:$bp_FUNCTION\r\n.*"
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
duplicate test name here.
>   
>   # do a step instruction to get to the body of the function
>   gdb_test "step" ".*int ret = 0;.*" "step test 1"
>   
> -gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
> -    "reverse-finish function1 call from function body"
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +    "reverse-finish function1 LEP call from function body"
>   
>   # Check to make sure we stopped at the first instruction in the source code
>   # line.  It should only take one reverse next command to get to the previous
>   # source line.
>   gdb_test "reverse-next" ".*b = 5;.*" \
>       "reverse next at b = 5, from function body"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test2"
> +gdb_test_no_output "record" "turn on process record for test3"
> +
> +
> +### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
> +### function1 when called using the alternate entry point (GEP).
> +
> +# Set breakpoint at call to funp in main.
> +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into function" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
Duplicated test name here too.
> +
> +# stepi until we see "{" indicating we entered function.
> +cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"

s/cmd_until/repeat_cmd_until

you probably missed because of the test compilation failed.

> +
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "function1 GEP call call from GEP"
> +
> +# Check to make sure we stopped at the first instruction in the source code
> +# line.  It should only take one reverse next command to get to the previous
> +# source line.  If GDB stops at the last instruction in the source code line
> +# it will take two reverse next instructions to get to the previous source
> +# line.
> +gdb_test "reverse-next" ".*b = 50;.*" "reverse next at b = 50, call from GEP"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test3"
> +gdb_test_no_output "record" "turn on process record for test4"
> +
> +
> +### TEST 4: reverse finish from the body of function 1 when calling using the
> +### alternate entrypoint (GEP).
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call.
> +gdb_continue_to_breakpoint \
> +    "at function1 entry point instruction to step to body of function" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# Step into body of funp, called via GEP.
> +gdb_test "step" ".*int ret = 0;.*" "step test 2"
> +
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "reverse-finish function1 GEP call, from function body  "
> +
> +# Check to make sure we stopped at the first instruction in the source code
> +# line.  It should only take one reverse next command to get to the previous
> +# source line.  If GDB stops at the last instruction in the source code line
> +# it will take two reverse next instructions to get to the previous source
> +# line.
> +gdb_test "reverse-next" ".*b = 50;.*" \
> +    "reverse next at b = 50 from function body"


-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-17 14:29                                                       ` Bruno Larsen
@ 2023-01-17 16:36                                                         ` Carl Love
  2023-01-17 16:55                                                           ` Tom de Vries
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-17 16:36 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

Bruno:

On Tue, 2023-01-17 at 15:29 +0100, Bruno Larsen wrote:
> On 16/01/2023 17:37, Carl Love wrote:
> > GDB maintainers:
> > 
> > Version 2: Addressed various comments from Bruno Larsen.
> > 
> > This patch fixes the issues with the reverse-finish command on
> > PowerPC.  The reverse-finish command now correctly stops at the
> > first
> > instruction in the source code line of the caller.
> > 
> > The patch adds tests for calling a function via the GEP to the new
> > test
> > gdb.reverse/finish-reverse-next.exp.
> > 
> > Version 2 patch changes have been re-verified on PowerPC and X86
> > with
> > no regressions.
> > 
> > Please let me know if you have any comments on the patch.  Thanks.
> > 
> >                      Carl
> > 
> > ---------------------------------------------------------------
> > PowerPC: fix for gdb.reverse/finish-precsave.exp and
> > gdb.reverse/finish-reverse.exp
> > 
> > PR record/29927 - reverse-finish requires two reverse next
> > instructions to
> > reach previous source line
> > 
> > PowerPC uses two entry points called the local entry point (LEP)
> > and the
> > global entry point (GEP).  Normally the LEP is used when calling a
> > function.  However, if the table of contents (TOC) value in
> > register 2 is
> > not valid the GEP is called to setup the TOC before execution
> > continues at
> > the LEP.  When executing in reverse, the function finish_backward
> > sets the
> > break point at the alternate entry point (GEP).  However if the
> > forward
> > execution enters via the normal entry point (LEP), the reverse
> > execution
> > never sees the break point at the GEP of the function.  Reverse
> > execution
> > continues until the next break point is encountered or the end of
> > the
> > recorded log is reached causing gdb to stop at the wrong place.
> > 
> > This patch adds a new address to struct execution_control_state to
> > hold the
> > address of the alternate function start address, known as the GEP
> > on
> > PowerPC.  The finish_backwards function is updated.  If the
> > stopping point
> > is between the two entry points (the LEP and GEP on PowerPC), the
> > stepping
> > range is set to execute back to the alternate entry point (GEP on
> > PowerPC).
> > Otherwise, a breakpoint is inserted at the normal entry point (LEP
> > on
> > PowerPC).
> > 
> > Function process_event_stop_test checks uses a stepping range to
> > stop
> > execution in the caller at the first instruction of the source code
> > line.
> > Note, on systems that only support one entry point, the address of
> > the two
> > entry points are the same.
> > 
> > Test finish-reverse-next.exp is updated to include tests for the
> > reverse-finish command when the function is entered via the normal
> > entry
> > point (i.e. the LEP) and the alternate entry point (i.e. the GEP).
> > 
> > The patch has been tested on X86 and PowerPC with no regressions.
> 
> I will reiterate that I don't know much about PPC, so the best I can
> do 
> is check for style and tests, but apart from a few minor nits
> inlined, 
> it looks ok

I fixed the issues, as noted below.  I did a careful review of the log
files to make sure there are no remaining duplicates and that each of
the tests in both patches ran as expected.

Thanks for your help on these patches.

                       Carl 
> 
> Tested-By: Bruno Larsen <blarsen@redhat.com>
> 
> > ---
> >   gdb/infcmd.c                                  | 40 +++++---
> >   gdb/infrun.c                                  | 16 +++-
> >   .../gdb.reverse/finish-reverse-next.c         | 41 +++++++-
> >   .../gdb.reverse/finish-reverse-next.exp       | 96
> > ++++++++++++++++---
> >   4 files changed, 161 insertions(+), 32 deletions(-)
> > 
> > diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> > index 9c42efeae8d..6aaed34b1b6 100644
> > --- a/gdb/infcmd.c
> > +++ b/gdb/infcmd.c
> > @@ -1722,22 +1722,25 @@ finish_backward (struct finish_command_fsm
> > *sm)
> >     sal = find_pc_line (func_addr, 0);
> >   
> >     frame_info_ptr frame = get_selected_frame (nullptr);
> > +  struct gdbarch *gdbarch = get_frame_arch (frame);
> > +  CORE_ADDR alt_entry_point = sal.pc;
> > +  CORE_ADDR entry_point = alt_entry_point;
> >   
> > -  if (sal.pc != pc)
> > +  if (gdbarch_skip_entrypoint_p (gdbarch))
> >       {
> > -      struct gdbarch *gdbarch = get_frame_arch (frame);
> > -
> > -      /* Set a step-resume at the function's entry point.  Once
> > that's
> > -	 hit, we'll do one more step backwards.  */
> > -      symtab_and_line sr_sal;
> > -      sr_sal.pc = sal.pc;
> > -      sr_sal.pspace = get_frame_program_space (frame);
> > -      insert_step_resume_breakpoint_at_sal (gdbarch,
> > -					    sr_sal, null_frame_id);
> > +      /* Some architectures, like PowerPC use local and global
> > entry points.
> > +	 There is only one Entry Point (GEP = LEP) for other
> > architectures.
> > +	 The GEP is an alternate entry point.  The LEP is the normal
> > entry
> > +	 point.  The value of entry_point was initialized to the
> > alternate
> > +	 entry point (GEP).  It will be adjusted if the normal entry
> > point
> > +	 (LEP) was used.  */
> > +       entry_point = gdbarch_skip_entrypoint (gdbarch,
> > entry_point);
> >       }
> > -  else
> > +
> > +  if (alt_entry_point <= pc && pc <= entry_point)
> >       {
> > -      /* We are exactly at the function entry point.  Note that
> > this
> > +      /* We are exactly at the function entry point, or between
> > the entry
> > +	 point on platforms that have two (like PowerPC).  Note that
> > this
> >   	 can only happen at frame #0.
> >   
> >   	 When setting a step range, need to call set_step_info
> > @@ -1746,8 +1749,17 @@ finish_backward (struct finish_command_fsm
> > *sm)
> >   
> >         /* Return using a step range so we will keep stepping back
> >   	 to the first instruction in the source code line.  */
> > -      tp->control.step_range_start = sal.pc;
> > -      tp->control.step_range_end = sal.pc;
> > +      tp->control.step_range_start = alt_entry_point;
> > +      tp->control.step_range_end = entry_point;
> > +    }
> > +  else
> > +    {
> > +      symtab_and_line sr_sal;
> > +      /* Set a step-resume at the function's entry point.  */
> > +      sr_sal.pc = entry_point;
> > +      sr_sal.pspace = get_frame_program_space (frame);
> > +      insert_step_resume_breakpoint_at_sal (gdbarch,
> > +					    sr_sal, null_frame_id);
> >       }
> >     proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> >   }
> > diff --git a/gdb/infrun.c b/gdb/infrun.c
> > index 86e5ef1ed12..b69f84824a3 100644
> > --- a/gdb/infrun.c
> > +++ b/gdb/infrun.c
> > @@ -1868,6 +1868,7 @@ struct execution_control_state
> >   
> >     struct target_waitstatus ws;
> >     int stop_func_filled_in = 0;
> > +  CORE_ADDR stop_func_alt_start = 0;
> >     CORE_ADDR stop_func_start = 0;
> >     CORE_ADDR stop_func_end = 0;
> >     const char *stop_func_name = nullptr;
> > @@ -4663,6 +4664,12 @@ fill_in_stop_func (struct gdbarch *gdbarch,
> >   				    &block);
> >         ecs->stop_func_name = gsi == nullptr ? nullptr : gsi-
> > >print_name ();
> >   
> > +      /* PowerPC functions have a Local Entry Point and a Global
> > Entry
> > +	 Point.  There is only one Entry Point (GEP = LEP) for other
> > +	 architectures.  Save the alternate entry point address (GEP)
> > for
> > +	 use later.  */
> > +      ecs->stop_func_alt_start = ecs->stop_func_start;
> > +
> >         /* The call to find_pc_partial_function, above, will set
> >   	 stop_func_start and stop_func_end to the start and end
> >   	 of the range containing the stop pc.  If this range
> > @@ -4679,6 +4686,9 @@ fill_in_stop_func (struct gdbarch *gdbarch,
> >   	    += gdbarch_deprecated_function_start_offset (gdbarch);
> >   
> >   	  if (gdbarch_skip_entrypoint_p (gdbarch))
> > +	    /* The PowerPC architecture uses two entry points.  Stop at
> > the
> > +	       regular entry point (LEP on PowerPC) initially.  Will
> > setup a
> > +	       breakpoint for the alternate entry point (GEP)
> > later.  */
> >   	    ecs->stop_func_start
> >   	      = gdbarch_skip_entrypoint (gdbarch, ecs-
> > >stop_func_start);
> >   	}
> > @@ -6754,7 +6764,7 @@ process_event_stop_test (struct
> > execution_control_state *ecs)
> >   
> >   	  /* Return using a step range so we will keep stepping back to
> > the
> >   	     first instruction in the source code line.  */
> > -	  tp->control.step_range_start = ecs->stop_func_start;
> > +	  tp->control.step_range_start = ecs->stop_func_alt_start;
> >   	  tp->control.step_range_end = ecs->stop_func_start;
> >   	  keep_going (ecs);
> >   	  return;
> > @@ -6891,8 +6901,10 @@ process_event_stop_test (struct
> > execution_control_state *ecs)
> >   	 (unless it's the function entry point, in which case
> >   	 keep going back to the call point).  */
> >         CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
> > +
> >         if (stop_pc == ecs->event_thread->control.step_range_start
> > -	  && stop_pc != ecs->stop_func_start
> > +	  && (stop_pc < ecs->stop_func_alt_start
> > +	      || stop_pc > ecs->stop_func_start)
> >   	  && execution_direction == EXEC_REVERSE)
> >   	end_stepping_range (ecs);
> >         else
> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > index f90ecbb93cb..6bac7c6117a 100644
> > --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > @@ -1,4 +1,4 @@
> > -/* This testcase is part of GDB, the GNU debugger.
> > +j/* This testcase is part of GDB, the GNU debugger.
> Accidental change that breaks the test here.

Fixed.

> >   
> >      Copyright 2012-2023 Free Software Foundation, Inc.
> >   
> > @@ -24,11 +24,37 @@
> >      This test verifies the fix for gdb bugzilla:
> >   
> >      
> > https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> >  
> > -*/
> > +
> > +   PowerPC supports two entry points to a function.  The normal
> > entry point
> > +   is called the local entry point (LEP).  The alternat entry
> > point is called
> > +   the global entry point (GEP).  The GEP is only used if the
> > table of
> > +   contents (TOC) value stored in register r2 needs to be setup
> > prior to
> > +   execution starting at the LEP.  A function call via a function
> > pointer
> > +   will entry via the GEP.  A normal function call will enter via
> > the LEP.
> > +
> > +   This test has been expanded to include tests to verify the
> > reverse-finish
> > +   command works properly if the function is called via the
> > GEP.  The original
> > +   test only verified the reverse-finish command for a normal call
> > that used
> > +   the LEP.  */
> >   
> >   int
> >   function1 (int a, int b)   // FUNCTION1
> >   {
> > +  /* The assembly code for this function when compiled for PowerPC
> > is as
> > +     follows:
> > +
> > +     0000000010000758 <function1>:
> > +     10000758:	02 10 40 3c 	lis     r2,4098        <-
> > GEP
> > +     1000075c:	00 7f 42 38 	addi    r2,r2,32512
> > +     10000760:	a6 02 08 7c 	mflr    r0             <-
> > LEP
> > +     10000764:	10 00 01 f8 	std     r0,16(r1)
> > +     ....
> > +
> > +     When the function is called on PowerPC with function1 (a, b)
> > the call
> > +     enters at the Local Entry Point (LEP).  When the function is
> > called via
> > +     a function pointer, the Global Entry Point (GEP) for
> > function1 is used.
> > +     The GEP sets up register 2 before reaching the LEP.
> > +  */
> >     int ret = 0;
> >   
> >     ret = a + b;
> > @@ -39,10 +65,19 @@ int
> >   main(int argc, char* argv[])
> >   {
> >     int a, b;
> > +  int (*funp) (int, int) = &function1;
> > +
> > +  /* Call function via Local Entry Point (LEP).  */
> >   
> >     a = 1;
> >     b = 5;
> >   
> > -  function1 (a, b);   // CALL FUNCTION
> > +  function1 (a, b);   // CALL VIA LEP
> > +
> > +  /* Call function via Global Entry Point (GEP).  */
> > +  a = 10;
> > +  b = 50;
> > +
> > +  funp (a, b);        // CALL VIA GEP
> >     return 0;
> >   }
> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > index 63305c109e1..240b7214ed2 100644
> > --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > @@ -31,6 +31,16 @@
> >   # This test verifies the fix for gdb bugzilla:
> >   #   
> > https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> >  
> >   
> > +# PowerPC supports two entry points to a function.  The normal
> > entry point
> > +# is called the local entry point (LEP).  The alternat entry point
> > is called
> > +# the global entry point (GEP).  A function call via a function
> > pointer
> > +# will entry via the GEP.  A normal function call will enter via
> > the LEP.
> > +#
> > +# This test has been expanded to include tests to verify the
> > reverse-finish
> > +# command works properly if the function is called via the
> > GEP.  The original
> > +# test only verified the reverse-finish command for a normal call
> > that used
> > +# the LEP.
> > +
> >   if ![supports_reverse] {
> >       return
> >   }
> > @@ -50,30 +60,30 @@ if [supports_process_record] {
> >   }
> >   
> >   
> > -### TEST 1: reverse finish from the entry point instruction in
> > -### function1.
> > +### TEST 1: reverse finish from the entry point instruction (LEP)
> > in
> > +### function1 when called using the normal entry point (LEP).
> >   
> >   # Set breakpoint at call to function1 in main.
> > -set bp_FUNCTION [gdb_get_line_number "CALL FUNCTION" $srcfile]
> > -gdb_breakpoint $srcfile:$bp_FUNCTION temporary
> > +set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
> > +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> >   
> >   # Continue to break point at function1 call in main.
> >   gdb_continue_to_breakpoint \
> >       "stopped at function1 entry point instruction to stepi into
> > function" \
> > -    ".*$srcfile:$bp_FUNCTION\r\n.*"
> > +    ".*$srcfile:$bp_LEP_test\r\n.*"
> >   
> >   # stepi until we see "{" indicating we entered function1
> > -repeat_cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1
> > call"
> > +repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1
> > call"
> >   
> > -gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL
> > FUNCTION.*" \
> > -    "reverse-finish function1 "
> > +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA
> > LEP.*" \
> > +    "reverse-finish function1 LEP call from LEP "
> >   
> >   # Check to make sure we stopped at the first instruction in the
> > source code
> >   # line.  It should only take one reverse next command to get to
> > the previous
> >   # source line.   If GDB stops at the last instruction in the
> > source code line
> >   # it will take two reverse next instructions to get to the
> > previous source
> >   # line.
> > -gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call
> > from function"
> > +gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call
> > from LEP"
> >   
> >   # Clear the recorded log.
> >   gdb_test "record stop"  "Process record is stopped.*" \
> > @@ -84,21 +94,81 @@ gdb_test_no_output "record" "turn on process
> > record for test2"
> >   ### TEST 2: reverse finish from the body of function1.
> >   
> >   # Set breakpoint at call to function1 in main.
> > -gdb_breakpoint $srcfile:$bp_FUNCTION temporary
> > +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> >   
> >   # Continue to break point at function1 call in main.
> >   gdb_continue_to_breakpoint \
> >       "at function1 entry point instruction to step to body of
> > function" \
> > -    ".*$srcfile:$bp_FUNCTION\r\n.*"
> > +    ".*$srcfile:$bp_LEP_test\r\n.*"
> duplicate test name here.

fixed

> >   
> >   # do a step instruction to get to the body of the function
> >   gdb_test "step" ".*int ret = 0;.*" "step test 1"
> >   
> > -gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL
> > FUNCTION.*" \
> > -    "reverse-finish function1 call from function body"
> > +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA
> > LEP.*" \
> > +    "reverse-finish function1 LEP call from function body"
> >   
> >   # Check to make sure we stopped at the first instruction in the
> > source code
> >   # line.  It should only take one reverse next command to get to
> > the previous
> >   # source line.
> >   gdb_test "reverse-next" ".*b = 5;.*" \
> >       "reverse next at b = 5, from function body"
> > +
> > +# Turn off record to clear logs and turn on again
> > +gdb_test "record stop"  "Process record is stopped.*" \
> > +    "turn off process record for test2"
> > +gdb_test_no_output "record" "turn on process record for test3"
> > +
> > +
> > +### TEST 3: reverse finish from the alternate entry point
> > instruction (GEP) in
> > +### function1 when called using the alternate entry point (GEP).
> > +
> > +# Set breakpoint at call to funp in main.
> > +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> > +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> > +
> > +# Continue to break point at funp call in main.
> > +gdb_continue_to_breakpoint \
> > +    "stopped at function1 entry point instruction to stepi into
> > function" \
> > +    ".*$srcfile:$bp_GEP_test\r\n.*"
> Duplicated test name here too.

Fixed

> > +
> > +# stepi until we see "{" indicating we entered function.
> > +cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
> 
> s/cmd_until/repeat_cmd_until
> 
> you probably missed because of the test compilation failed.

Fixed.  Yup, I always try to go read the log file for that reason.  I
have been burned in the past thinking it worked when it didn't actually
run.

> 
> > +
> > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> > +    "function1 GEP call call from GEP"
> > +
> > +# Check to make sure we stopped at the first instruction in the
> > source code
> > +# line.  It should only take one reverse next command to get to
> > the previous
> > +# source line.  If GDB stops at the last instruction in the source
> > code line
> > +# it will take two reverse next instructions to get to the
> > previous source
> > +# line.
> > +gdb_test "reverse-next" ".*b = 50;.*" "reverse next at b = 50,
> > call from GEP"
> > +
> > +# Turn off record to clear logs and turn on again
> > +gdb_test "record stop"  "Process record is stopped.*" \
> > +    "turn off process record for test3"
> > +gdb_test_no_output "record" "turn on process record for test4"
> > +
> > +
> > +### TEST 4: reverse finish from the body of function 1 when
> > calling using the
> > +### alternate entrypoint (GEP).
> > +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> > +
> > +# Continue to break point at funp call.
> > +gdb_continue_to_breakpoint \
> > +    "at function1 entry point instruction to step to body of
> > function" \
> > +    ".*$srcfile:$bp_GEP_test\r\n.*"
> > +
> > +# Step into body of funp, called via GEP.
> > +gdb_test "step" ".*int ret = 0;.*" "step test 2"
> > +
> > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> > +    "reverse-finish function1 GEP call, from function body  "
> > +
> > +# Check to make sure we stopped at the first instruction in the
> > source code
> > +# line.  It should only take one reverse next command to get to
> > the previous
> > +# source line.  If GDB stops at the last instruction in the source
> > code line
> > +# it will take two reverse next instructions to get to the
> > previous source
> > +# line.
> > +gdb_test "reverse-next" ".*b = 50;.*" \
> > +    "reverse next at b = 50 from function body"
> 
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-17 16:36                                                         ` Carl Love
@ 2023-01-17 16:55                                                           ` Tom de Vries
  2023-01-17 17:03                                                             ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Tom de Vries @ 2023-01-17 16:55 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches

AFAICT, this has been committed just now.

I'm having difficulty finding an approval, did it happen maybe offlist?

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-17 16:55                                                           ` Tom de Vries
@ 2023-01-17 17:03                                                             ` Carl Love
  2023-01-17 17:14                                                               ` Tom de Vries
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-17 17:03 UTC (permalink / raw)
  To: Tom de Vries, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

Tom:

On Tue, 2023-01-17 at 17:55 +0100, Tom de Vries wrote:
> AFAICT, this has been committed just now.
> 
> I'm having difficulty finding an approval, did it happen maybe
> offlist?
> 
> Thanks,
> - Tom

I just committed it based on Bruno's reply.

   > The patch has been tested on X86 and PowerPC with no regressions.

   I will reiterate that I don't know much about PPC, so the best I can do 
   is check for style and tests, but apart from a few minor nits inlined, 
   it looks ok

   Tested-By: Bruno Larsen <blarsen@redhat.com>

I thought that was an approval to commit.  Is it not?

                       Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-17 17:03                                                             ` Carl Love
@ 2023-01-17 17:14                                                               ` Tom de Vries
  2023-01-17 19:31                                                                 ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Tom de Vries @ 2023-01-17 17:14 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches

On 1/17/23 18:03, Carl Love wrote:
> Tom:
> 
> On Tue, 2023-01-17 at 17:55 +0100, Tom de Vries wrote:
>> AFAICT, this has been committed just now.
>>
>> I'm having difficulty finding an approval, did it happen maybe
>> offlist?
>>
>> Thanks,
>> - Tom
> 
> I just committed it based on Bruno's reply.
> 
>     > The patch has been tested on X86 and PowerPC with no regressions.
> 
>     I will reiterate that I don't know much about PPC, so the best I can do
>     is check for style and tests, but apart from a few minor nits inlined,
>     it looks ok
> 
>     Tested-By: Bruno Larsen <blarsen@redhat.com>
> 
> I thought that was an approval to commit.  Is it not?

Hi Carl,

sorry, AFAIU it's not.  Bruno has been helpfully reviewing your patch, 
but AFAIK he cannot approve it.

This is an easy mistake to make though, given the used formulation, it's 
not the first time it happened, and it's one of the reasons we're trying 
to move towards replying with the Approved-By tag to make approval more 
formal, explicit and unambiguous.

FYI, I'm working my way toward reviewing these patches, and have 
regained access to my usual powerpc machine, so I'll try to reproduce 
the issue you're seeing.

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-17 17:14                                                               ` Tom de Vries
@ 2023-01-17 19:31                                                                 ` Carl Love
  2023-01-18 10:55                                                                   ` Tom de Vries
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-17 19:31 UTC (permalink / raw)
  To: Tom de Vries, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

Tom:

On Tue, 2023-01-17 at 18:14 +0100, Tom de Vries wrote:
> On 1/17/23 18:03, Carl Love wrote:
> > Tom:
> > 
> > On Tue, 2023-01-17 at 17:55 +0100, Tom de Vries wrote:
> > > AFAICT, this has been committed just now.
> > > 
> > > I'm having difficulty finding an approval, did it happen maybe
> > > offlist?
> > > 
> > > Thanks,
> > > - Tom
> > 
> > I just committed it based on Bruno's reply.
> > 
> >     > The patch has been tested on X86 and PowerPC with no
> > regressions.
> > 
> >     I will reiterate that I don't know much about PPC, so the best
> > I can do
> >     is check for style and tests, but apart from a few minor nits
> > inlined,
> >     it looks ok
> > 
> >     Tested-By: Bruno Larsen <blarsen@redhat.com>
> > 
> > I thought that was an approval to commit.  Is it not?
> 
> Hi Carl,
> 
> sorry, AFAIU it's not.  Bruno has been helpfully reviewing your
> patch, 
> but AFAIK he cannot approve it.
> 
> This is an easy mistake to make though, given the used formulation,
> it's 
> not the first time it happened, and it's one of the reasons we're
> trying 
> to move towards replying with the Approved-By tag to make approval
> more 
> formal, explicit and unambiguous.
> 
> FYI, I'm working my way toward reviewing these patches, and have 
> regained access to my usual powerpc machine, so I'll try to
> reproduce 
> the issue you're seeing.

OK, thanks for the clarification on the process.  In the past, I have
had people explicitly state in their reply that they could not approve
a patch but were just reviewing and commenting on it.  

I will be sure to look for the "Approved-By tag" in the future.  Sorry
for the mistake.

Please let me know if you need me to revert the patch, make some fixes,
or?  

Thanks. 

                     Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-17 19:31                                                                 ` Carl Love
@ 2023-01-18 10:55                                                                   ` Tom de Vries
  2023-01-18 16:16                                                                     ` Carl Love
  2023-01-18 22:26                                                                     ` Carl Love
  0 siblings, 2 replies; 105+ messages in thread
From: Tom de Vries @ 2023-01-18 10:55 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches

On 1/17/23 20:31, Carl Love wrote:
> Tom:
> 
> On Tue, 2023-01-17 at 18:14 +0100, Tom de Vries wrote:
>> On 1/17/23 18:03, Carl Love wrote:
>>> Tom:
>>>
>>> On Tue, 2023-01-17 at 17:55 +0100, Tom de Vries wrote:
>>>> AFAICT, this has been committed just now.
>>>>
>>>> I'm having difficulty finding an approval, did it happen maybe
>>>> offlist?
>>>>
>>>> Thanks,
>>>> - Tom
>>>
>>> I just committed it based on Bruno's reply.
>>>
>>>      > The patch has been tested on X86 and PowerPC with no
>>> regressions.
>>>
>>>      I will reiterate that I don't know much about PPC, so the best
>>> I can do
>>>      is check for style and tests, but apart from a few minor nits
>>> inlined,
>>>      it looks ok
>>>
>>>      Tested-By: Bruno Larsen <blarsen@redhat.com>
>>>
>>> I thought that was an approval to commit.  Is it not?
>>
>> Hi Carl,
>>
>> sorry, AFAIU it's not.  Bruno has been helpfully reviewing your
>> patch,
>> but AFAIK he cannot approve it.
>>
>> This is an easy mistake to make though, given the used formulation,
>> it's
>> not the first time it happened, and it's one of the reasons we're
>> trying
>> to move towards replying with the Approved-By tag to make approval
>> more
>> formal, explicit and unambiguous.
>>
>> FYI, I'm working my way toward reviewing these patches, and have
>> regained access to my usual powerpc machine, so I'll try to
>> reproduce
>> the issue you're seeing.
> 
> OK, thanks for the clarification on the process.  In the past, I have
> had people explicitly state in their reply that they could not approve
> a patch but were just reviewing and commenting on it.
> 
> I will be sure to look for the "Approved-By tag" in the future.  Sorry
> for the mistake.
> 
> Please let me know if you need me to revert the patch, make some fixes,
> or?

I've run into regressions due to the first patch:
...
FAIL: gdb.btrace/rn-dl-bind.exp: test: reverse-next
FAIL: gdb.btrace/tailcall.exp: reverse-next.1
FAIL: gdb.btrace/tailcall.exp: step.1
...

So, please revert both.

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-18 10:55                                                                   ` Tom de Vries
@ 2023-01-18 16:16                                                                     ` Carl Love
  2023-01-18 22:26                                                                     ` Carl Love
  1 sibling, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-18 16:16 UTC (permalink / raw)
  To: Tom de Vries, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel

On Wed, 2023-01-18 at 11:55 +0100, Tom de Vries wrote:
> On 1/17/23 20:31, Carl Love wrote:
> > Tom:
> > 
> > On Tue, 2023-01-17 at 18:14 +0100, Tom de Vries wrote:
> > > On 1/17/23 18:03, Carl Love wrote:
> > > > Tom:
> > > > 
> > > > On Tue, 2023-01-17 at 17:55 +0100, Tom de Vries wrote:
> > > > > AFAICT, this has been committed just now.
> > > > > 
> > > > > I'm having difficulty finding an approval, did it happen
> > > > > maybe
> > > > > offlist?
> > > > > 
> > > > > Thanks,
> > > > > - Tom
> > > > 
> > > > I just committed it based on Bruno's reply.
> > > > 
> > > >      > The patch has been tested on X86 and PowerPC with no
> > > > regressions.
> > > > 
> > > >      I will reiterate that I don't know much about PPC, so the
> > > > best
> > > > I can do
> > > >      is check for style and tests, but apart from a few minor
> > > > nits
> > > > inlined,
> > > >      it looks ok
> > > > 
> > > >      Tested-By: Bruno Larsen <blarsen@redhat.com>
> > > > 
> > > > I thought that was an approval to commit.  Is it not?
> > > 
> > > Hi Carl,
> > > 
> > > sorry, AFAIU it's not.  Bruno has been helpfully reviewing your
> > > patch,
> > > but AFAIK he cannot approve it.
> > > 
> > > This is an easy mistake to make though, given the used
> > > formulation,
> > > it's
> > > not the first time it happened, and it's one of the reasons we're
> > > trying
> > > to move towards replying with the Approved-By tag to make
> > > approval
> > > more
> > > formal, explicit and unambiguous.
> > > 
> > > FYI, I'm working my way toward reviewing these patches, and have
> > > regained access to my usual powerpc machine, so I'll try to
> > > reproduce
> > > the issue you're seeing.
> > 
> > OK, thanks for the clarification on the process.  In the past, I
> > have
> > had people explicitly state in their reply that they could not
> > approve
> > a patch but were just reviewing and commenting on it.
> > 
> > I will be sure to look for the "Approved-By tag" in the
> > future.  Sorry
> > for the mistake.
> > 
> > Please let me know if you need me to revert the patch, make some
> > fixes,
> > or?
> 
> I've run into regressions due to the first patch:
> ...
> FAIL: gdb.btrace/rn-dl-bind.exp: test: reverse-next
> FAIL: gdb.btrace/tailcall.exp: reverse-next.1
> FAIL: gdb.btrace/tailcall.exp: step.1
> ...
> 
> So, please revert both.

I reverted both commits.  I will take see if I can reproduce the
failures you are seeing.


ommit b986eec55f460a9c77a0c06ec30d7280293f7a8c (HEAD -> master,
origin/master, origin/HEAD)
Author: Carl Love <cel@us.ibm.com>
Date:   Wed Jan 18 11:13:17 2023 -0500

    Revert "X86: reverse-finish fix"
    
    This reverts commit b22548ddb30bfb167708e82d3bb932461c1b703a.
    
    This patch is being reverted since the patch series is causing
regressions.

commit 15d2b36c5b60795067cec773a66d2627d2bf9266
Author: Carl Love <cel@us.ibm.com>
Date:   Wed Jan 18 11:12:13 2023 -0500

    Revert "PowerPC: fix for gdb.reverse/finish-precsave.exp and
gdb.reverse/finish-reverse.exp"
    
    This reverts commit 92e07580db6a5572573d5177ca23933064158f89.
    
    Reverting patch as the patch series is causing regressions.


                  Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-18 10:55                                                                   ` Tom de Vries
  2023-01-18 16:16                                                                     ` Carl Love
@ 2023-01-18 22:26                                                                     ` Carl Love
  2023-01-19  8:04                                                                       ` Bruno Larsen
  1 sibling, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-18 22:26 UTC (permalink / raw)
  To: Tom de Vries, Bruno Larsen, Ulrich Weigand, gdb-patches; +Cc: cel

Tom and Bruno:

On Wed, 2023-01-18 at 11:55 +0100, Tom de Vries wrote:
> 
> I've run into regressions due to the first patch:
> ...
> FAIL: gdb.btrace/rn-dl-bind.exp: test: reverse-next
> FAIL: gdb.btrace/tailcall.exp: reverse-next.1
> FAIL: gdb.btrace/tailcall.exp: step.1
> ...

I am looking into these failures.  I tried running the rn-dl-bind.exp
test on my PowerPC and X86 box.  On both systems, I get the error:

UNSUPPORTED: gdb.btrace/rn-dl-bind.exp: target does not support record-btrace
testcase /../binutils-gdb-finish-precsave/gdb/testsuite/gdb.btrace/rn-dl-bind.exp completed in 0 seconds

I tried compiling the source code and running gdb by hand on my PowerPC
machine.  When I try the command record btrace, I get the message:  You
can't do that when your target is `multi-thread'.  Digging into the GDB
manual I see it says the following about btrace:

   Hardware-supported instruction recording, supported on Intel
   processors. This method does not record data. Further, the data is
   collected in a ring buffer so old data will be overwritten when the
   buffer is full. It allows limited reverse execution. Variables and
   registers are not available during reverse execution. In remote
   debugging, recording continues on disconnect. Recorded data can be
   inspected after reconnecting. The recording may be stopped using
   record stop.

From this I am assuming you saw the error on and Intel box not a
PowerPC box.  

I tried to run the rn-dl-bind.exp test on my X66 box by hand and got
the messages:

   Breakpoint 1, main () at rn-dl-bind.c:35
   35        ret = test ();                        /* main.1 */
   (gdb) record btrace pt
   Intel Processor Trace support was disabled at compile time.
   (gdb) record btrace bts
   Could not enable branch tracing for Thread 0x7ffff7d85740 (LWP
   3087787): BTS support has been disabled for the target cpu.

I found on the web page:  
 
https://gdb-patches.sourceware.narkive.com/Y1ypJmWj/patch-btrace-diagnose-record-bt
race-pt-without-libipt

says record btrace pt neds:

   This requires a system with Linux kernel 4.1 or later running on a
   5th Generation Intel Core processor or later.

Since I couldn't get the test to run on an IBM machine, I built GDB on
my personal Linux laptop.  Initially, I was not able to get the test to
run.  The log file had the error message:

   (gdb) record btrace
   Could not enable branch tracing for process 3941218: You do not have
   permission to record the process.  Try setting
   /proc/sys/kernel/perf_event_paranoid to 2 or less.


I changed /proc/sys/kernel/perf_event_paranoid from 4 to 2.  Now the
test runs.

   (gdb) PASS: gdb.btrace/rn-dl-bind.exp: test: reverse-next
   testcase /home/carll/GDB/binutils-
   build/gdb/testsuite/../../../binutils-
   gdb/gdb/testsuite/gdb.btrace/rn-dl-bind.exp completed in 0 seconds

                   === gdb Summary ===

   # of expected passes            9

The test works fine without my patches, with just the X86 patch and
with both the X86 patch and the PPC patch.  Unfortunately, I wasn't
able to run the tests on the IBM machine but I can on my personal
laptop.  However, I am still not seeing any errors as a result of my
patches.  

Not sure what more I can do at this point.  If you have some time, can
you take a look at the failures on your machine and let me know what
you are seeing.  Maybe we can figure out what is going on.

Perhaps Bruno can also check to see if the two tests were ran on his
machine.  If not, hopefully the info above will help Bruno to get the
tests to run on his machine and we can see if they fail there as well.

Thanks for the help with this patch.

                                 Carl


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-18 22:26                                                                     ` Carl Love
@ 2023-01-19  8:04                                                                       ` Bruno Larsen
  2023-01-19 16:56                                                                         ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-01-19  8:04 UTC (permalink / raw)
  To: Carl Love, Tom de Vries, Ulrich Weigand, gdb-patches

On 18/01/2023 23:26, Carl Love wrote:
> Not sure what more I can do at this point.  If you have some time, can
> you take a look at the failures on your machine and let me know what
> you are seeing.  Maybe we can figure out what is going on.
>
> Perhaps Bruno can also check to see if the two tests were ran on his
> machine.  If not, hopefully the info above will help Bruno to get the
> tests to run on his machine and we can see if they fail there as well.

I just tried running the gdb.btrace/rn-dl-bind.exp and also got 9 
passes, so I cant help there, but I did miss the 2 failures in 
tailcall.exp; here's the relevant log:

Breakpoint 1, main () at tailcall.c:37
38        answer += 1;
(gdb) PASS: gdb.btrace/tailcall.exp: next.1
reverse-next
foo () at tailcall.c:29
29        return bar ();
(gdb) FAIL: gdb.btrace/tailcall.exp: reverse-next.1
step
bar () at tailcall.c:24
24      }
(gdb) FAIL: gdb.btrace/tailcall.exp: step.1
finish

Some extra context, line 37 (the line that is being "undone" by 
reverse-next) has a call to foo, which calls bar. Whats going on here is 
that we're hitting the step-resume breakpoint when exiting the bar call, 
instead of when exiting the foo call.Has a very similar smell to the 
type of bug I fixed in commit 1f3e37e057e876b37db49dbd8ed5ca22c33f6772, 
but that fix itself might not work because of tailcall optimizations.

If you have the test compiled, you can trigger the bug using regular 
record, no need to use btrace specifically.

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-19  8:04                                                                       ` Bruno Larsen
@ 2023-01-19 16:56                                                                         ` Carl Love
  2023-01-19 23:57                                                                           ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-19 16:56 UTC (permalink / raw)
  To: Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches; +Cc: cel

Bruno:

On Thu, 2023-01-19 at 09:04 +0100, Bruno Larsen wrote:
> On 18/01/2023 23:26, Carl Love wrote:
> > Not sure what more I can do at this point.  If you have some time,
> > can
> > you take a look at the failures on your machine and let me know
> > what
> > you are seeing.  Maybe we can figure out what is going on.
> > 
> > Perhaps Bruno can also check to see if the two tests were ran on
> > his
> > machine.  If not, hopefully the info above will help Bruno to get
> > the
> > tests to run on his machine and we can see if they fail there as
> > well.
> 
> I just tried running the gdb.btrace/rn-dl-bind.exp and also got 9 
> passes, so I cant help there, but I did miss the 2 failures in 
> tailcall.exp; here's the relevant log:
> 
> Breakpoint 1, main () at tailcall.c:37
> 38        answer += 1;
> (gdb) PASS: gdb.btrace/tailcall.exp: next.1
> reverse-next
> foo () at tailcall.c:29
> 29        return bar ();
> (gdb) FAIL: gdb.btrace/tailcall.exp: reverse-next.1
> step
> bar () at tailcall.c:24
> 24      }
> (gdb) FAIL: gdb.btrace/tailcall.exp: step.1
> finish
> 
> Some extra context, line 37 (the line that is being "undone" by 
> reverse-next) has a call to foo, which calls bar. Whats going on here
> is 
> that we're hitting the step-resume breakpoint when exiting the bar
> call, 
> instead of when exiting the foo call.Has a very similar smell to the 
> type of bug I fixed in commit
> 1f3e37e057e876b37db49dbd8ed5ca22c33f6772, 
> but that fix itself might not work because of tailcall optimizations.
> 
> If you have the test compiled, you can trigger the bug using regular 
> record, no need to use btrace specifically.

Thanks, I went back and tried the tailcall again.  I was able to get it
to generate 2 fails on my laptop with just the X86 patch.  Not sure why
I didn't see that before, maybe I had a typo???   I did note that git
on my laptop seems to act a bit weird so maybe that was an issue??  I
am having to double check the code changes after running git to make
sure it applied the changes correctly.  Not sure why I didn't see the
passes in the full regression suite either.  Anyway, I am looking to
see if I can figure out what the regression issue is for this test.

The gdb.btrace/rn-dl-bind.exp test still runs fine with 9 passes.

                                Carl 



^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-19 16:56                                                                         ` Carl Love
@ 2023-01-19 23:57                                                                           ` Carl Love
  2023-01-20 20:04                                                                             ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-19 23:57 UTC (permalink / raw)
  To: Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches; +Cc: cel

Bruno, Tom:


On Thu, 2023-01-19 at 08:56 -0800, Carl Love wrote:
<snip>
> > 
> > If you have the test compiled, you can trigger the bug using
> > regular 
> > record, no need to use btrace specifically.
> 
> Thanks, I went back and tried the tailcall again.  I was able to get
> it
> to generate 2 fails on my laptop with just the X86 patch.  Not sure
> why
> I didn't see that before, maybe I had a typo??? 

I reviewed the full regression log on my X86 laptop and yup there are
the two errors for tailcall in the log.  I just missed them when I was
looking.  Argh.

>   I did note that git
> on my laptop seems to act a bit weird so maybe that was an issue??  I
> am having to double check the code changes after running git to make
> sure it applied the changes correctly.  Not sure why I didn't see the
> passes in the full regression suite either.  Anyway, I am looking to
> see if I can figure out what the regression issue is for this test.
> 
> The gdb.btrace/rn-dl-bind.exp test still runs fine with 9 passes.

I claim, the test case for gdb.btrace/tailcall.exp also needs fixing.

Without the patch, when you were in the main program at "answer += 1"
and did a reverse-next, gdb would go back thru the call to function bar
and thru the call to function foo stopping in main.  That doesn't seem
right to me as you have stepped back thru function foo and bar.  

With the patch the reverse-next only step back thru function bar and
stops in function foo at the call to bar, i.e. doesn't continue to step
back thru function bar.

The following is the tailcall source code with comments showing where
the reverse-step and reverse-next stop with and without the X86 patch
applied.  Hopefully the code below is a little easier to follow.
Initially, the reverse-step and reverse-next tests are executed from
the line "answer += 1;" in function main.


static __attribute__ ((noinline)) int
bar (void)
{
  return 42;
}                    <- reverse-step stops here (with no patch
                        and with X86 patch)

static __attribute__ ((noinline)) int
foo (void)
{
  return bar ();     <- reverse-next stops here (patch X86 applied)
}

int
main (void)
{
  int answer;

  answer = foo ();    <- reverse-next tops here (no patch applied, stepped
                         back thru both the bar and foo functions)
  answer += 1;        <- GDB is here, now issue the reverse-step
                         and reverse-next commands

  return answer;
}

As a result of the change in the reverse-next instruction, the expected
test results for the tailcall test need to be updated to reflect the
fact that gdb now stops in function foo not main.

--- a/gdb/testsuite/gdb.btrace/tailcall.exp
+++ b/gdb/testsuite/gdb.btrace/tailcall.exp
@@ -102,9 +102,9 @@ gdb_test "reverse-step" "\[^\r\n\]*main \\(\\) at tailcall.c
:37\r\n.*" \
     "reverse-step.2"
 gdb_test "next" "\[^\r\n\]*38.*" \
     "next.1"
-gdb_test "reverse-next" "\[^\r\n\]*main \\(\\) at tailcall.c:37\r\n.*" \
+gdb_test "reverse-next" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
     "reverse-next.1"
-gdb_test "step" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
+gdb_test "step" "\[^\r\n\]*bar \\(\\) at tailcall.c:24\r\n.*" \
     "step.1"
 gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:38\r\n.*" \
     "finish.2"

With this change, the tailcall.exp test now passes on my X86 laptop.
The PowerPC do not change since the test is not supported on PowerPC.

I will post an updated version of the X86 patch with the fixes to the
tailcall test.  It will be version 3.  There are no changes to the
PowerPC patch.

The gdb.btrace/rn-dl-bind.exp test passes with and without my patches. 
I still can not get this test to fail on my system.  

                    Carl


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-17 12:35                                                       ` Bruno Larsen
@ 2023-01-20  0:03                                                         ` Carl Love
  2023-01-23 19:17                                                           ` Pedro Alves
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-20  0:03 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches; +Cc: cel


Bruno, Tom:

Per the conversation about the regressions for the regressions in tests

FAIL: gdb.btrace/rn-dl-bind.exp: test: reverse-next
FAIL: gdb.btrace/tailcall.exp: reverse-next.1
FAIL: gdb.btrace/tailcall.exp: step.1

The following patch fixes the expected results for the tailcall test on
X86.  Per the previous messages, the output needs to be updated since
the behavior of the reverse-next command was fixed.

As noted, I have not been able to reproduce the gdb.btrace/rn-dl-
bind.exp test failure.

The patch has been tested on my personal X86 laptop which has the
needed processor version and on the PowerPC machine with no regressions
found.

                           Carl 

------------------------------------------

X86: reverse-finish fix

PR record/29927  - reverse-finish requires two reverse next instructions to
reach previous source line

Currently on X86, when executing the finish command in reverse, gdb does a
single step from the first instruction in the callee to get back to the
caller.  GDB stops on the last instruction in the source code line where
the call was made.  When stopped at the last instruction of the source code
line, a reverse next or step command will stop at the first instruction
of the same source code line thus requiring two step/next commands to
reach the previous source code line.  It should only require one step/next
command to reach the previous source code line.

By contrast, a reverse next or step command from the first line in a
function stops at the first instruction in the source code line where the
call was made.

This patch fixes the reverse finish command so it will stop at the first
instruction of the source line where the function call was made.  The
behavior on X86 for the reverse-finish command now matches doing a
reverse-next from the beginning of the function.

The proceed_to_finish flag in struct thread_control_state is no longer
used.  This patch removes the declaration, initialization and setting of
the flag.

This patch requires a number of regression tests to be updated.  Test
gdb.mi/mi-reverse.exp no longer needs to execute two steps to get to the
previous line.  The gdb output for tests gdb.reverse/until-precsave.exp
and gdb.reverse/until-reverse.exp changed slightly.  The expected result in
tests gdb.reverse/amd64-failcall-reverse.exp and
gdb.reverse/singlejmp-reverse.exp are updated to the correct expected
result.  The expected result in btrace/tailcall.exp also changes since
the reverse-next now only steps back thru one function call not two
function calls.

This patch adds a new test gdb.reverse/finish-reverse-next.exp to test the
reverse-finish command when returning from the entry point and from the
body of the function.

The step_until proceedure in test gdb.reverse/step-indirect-call-thunk.exp
was moved to lib/gdb.exp and renamed cmd_until.

The patch has been tested on X86 and PowerPC to verify no additional
regression failures occured.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29927
---
 gdb/gdbthread.h                               |   4 -
 gdb/infcall.c                                 |   3 -
 gdb/infcmd.c                                  |  32 +++---
 gdb/infrun.c                                  |  40 +++----
 gdb/testsuite/gdb.btrace/tailcall.exp         |   4 +-
 gdb/testsuite/gdb.mi/mi-reverse.exp           |   9 +-
 .../gdb.reverse/amd64-tailcall-reverse.exp    |   5 +-
 .../gdb.reverse/finish-reverse-next.c         |  48 ++++++++
 .../gdb.reverse/finish-reverse-next.exp       | 104 ++++++++++++++++++
 .../gdb.reverse/singlejmp-reverse.exp         |   5 +-
 .../gdb.reverse/step-indirect-call-thunk.exp  |  49 ++-------
 gdb/testsuite/gdb.reverse/until-precsave.exp  |   2 +-
 gdb/testsuite/gdb.reverse/until-reverse.exp   |   2 +-
 gdb/testsuite/lib/gdb.exp                     |  33 ++++++
 14 files changed, 232 insertions(+), 108 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp

diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 11d69fceab0..e4edff2d621 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -150,10 +150,6 @@ struct thread_control_state
      the finished single step.  */
   int trap_expected = 0;
 
-  /* Nonzero if the thread is being proceeded for a "finish" command
-     or a similar situation when return value should be printed.  */
-  int proceed_to_finish = 0;
-
   /* Nonzero if the thread is being proceeded for an inferior function
      call.  */
   int in_infcall = 0;
diff --git a/gdb/infcall.c b/gdb/infcall.c
index e09904f9a35..116605c43ef 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -625,9 +625,6 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
 
   disable_watchpoints_before_interactive_call_start ();
 
-  /* We want to print return value, please...  */
-  call_thread->control.proceed_to_finish = 1;
-
   try
     {
       /* Infcalls run synchronously, in the foreground.  */
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 0497ad05091..9c42efeae8d 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1721,19 +1721,10 @@ finish_backward (struct finish_command_fsm *sm)
 
   sal = find_pc_line (func_addr, 0);
 
-  tp->control.proceed_to_finish = 1;
-  /* Special case: if we're sitting at the function entry point,
-     then all we need to do is take a reverse singlestep.  We
-     don't need to set a breakpoint, and indeed it would do us
-     no good to do so.
-
-     Note that this can only happen at frame #0, since there's
-     no way that a function up the stack can have a return address
-     that's equal to its entry point.  */
+  frame_info_ptr frame = get_selected_frame (nullptr);
 
   if (sal.pc != pc)
     {
-      frame_info_ptr frame = get_selected_frame (nullptr);
       struct gdbarch *gdbarch = get_frame_arch (frame);
 
       /* Set a step-resume at the function's entry point.  Once that's
@@ -1743,16 +1734,22 @@ finish_backward (struct finish_command_fsm *sm)
       sr_sal.pspace = get_frame_program_space (frame);
       insert_step_resume_breakpoint_at_sal (gdbarch,
 					    sr_sal, null_frame_id);
-
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
   else
     {
-      /* We're almost there -- we just need to back up by one more
-	 single-step.  */
-      tp->control.step_range_start = tp->control.step_range_end = 1;
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
+      /* We are exactly at the function entry point.  Note that this
+	 can only happen at frame #0.
+
+	 When setting a step range, need to call set_step_info
+	 to setup the current_line/symtab fields as well.  */
+      set_step_info (tp, frame, find_pc_line (pc, 0));
+
+      /* Return using a step range so we will keep stepping back
+	 to the first instruction in the source code line.  */
+      tp->control.step_range_start = sal.pc;
+      tp->control.step_range_end = sal.pc;
     }
+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
 /* finish_forward -- helper function for finish_command.  FRAME is the
@@ -1778,9 +1775,6 @@ finish_forward (struct finish_command_fsm *sm, frame_info_ptr frame)
 
   set_longjmp_breakpoint (tp, frame_id);
 
-  /* We want to print return value, please...  */
-  tp->control.proceed_to_finish = 1;
-
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 181d961d80d..86e5ef1ed12 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct thread_info *tp)
 
   tp->control.stop_step = 0;
 
-  tp->control.proceed_to_finish = 0;
-
   tp->control.stepping_command = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
@@ -6737,31 +6735,27 @@ process_event_stop_test (struct execution_control_state *ecs)
 
     case BPSTAT_WHAT_STEP_RESUME:
       infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
-
       delete_step_resume_breakpoint (ecs->event_thread);
-      if (ecs->event_thread->control.proceed_to_finish
-	  && execution_direction == EXEC_REVERSE)
+      fill_in_stop_func (gdbarch, ecs);
+
+      if (execution_direction == EXEC_REVERSE)
 	{
 	  struct thread_info *tp = ecs->event_thread;
+	  /* We are finishing a function in reverse or stepping over a function
+	     call in reverse, and just hit the step-resume breakpoint at the
+	     start address of the function, and we're almost there -- just need
+	     to back up to the function call.  */
 
-	  /* We are finishing a function in reverse, and just hit the
-	     step-resume breakpoint at the start address of the
-	     function, and we're almost there -- just need to back up
-	     by one more single-step, which should take us back to the
-	     function call.  */
-	  tp->control.step_range_start = tp->control.step_range_end = 1;
-	  keep_going (ecs);
-	  return;
-	}
-      fill_in_stop_func (gdbarch, ecs);
-      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
-	  && execution_direction == EXEC_REVERSE)
-	{
-	  /* We are stepping over a function call in reverse, and just
-	     hit the step-resume breakpoint at the start address of
-	     the function.  Go back to single-stepping, which should
-	     take us back to the function call.  */
-	  ecs->event_thread->stepping_over_breakpoint = 1;
+	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
+
+	  /* When setting a step range, need to call set_step_info
+	     to setup the current_line/symtab fields as well.  */
+	  set_step_info (tp, frame, stop_pc_sal);
+
+	  /* Return using a step range so we will keep stepping back to the
+	     first instruction in the source code line.  */
+	  tp->control.step_range_start = ecs->stop_func_start;
+	  tp->control.step_range_end = ecs->stop_func_start;
 	  keep_going (ecs);
 	  return;
 	}
diff --git a/gdb/testsuite/gdb.btrace/tailcall.exp b/gdb/testsuite/gdb.btrace/tailcall.exp
index 028e03fc6f6..fa254664a09 100644
--- a/gdb/testsuite/gdb.btrace/tailcall.exp
+++ b/gdb/testsuite/gdb.btrace/tailcall.exp
@@ -102,9 +102,9 @@ gdb_test "reverse-step" "\[^\r\n\]*main \\(\\) at tailcall.c:37\r\n.*" \
     "reverse-step.2"
 gdb_test "next" "\[^\r\n\]*38.*" \
     "next.1"
-gdb_test "reverse-next" "\[^\r\n\]*main \\(\\) at tailcall.c:37\r\n.*" \
+gdb_test "reverse-next" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
     "reverse-next.1"
-gdb_test "step" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
+gdb_test "step" "\[^\r\n\]*bar \\(\\) at tailcall.c:24\r\n.*" \
     "step.1"
 gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:38\r\n.*" \
     "finish.2"
diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
index d631beb17c8..30635ab1754 100644
--- a/gdb/testsuite/gdb.mi/mi-reverse.exp
+++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
@@ -97,15 +97,10 @@ proc test_controlled_execution_reverse {} {
 	"basics.c" $line_main_callme_1 "" \
 	"reverse finish from callme"
 
-    # Test exec-reverse-next
-    #   It takes two steps to get back to the previous line,
-    #   as the first step moves us to the start of the current line,
-    #   and the one after that moves back to the previous line.
-
-    mi_execute_to "exec-next --reverse 2" \
+    mi_execute_to "exec-next --reverse" \
  	"end-stepping-range" "main" "" \
  	"basics.c" $line_main_hello "" \
- 	"reverse next to get over the call to do_nothing"
+	"reverse next to get over the call to do_nothing"
 
     # Test exec-reverse-step
 
diff --git a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
index 52a87faabf7..9964b4f8e4b 100644
--- a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
@@ -44,6 +44,5 @@ if [supports_process_record] {
 gdb_test "next" {f \(\);} "next to f"
 gdb_test "next" {v = 3;} "next to v = 3"
 
-# FAIL was:
-# 29        g ();
-gdb_test "reverse-next" {f \(\);}
+# Reverse step back into f ().  Puts us at call to g () in function f ().
+gdb_test "reverse-next" {g \(\);}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
new file mode 100644
index 00000000000..f90ecbb93cb
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -0,0 +1,48 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The reverse finish command should return from a function and stop on
+   the first instruction of the source line where the function call is made.
+   Specifically, the behavior should match doing a reverse next from the
+   first instruction in the function.  GDB should only require one reverse
+   step or next statement to reach the previous source code line.
+
+   This test verifies the fix for gdb bugzilla:
+
+   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+*/
+
+int
+function1 (int a, int b)   // FUNCTION1
+{
+  int ret = 0;
+
+  ret = a + b;
+  return ret;
+}
+
+int
+main(int argc, char* argv[])
+{
+  int a, b;
+
+  a = 1;
+  b = 5;
+
+  function1 (a, b);   // CALL FUNCTION
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
new file mode 100644
index 00000000000..63305c109e1
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -0,0 +1,104 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+### TEST 1: reverse finish from the entry point instruction in
+### function1.
+
+# Set breakpoint at call to function1 in main.
+set bp_FUNCTION [gdb_get_line_number "CALL FUNCTION" $srcfile]
+gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_FUNCTION\r\n.*"
+
+# stepi until we see "{" indicating we entered function1
+repeat_cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
+    "reverse-finish function1 "
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.   If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
+
+# Clear the recorded log.
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+### TEST 2: reverse finish from the body of function1.
+
+# Set breakpoint at call to function1 in main.
+gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of function" \
+    ".*$srcfile:$bp_FUNCTION\r\n.*"
+
+# do a step instruction to get to the body of the function
+gdb_test "step" ".*int ret = 0;.*" "step test 1"
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
+    "reverse-finish function1 call from function body"
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse next at b = 5, from function body"
diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
index 1ca7c2ce559..eb03051625a 100644
--- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
@@ -56,7 +56,4 @@ gdb_test "next" {v = 3;} "next to v = 3"
 # {
 gdb_test "reverse-step" {nodebug \(\);}
 
-# FAIL was:
-# No more reverse-execution history.
-# {
-gdb_test "reverse-next" {f \(\);}
+gdb_test "reverse-next" {g \(\);}
diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index ad637899e5b..b82e5663bd5 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -39,39 +39,6 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
-proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
-}
-
 gdb_test_no_output "record"
 gdb_test "next" ".*" "record trace"
 
@@ -91,20 +58,20 @@ gdb_test "reverse-next" "apply\.2.*" \
     "reverse-step through thunks and over inc"
 
 # We can use instruction stepping to step into thunks.
-step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
-step_until "stepi" "indirect_thunk" "inc" \
+repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
+repeat_cmd_until "stepi" "indirect_thunk" "inc" \
     "stepi out of call thunk into inc"
 set alphanum_re "\[a-zA-Z0-9\]"
 set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
-step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
-step_until "stepi" "return_thunk" "apply" \
+repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
+repeat_cmd_until "stepi" "return_thunk" "apply" \
     "stepi out of return thunk back into apply"
 
-step_until "reverse-stepi" "apply" "return_thunk" \
+repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
     "reverse-stepi into return thunk"
-step_until "reverse-stepi" "return_thunk" "inc" \
+repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
     "reverse-stepi out of return thunk into inc"
-step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
+repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
     "reverse-stepi into call thunk"
-step_until "reverse-stepi" "indirect_thunk" "apply" \
+repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
     "reverse-stepi out of call thunk into apply"
diff --git a/gdb/testsuite/gdb.reverse/until-precsave.exp b/gdb/testsuite/gdb.reverse/until-precsave.exp
index 0c2d7537cd6..777aec94ac1 100644
--- a/gdb/testsuite/gdb.reverse/until-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/until-precsave.exp
@@ -142,7 +142,7 @@ gdb_test "advance marker2" \
 # Finish out to main scope (backward)
 
 gdb_test "finish" \
-    " in main .*$srcfile:$bp_location20.*" \
+    "main .*$srcfile:$bp_location20.*" \
     "reverse-finish from marker2"
 
 # Advance backward to last line of factorial (outer invocation)
diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp b/gdb/testsuite/gdb.reverse/until-reverse.exp
index 23fc881dbf2..3a05953329f 100644
--- a/gdb/testsuite/gdb.reverse/until-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/until-reverse.exp
@@ -113,7 +113,7 @@ gdb_test "advance marker2" \
 # Finish out to main scope (backward)
 
 gdb_test "finish" \
-    " in main .*$srcfile:$bp_location20.*" \
+    "main .*$srcfile:$bp_location20.*" \
     "reverse-finish from marker2"
 
 # Advance backward to last line of factorial (outer invocation)
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index c41d4698d66..234c21a04ea 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9301,6 +9301,39 @@ proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
     }
 }
 
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND is a stepping command
+#  CURRENT is a string matching the current location
+#  TARGET  is a string matching the target location
+#  TEST    is the test name
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of 100 steps.
+#
+# TEST passes if the resulting location matches TARGET and fails
+# otherwise.
+
+proc repeat_cmd_until { command current target test } {
+    global gdb_prompt
+
+    set count 0
+    gdb_test_multiple "$command" "$test" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < 100 } {
+		send_gdb "$command\n"
+		exp_continue
+	    } else {
+		fail "$test"
+	    }
+	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+}
+
 # Check if the compiler emits epilogue information associated
 # with the closing brace or with the last statement line.
 #
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 version 2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-19 23:57                                                                           ` Carl Love
@ 2023-01-20 20:04                                                                             ` Carl Love
  2023-01-23 16:42                                                                               ` [PATCH 1/2 version 3] " Carl Love
                                                                                                 ` (2 more replies)
  0 siblings, 3 replies; 105+ messages in thread
From: Carl Love @ 2023-01-20 20:04 UTC (permalink / raw)
  To: Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches; +Cc: cel

On Thu, 2023-01-19 at 15:57 -0800, Carl Love wrote:
> Bruno, Tom:
> 
> 
> On Thu, 2023-01-19 at 08:56 -0800, Carl Love wrote:
> 
<snip>
> 
> Without the patch, when you were in the main program at "answer += 1"
> and did a reverse-next, gdb would go back thru the call to function
> bar
> and thru the call to function foo stopping in main.  That doesn't
> seem
> right to me as you have stepped back thru function foo and bar.  
> 
> With the patch the reverse-next only step back thru function bar and
> stops in function foo at the call to bar, i.e. doesn't continue to
> step
> back thru function bar.
> 
> The following is the tailcall source code with comments showing where
> the reverse-step and reverse-next stop with and without the X86 patch
> applied.  Hopefully the code below is a little easier to follow.
> Initially, the reverse-step and reverse-next tests are executed from
> the line "answer += 1;" in function main.
> 
> 
> static __attribute__ ((noinline)) int
> bar (void)
> {
>   return 42;
> }                    <- reverse-step stops here (with no patch
>                         and with X86 patch)
> 
> static __attribute__ ((noinline)) int
> foo (void)
> {
>   return bar ();     <- reverse-next stops here (patch X86 applied)
> }
> 
> int
> main (void)
> {
>   int answer;
> 
>   answer = foo ();    <- reverse-next tops here (no patch applied,
> stepped
>                          back thru both the bar and foo functions)
>   answer += 1;        <- GDB is here, now issue the reverse-step
>                          and reverse-next commands
> 
>   return answer;
> }
> 
> As a result of the change in the reverse-next instruction, the
> expected
> test results for the tailcall test need to be updated to reflect the
> fact that gdb now stops in function foo not main.
> 
> --- a/gdb/testsuite/gdb.btrace/tailcall.exp
> +++ b/gdb/testsuite/gdb.btrace/tailcall.exp
> @@ -102,9 +102,9 @@ gdb_test "reverse-step" "\[^\r\n\]*main \\(\\) at
> tailcall.c
> :37\r\n.*" \
>      "reverse-step.2"
>  gdb_test "next" "\[^\r\n\]*38.*" \
>      "next.1"
> -gdb_test "reverse-next" "\[^\r\n\]*main \\(\\) at
> tailcall.c:37\r\n.*" \
> +gdb_test "reverse-next" "\[^\r\n\]*foo \\(\\) at
> tailcall.c:29\r\n.*" \
>      "reverse-next.1"
> -gdb_test "step" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
> +gdb_test "step" "\[^\r\n\]*bar \\(\\) at tailcall.c:24\r\n.*" \
>      "step.1"
>  gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:38\r\n.*" \
>      "finish.2"
> 
> With this change, the tailcall.exp test now passes on my X86 laptop.
> The PowerPC do not change since the test is not supported on PowerPC.
> 
> I will post an updated version of the X86 patch with the fixes to the
> tailcall test.  It will be version 3.  There are no changes to the
> PowerPC patch.
> 
> The gdb.btrace/rn-dl-bind.exp test passes with and without my
> patches. 
> I still can not get this test to fail on my system.  

I have been thinking about this and have decided the above change is
not what we should do.  Basically if we forward step at answer = foo();
we stop at answer += 1;.  Which is the expected behavior for next.  So,
is we are at answer += 1; and do a reverse step it should take us to
answer = foo().  It would be the opposite of the forward next.

I think I have identified the single line in the function call
set_step_info() which caused the regression in gdb.btrace/tailcall.exp.
I have so far run a few experiments and it looks like not doing the 
statement:

 tp->control.step_stack_frame_id = get_stack_frame_id (frame);

eliminates the regression in tailcall.exp. 

So far.  I need to do some more testing but it looks like there is a
couple of regressions on my X86 laptop. It looks like the expected
behavior in both of these tests is for the reverse step over a function
stops at a function call within the function not stepping all the way
back to the call of the function.  Basically, the expected behavior of
these reverse tests is not consistent across tests.  

I am not seeing any PowerPC regression failures with the above change. 
My IBM x86 machine tests are still running.

Anyway, just wanted to give people a heads up that I am pursuing
another fix and that I now think the above fix is not the best
direction to go.

                          Carl


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-20 20:04                                                                             ` Carl Love
@ 2023-01-23 16:42                                                                               ` Carl Love
  2023-01-23 16:42                                                                               ` [PATCH 2/2 " Carl Love
  2023-02-10 20:55                                                                               ` [PATCH ] PowerPC: " Carl Love
  2 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-23 16:42 UTC (permalink / raw)
  To: Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches; +Cc: cel

Bruno, Tom, Ulrich, GDB developers:

Fixed the regression failure in gdb.btrace/tailcall.exp.  The function
call set_step_info() sets the following values:

  tp->control.step_frame_id = get_frame_id (frame);
  tp->control.step_stack_frame_id = get_stack_frame_id (frame);

  tp->current_symtab = sal.symtab;
  tp->current_line = sal.line;

The regression failure was due to the function updating the value of
tp->control.step_stack_frame_id.  So, the function call was replaced
with the three lines of code to update step_frame_id, current_symtab, 
current_line.  This was done in both places where set_step_info() was
being called.

The gdb.btrace tests require a 5th generation Intel processor to run. 
I have run the regression tests on my X86 laptop with a 5th generation
processor as well as the IBM X86 system, with a pre 5th generation
processor and on PowerPC with no regressions.

I do not see the issue with test gdb.btrace/rn-dl-bind.exp Tom
reported.

Please let me know if this version of the patch is acceptable.  Thanks.

                         Carl 

----------------
X86: reverse-finish fix

PR record/29927  - reverse-finish requires two reverse next instructions to
reach previous source line

Currently on X86, when executing the finish command in reverse, gdb does a
single step from the first instruction in the callee to get back to the
caller.  GDB stops on the last instruction in the source code line where
the call was made.  When stopped at the last instruction of the source code
line, a reverse next or step command will stop at the first instruction
of the same source code line thus requiring two step/next commands to
reach the previous source code line.  It should only require one step/next
command to reach the previous source code line.

By contrast, a reverse next or step command from the first line in a
function stops at the first instruction in the source code line where the
call was made.

This patch fixes the reverse finish command so it will stop at the first
instruction of the source line where the function call was made.  The
behavior on X86 for the reverse-finish command now matches doing a
reverse-next from the beginning of the function.

The proceed_to_finish flag in struct thread_control_state is no longer
used.  This patch removes the declaration, initialization and setting of
the flag.

This patch requires a number of regression tests to be updated.  Test
gdb.mi/mi-reverse.exp no longer needs to execute two steps to get to the
previous line.  The gdb output for tests gdb.reverse/until-precsave.exp
and gdb.reverse/until-reverse.exp changed slightly.  The expected result in
tests gdb.reverse/amd64-failcall-reverse.exp and
gdb.reverse/singlejmp-reverse.exp are updated to the correct expected
result.  Test gdb.reverse/singlejmp-reverse.exp no longer fails on "no
more reverse-execution history".

The reverse-next command should step all the way back thru a function call.
For example:

   a = foo ();
   b = 1;          <- issuing reverse-next here should stop at the
                      previous line.

Test gdb.reverse/amd64-tailcall-reverse.exp expected the reverse-next
command to stop at a function call in foo ().  That is not the correct
behavior.  GDB now step to the previous line as expected.  The expected
output for the test is updated to the correct behavior.

This patch adds a new test gdb.reverse/finish-reverse-next.exp to test the
reverse-finish command when returning from the entry point and from the
body of the function.

The step_until proceedure in test gdb.reverse/step-indirect-call-thunk.exp
was moved to lib/gdb.exp and renamed cmd_until.

The patch has been tested on X86 and PowerPC to verify no additional
regression failures occured.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29927
---
 gdb/gdbthread.h                               |   4 -
 gdb/infcall.c                                 |   3 -
 gdb/infcmd.c                                  |  37 +++----
 gdb/infrun.c                                  |  45 ++++----
 gdb/testsuite/gdb.mi/mi-reverse.exp           |   9 +-
 .../gdb.reverse/amd64-tailcall-reverse.exp    |   3 +-
 .../gdb.reverse/finish-reverse-next.c         |  48 ++++++++
 .../gdb.reverse/finish-reverse-next.exp       | 104 ++++++++++++++++++
 .../gdb.reverse/singlejmp-reverse.exp         |   3 -
 .../gdb.reverse/step-indirect-call-thunk.exp  |  49 ++-------
 gdb/testsuite/gdb.reverse/until-precsave.exp  |   2 +-
 gdb/testsuite/gdb.reverse/until-reverse.exp   |   2 +-
 gdb/testsuite/lib/gdb.exp                     |  33 ++++++
 13 files changed, 237 insertions(+), 105 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp

diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 11d69fceab0..e4edff2d621 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -150,10 +150,6 @@ struct thread_control_state
      the finished single step.  */
   int trap_expected = 0;
 
-  /* Nonzero if the thread is being proceeded for a "finish" command
-     or a similar situation when return value should be printed.  */
-  int proceed_to_finish = 0;
-
   /* Nonzero if the thread is being proceeded for an inferior function
      call.  */
   int in_infcall = 0;
diff --git a/gdb/infcall.c b/gdb/infcall.c
index e09904f9a35..116605c43ef 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -625,9 +625,6 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
 
   disable_watchpoints_before_interactive_call_start ();
 
-  /* We want to print return value, please...  */
-  call_thread->control.proceed_to_finish = 1;
-
   try
     {
       /* Infcalls run synchronously, in the foreground.  */
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 0497ad05091..5d3221e8b90 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1721,19 +1721,10 @@ finish_backward (struct finish_command_fsm *sm)
 
   sal = find_pc_line (func_addr, 0);
 
-  tp->control.proceed_to_finish = 1;
-  /* Special case: if we're sitting at the function entry point,
-     then all we need to do is take a reverse singlestep.  We
-     don't need to set a breakpoint, and indeed it would do us
-     no good to do so.
-
-     Note that this can only happen at frame #0, since there's
-     no way that a function up the stack can have a return address
-     that's equal to its entry point.  */
+  frame_info_ptr frame = get_selected_frame (nullptr);
 
   if (sal.pc != pc)
     {
-      frame_info_ptr frame = get_selected_frame (nullptr);
       struct gdbarch *gdbarch = get_frame_arch (frame);
 
       /* Set a step-resume at the function's entry point.  Once that's
@@ -1743,16 +1734,27 @@ finish_backward (struct finish_command_fsm *sm)
       sr_sal.pspace = get_frame_program_space (frame);
       insert_step_resume_breakpoint_at_sal (gdbarch,
 					    sr_sal, null_frame_id);
-
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
   else
     {
-      /* We're almost there -- we just need to back up by one more
-	 single-step.  */
-      tp->control.step_range_start = tp->control.step_range_end = 1;
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
+      /* We are exactly at the function entry point.  Note that this
+	 can only happen at frame #0.
+
+	 When setting a step range, need to setup the current_symtab and
+	 current_line.  Do not change the step_stack_frame_id as this
+	 will cause the reverse-next command to stop in the wrong spot.  */
+      struct symtab_and_line stop_pc_sal;
+      stop_pc_sal = find_pc_line (pc, 0);
+      tp->control.step_frame_id = get_frame_id (frame);
+      tp->current_symtab = stop_pc_sal.symtab;
+      tp->current_line = stop_pc_sal.line;
+
+      /* Return using a step range so we will keep stepping back
+	 to the first instruction in the source code line.  */
+      tp->control.step_range_start = sal.pc;
+      tp->control.step_range_end = sal.pc;
     }
+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
 /* finish_forward -- helper function for finish_command.  FRAME is the
@@ -1778,9 +1780,6 @@ finish_forward (struct finish_command_fsm *sm, frame_info_ptr frame)
 
   set_longjmp_breakpoint (tp, frame_id);
 
-  /* We want to print return value, please...  */
-  tp->control.proceed_to_finish = 1;
-
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 181d961d80d..183110a049a 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct thread_info *tp)
 
   tp->control.stop_step = 0;
 
-  tp->control.proceed_to_finish = 0;
-
   tp->control.stepping_command = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
@@ -6737,31 +6735,30 @@ process_event_stop_test (struct execution_control_state *ecs)
 
     case BPSTAT_WHAT_STEP_RESUME:
       infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
-
       delete_step_resume_breakpoint (ecs->event_thread);
-      if (ecs->event_thread->control.proceed_to_finish
-	  && execution_direction == EXEC_REVERSE)
-	{
-	  struct thread_info *tp = ecs->event_thread;
-
-	  /* We are finishing a function in reverse, and just hit the
-	     step-resume breakpoint at the start address of the
-	     function, and we're almost there -- just need to back up
-	     by one more single-step, which should take us back to the
-	     function call.  */
-	  tp->control.step_range_start = tp->control.step_range_end = 1;
-	  keep_going (ecs);
-	  return;
-	}
       fill_in_stop_func (gdbarch, ecs);
-      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
-	  && execution_direction == EXEC_REVERSE)
+
+      if (execution_direction == EXEC_REVERSE)
 	{
-	  /* We are stepping over a function call in reverse, and just
-	     hit the step-resume breakpoint at the start address of
-	     the function.  Go back to single-stepping, which should
-	     take us back to the function call.  */
-	  ecs->event_thread->stepping_over_breakpoint = 1;
+	  struct thread_info *tp = ecs->event_thread;
+	  /* We are finishing a function in reverse or stepping over a function
+	     call in reverse, and just hit the step-resume breakpoint at the
+	     start address of the function, and we're almost there -- just need
+	     to back up to the function call.  */
+
+	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
+
+	  /* When setting a step range, need to setup the current_symtab and
+	     current_line.  Do not change the step_stack_frame_id as this
+	     will cause the reverse-next command to stop in the wrong spot.  */
+	  tp->control.step_frame_id = get_frame_id (frame);
+	  tp->current_symtab = stop_pc_sal.symtab;
+	  tp->current_line = stop_pc_sal.line;
+
+	  /* Return using a step range so we will keep stepping back to the
+	     first instruction in the source code line.  */
+	  tp->control.step_range_start = ecs->stop_func_start;
+	  tp->control.step_range_end = ecs->stop_func_start;
 	  keep_going (ecs);
 	  return;
 	}
diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
index d631beb17c8..30635ab1754 100644
--- a/gdb/testsuite/gdb.mi/mi-reverse.exp
+++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
@@ -97,15 +97,10 @@ proc test_controlled_execution_reverse {} {
 	"basics.c" $line_main_callme_1 "" \
 	"reverse finish from callme"
 
-    # Test exec-reverse-next
-    #   It takes two steps to get back to the previous line,
-    #   as the first step moves us to the start of the current line,
-    #   and the one after that moves back to the previous line.
-
-    mi_execute_to "exec-next --reverse 2" \
+    mi_execute_to "exec-next --reverse" \
  	"end-stepping-range" "main" "" \
  	"basics.c" $line_main_hello "" \
- 	"reverse next to get over the call to do_nothing"
+	"reverse next to get over the call to do_nothing"
 
     # Test exec-reverse-step
 
diff --git a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
index 52a87faabf7..7d441dbb7a9 100644
--- a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
@@ -44,6 +44,5 @@ if [supports_process_record] {
 gdb_test "next" {f \(\);} "next to f"
 gdb_test "next" {v = 3;} "next to v = 3"
 
-# FAIL was:
-# 29        g ();
+# Reverse step back to f ().
 gdb_test "reverse-next" {f \(\);}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
new file mode 100644
index 00000000000..f90ecbb93cb
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -0,0 +1,48 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The reverse finish command should return from a function and stop on
+   the first instruction of the source line where the function call is made.
+   Specifically, the behavior should match doing a reverse next from the
+   first instruction in the function.  GDB should only require one reverse
+   step or next statement to reach the previous source code line.
+
+   This test verifies the fix for gdb bugzilla:
+
+   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+*/
+
+int
+function1 (int a, int b)   // FUNCTION1
+{
+  int ret = 0;
+
+  ret = a + b;
+  return ret;
+}
+
+int
+main(int argc, char* argv[])
+{
+  int a, b;
+
+  a = 1;
+  b = 5;
+
+  function1 (a, b);   // CALL FUNCTION
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
new file mode 100644
index 00000000000..63305c109e1
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -0,0 +1,104 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+### TEST 1: reverse finish from the entry point instruction in
+### function1.
+
+# Set breakpoint at call to function1 in main.
+set bp_FUNCTION [gdb_get_line_number "CALL FUNCTION" $srcfile]
+gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_FUNCTION\r\n.*"
+
+# stepi until we see "{" indicating we entered function1
+repeat_cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
+    "reverse-finish function1 "
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.   If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
+
+# Clear the recorded log.
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+### TEST 2: reverse finish from the body of function1.
+
+# Set breakpoint at call to function1 in main.
+gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of function" \
+    ".*$srcfile:$bp_FUNCTION\r\n.*"
+
+# do a step instruction to get to the body of the function
+gdb_test "step" ".*int ret = 0;.*" "step test 1"
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
+    "reverse-finish function1 call from function body"
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse next at b = 5, from function body"
diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
index 1ca7c2ce559..e94bcdbe52e 100644
--- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
@@ -56,7 +56,4 @@ gdb_test "next" {v = 3;} "next to v = 3"
 # {
 gdb_test "reverse-step" {nodebug \(\);}
 
-# FAIL was:
-# No more reverse-execution history.
-# {
 gdb_test "reverse-next" {f \(\);}
diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index ad637899e5b..b82e5663bd5 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -39,39 +39,6 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
-proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
-}
-
 gdb_test_no_output "record"
 gdb_test "next" ".*" "record trace"
 
@@ -91,20 +58,20 @@ gdb_test "reverse-next" "apply\.2.*" \
     "reverse-step through thunks and over inc"
 
 # We can use instruction stepping to step into thunks.
-step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
-step_until "stepi" "indirect_thunk" "inc" \
+repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
+repeat_cmd_until "stepi" "indirect_thunk" "inc" \
     "stepi out of call thunk into inc"
 set alphanum_re "\[a-zA-Z0-9\]"
 set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
-step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
-step_until "stepi" "return_thunk" "apply" \
+repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
+repeat_cmd_until "stepi" "return_thunk" "apply" \
     "stepi out of return thunk back into apply"
 
-step_until "reverse-stepi" "apply" "return_thunk" \
+repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
     "reverse-stepi into return thunk"
-step_until "reverse-stepi" "return_thunk" "inc" \
+repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
     "reverse-stepi out of return thunk into inc"
-step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
+repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
     "reverse-stepi into call thunk"
-step_until "reverse-stepi" "indirect_thunk" "apply" \
+repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
     "reverse-stepi out of call thunk into apply"
diff --git a/gdb/testsuite/gdb.reverse/until-precsave.exp b/gdb/testsuite/gdb.reverse/until-precsave.exp
index 0c2d7537cd6..777aec94ac1 100644
--- a/gdb/testsuite/gdb.reverse/until-precsave.exp
+++ b/gdb/testsuite/gdb.reverse/until-precsave.exp
@@ -142,7 +142,7 @@ gdb_test "advance marker2" \
 # Finish out to main scope (backward)
 
 gdb_test "finish" \
-    " in main .*$srcfile:$bp_location20.*" \
+    "main .*$srcfile:$bp_location20.*" \
     "reverse-finish from marker2"
 
 # Advance backward to last line of factorial (outer invocation)
diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp b/gdb/testsuite/gdb.reverse/until-reverse.exp
index 23fc881dbf2..3a05953329f 100644
--- a/gdb/testsuite/gdb.reverse/until-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/until-reverse.exp
@@ -113,7 +113,7 @@ gdb_test "advance marker2" \
 # Finish out to main scope (backward)
 
 gdb_test "finish" \
-    " in main .*$srcfile:$bp_location20.*" \
+    "main .*$srcfile:$bp_location20.*" \
     "reverse-finish from marker2"
 
 # Advance backward to last line of factorial (outer invocation)
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index c41d4698d66..234c21a04ea 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9301,6 +9301,39 @@ proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
     }
 }
 
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND is a stepping command
+#  CURRENT is a string matching the current location
+#  TARGET  is a string matching the target location
+#  TEST    is the test name
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of 100 steps.
+#
+# TEST passes if the resulting location matches TARGET and fails
+# otherwise.
+
+proc repeat_cmd_until { command current target test } {
+    global gdb_prompt
+
+    set count 0
+    gdb_test_multiple "$command" "$test" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < 100 } {
+		send_gdb "$command\n"
+		exp_continue
+	    } else {
+		fail "$test"
+	    }
+	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+}
+
 # Check if the compiler emits epilogue information associated
 # with the closing brace or with the last statement line.
 #
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-20 20:04                                                                             ` Carl Love
  2023-01-23 16:42                                                                               ` [PATCH 1/2 version 3] " Carl Love
@ 2023-01-23 16:42                                                                               ` Carl Love
  2023-02-10 20:55                                                                               ` [PATCH ] PowerPC: " Carl Love
  2 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-23 16:42 UTC (permalink / raw)
  To: Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches; +Cc: cel

Bruno, Tom, Ulrich, GDB maintainers:

This patch is functionally the same as version 2.  It was refreshed to
properly apply on the X86 patch.  The X86 patch changed the diff
locations slightly.

I have run the regression tests on my X86 laptop with a 5th generation
processor as well as the IBM X86 system, with a pre 5th generation
processor and on PowerPC with no regressions.

Please let me know if this version of the patch is acceptable.  Thanks.

                         Carl 

---------------------------------------------
PowerPC: fix for gdb.reverse/finish-precsave.exp and  gdb.reverse/finish-reverse.exp

PR record/29927 - reverse-finish requires two reverse next instructions to
reach previous source line

PowerPC uses two entry points called the local entry point (LEP) and the
global entry point (GEP).  Normally the LEP is used when calling a
function.  However, if the table of contents (TOC) value in register 2 is
not valid the GEP is called to setup the TOC before execution continues at
the LEP.  When executing in reverse, the function finish_backward sets the
break point at the alternate entry point (GEP).  However if the forward
execution enters via the normal entry point (LEP), the reverse execution
never sees the break point at the GEP of the function.  Reverse execution
continues until the next break point is encountered or the end of the
recorded log is reached causing gdb to stop at the wrong place.

This patch adds a new address to struct execution_control_state to hold the
address of the alternate function start address, known as the GEP on
PowerPC.  The finish_backwards function is updated.  If the stopping point
is between the two entry points (the LEP and GEP on PowerPC), the stepping
range is set to execute back to the alternate entry point (GEP on PowerPC).
Otherwise, a breakpoint is inserted at the normal entry point (LEP on
PowerPC).

Function process_event_stop_test checks uses a stepping range to stop
execution in the caller at the first instruction of the source code line.
Note, on systems that only support one entry point, the address of the two
entry points are the same.

Test finish-reverse-next.exp is updated to include tests for the
reverse-finish command when the function is entered via the normal entry
point (i.e. the LEP) and the alternate entry point (i.e. the GEP).

The patch has been tested on X86 and PowerPC with no regressions.
---
 gdb/infcmd.c                                  | 40 +++++---
 gdb/infrun.c                                  | 16 +++-
 .../gdb.reverse/finish-reverse-next.c         | 39 +++++++-
 .../gdb.reverse/finish-reverse-next.exp       | 96 ++++++++++++++++---
 4 files changed, 160 insertions(+), 31 deletions(-)

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 5d3221e8b90..63e245f7de9 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1722,22 +1722,25 @@ finish_backward (struct finish_command_fsm *sm)
   sal = find_pc_line (func_addr, 0);
 
   frame_info_ptr frame = get_selected_frame (nullptr);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  CORE_ADDR alt_entry_point = sal.pc;
+  CORE_ADDR entry_point = alt_entry_point;
 
-  if (sal.pc != pc)
+  if (gdbarch_skip_entrypoint_p (gdbarch))
     {
-      struct gdbarch *gdbarch = get_frame_arch (frame);
-
-      /* Set a step-resume at the function's entry point.  Once that's
-	 hit, we'll do one more step backwards.  */
-      symtab_and_line sr_sal;
-      sr_sal.pc = sal.pc;
-      sr_sal.pspace = get_frame_program_space (frame);
-      insert_step_resume_breakpoint_at_sal (gdbarch,
-					    sr_sal, null_frame_id);
+      /* Some architectures, like PowerPC use local and global entry points.
+	 There is only one Entry Point (GEP = LEP) for other architectures.
+	 The GEP is an alternate entry point.  The LEP is the normal entry
+	 point.  The value of entry_point was initialized to the alternate
+	 entry point (GEP).  It will be adjusted if the normal entry point
+	 (LEP) was used.  */
+       entry_point = gdbarch_skip_entrypoint (gdbarch, entry_point);
     }
-  else
+
+  if (alt_entry_point <= pc && pc <= entry_point)
     {
-      /* We are exactly at the function entry point.  Note that this
+      /* We are exactly at the function entry point, or between the entry
+	 point on platforms that have two (like PowerPC).  Note that this
 	 can only happen at frame #0.
 
 	 When setting a step range, need to setup the current_symtab and
@@ -1751,8 +1754,17 @@ finish_backward (struct finish_command_fsm *sm)
 
       /* Return using a step range so we will keep stepping back
 	 to the first instruction in the source code line.  */
-      tp->control.step_range_start = sal.pc;
-      tp->control.step_range_end = sal.pc;
+      tp->control.step_range_start = alt_entry_point;
+      tp->control.step_range_end = entry_point;
+    }
+  else
+    {
+      symtab_and_line sr_sal;
+      /* Set a step-resume at the function's entry point.  */
+      sr_sal.pc = entry_point;
+      sr_sal.pspace = get_frame_program_space (frame);
+      insert_step_resume_breakpoint_at_sal (gdbarch,
+					    sr_sal, null_frame_id);
     }
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 183110a049a..a911aec8568 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1868,6 +1868,7 @@ struct execution_control_state
 
   struct target_waitstatus ws;
   int stop_func_filled_in = 0;
+  CORE_ADDR stop_func_alt_start = 0;
   CORE_ADDR stop_func_start = 0;
   CORE_ADDR stop_func_end = 0;
   const char *stop_func_name = nullptr;
@@ -4663,6 +4664,12 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 				    &block);
       ecs->stop_func_name = gsi == nullptr ? nullptr : gsi->print_name ();
 
+      /* PowerPC functions have a Local Entry Point and a Global Entry
+	 Point.  There is only one Entry Point (GEP = LEP) for other
+	 architectures.  Save the alternate entry point address (GEP) for
+	 use later.  */
+      ecs->stop_func_alt_start = ecs->stop_func_start;
+
       /* The call to find_pc_partial_function, above, will set
 	 stop_func_start and stop_func_end to the start and end
 	 of the range containing the stop pc.  If this range
@@ -4679,6 +4686,9 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 	    += gdbarch_deprecated_function_start_offset (gdbarch);
 
 	  if (gdbarch_skip_entrypoint_p (gdbarch))
+	    /* The PowerPC architecture uses two entry points.  Stop at the
+	       regular entry point (LEP on PowerPC) initially.  Will setup a
+	       breakpoint for the alternate entry point (GEP) later.  */
 	    ecs->stop_func_start
 	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
 	}
@@ -6757,7 +6767,7 @@ process_event_stop_test (struct execution_control_state *ecs)
 
 	  /* Return using a step range so we will keep stepping back to the
 	     first instruction in the source code line.  */
-	  tp->control.step_range_start = ecs->stop_func_start;
+	  tp->control.step_range_start = ecs->stop_func_alt_start;
 	  tp->control.step_range_end = ecs->stop_func_start;
 	  keep_going (ecs);
 	  return;
@@ -6894,8 +6904,10 @@ process_event_stop_test (struct execution_control_state *ecs)
 	 (unless it's the function entry point, in which case
 	 keep going back to the call point).  */
       CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
+
       if (stop_pc == ecs->event_thread->control.step_range_start
-	  && stop_pc != ecs->stop_func_start
+	  && (stop_pc < ecs->stop_func_alt_start
+	      || stop_pc > ecs->stop_func_start)
 	  && execution_direction == EXEC_REVERSE)
 	end_stepping_range (ecs);
       else
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
index f90ecbb93cb..0347906961d 100644
--- a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -24,11 +24,37 @@
    This test verifies the fix for gdb bugzilla:
 
    https://sourceware.org/bugzilla/show_bug.cgi?id=29927
-*/
+
+   PowerPC supports two entry points to a function.  The normal entry point
+   is called the local entry point (LEP).  The alternat entry point is called
+   the global entry point (GEP).  The GEP is only used if the table of
+   contents (TOC) value stored in register r2 needs to be setup prior to
+   execution starting at the LEP.  A function call via a function pointer
+   will entry via the GEP.  A normal function call will enter via the LEP.
+
+   This test has been expanded to include tests to verify the reverse-finish
+   command works properly if the function is called via the GEP.  The original
+   test only verified the reverse-finish command for a normal call that used
+   the LEP.  */
 
 int
 function1 (int a, int b)   // FUNCTION1
 {
+  /* The assembly code for this function when compiled for PowerPC is as
+     follows:
+
+     0000000010000758 <function1>:
+     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
+     1000075c:	00 7f 42 38 	addi    r2,r2,32512
+     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
+     10000764:	10 00 01 f8 	std     r0,16(r1)
+     ....
+
+     When the function is called on PowerPC with function1 (a, b) the call
+     enters at the Local Entry Point (LEP).  When the function is called via
+     a function pointer, the Global Entry Point (GEP) for function1 is used.
+     The GEP sets up register 2 before reaching the LEP.
+  */
   int ret = 0;
 
   ret = a + b;
@@ -39,10 +65,19 @@ int
 main(int argc, char* argv[])
 {
   int a, b;
+  int (*funp) (int, int) = &function1;
+
+  /* Call function via Local Entry Point (LEP).  */
 
   a = 1;
   b = 5;
 
-  function1 (a, b);   // CALL FUNCTION
+  function1 (a, b);   // CALL VIA LEP
+
+  /* Call function via Global Entry Point (GEP).  */
+  a = 10;
+  b = 50;
+
+  funp (a, b);        // CALL VIA GEP
   return 0;
 }
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
index 63305c109e1..a9c895dfcd4 100644
--- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -31,6 +31,16 @@
 # This test verifies the fix for gdb bugzilla:
 #   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
 
+# PowerPC supports two entry points to a function.  The normal entry point
+# is called the local entry point (LEP).  The alternat entry point is called
+# the global entry point (GEP).  A function call via a function pointer
+# will entry via the GEP.  A normal function call will enter via the LEP.
+#
+# This test has been expanded to include tests to verify the reverse-finish
+# command works properly if the function is called via the GEP.  The original
+# test only verified the reverse-finish command for a normal call that used
+# the LEP.
+
 if ![supports_reverse] {
     return
 }
@@ -50,30 +60,30 @@ if [supports_process_record] {
 }
 
 
-### TEST 1: reverse finish from the entry point instruction in
-### function1.
+### TEST 1: reverse finish from the entry point instruction (LEP) in
+### function1 when called using the normal entry point (LEP).
 
 # Set breakpoint at call to function1 in main.
-set bp_FUNCTION [gdb_get_line_number "CALL FUNCTION" $srcfile]
-gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
 
 # Continue to break point at function1 call in main.
 gdb_continue_to_breakpoint \
     "stopped at function1 entry point instruction to stepi into function" \
-    ".*$srcfile:$bp_FUNCTION\r\n.*"
+    ".*$srcfile:$bp_LEP_test\r\n.*"
 
 # stepi until we see "{" indicating we entered function1
-repeat_cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
+repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call"
 
-gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
-    "reverse-finish function1 "
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from LEP "
 
 # Check to make sure we stopped at the first instruction in the source code
 # line.  It should only take one reverse next command to get to the previous
 # source line.   If GDB stops at the last instruction in the source code line
 # it will take two reverse next instructions to get to the previous source
 # line.
-gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from LEP"
 
 # Clear the recorded log.
 gdb_test "record stop"  "Process record is stopped.*" \
@@ -84,21 +94,81 @@ gdb_test_no_output "record" "turn on process record for test2"
 ### TEST 2: reverse finish from the body of function1.
 
 # Set breakpoint at call to function1 in main.
-gdb_breakpoint $srcfile:$bp_FUNCTION temporary
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
 
 # Continue to break point at function1 call in main.
 gdb_continue_to_breakpoint \
     "at function1 entry point instruction to step to body of function" \
-    ".*$srcfile:$bp_FUNCTION\r\n.*"
+    ".*$srcfile:$bp_LEP_test\r\n.*"
 
 # do a step instruction to get to the body of the function
 gdb_test "step" ".*int ret = 0;.*" "step test 1"
 
-gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
-    "reverse-finish function1 call from function body"
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from function body"
 
 # Check to make sure we stopped at the first instruction in the source code
 # line.  It should only take one reverse next command to get to the previous
 # source line.
 gdb_test "reverse-next" ".*b = 5;.*" \
     "reverse next at b = 5, from function body"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test2"
+gdb_test_no_output "record" "turn on process record for test3"
+
+
+### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
+
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP"
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.  If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 50;.*" "reverse next at b = 50, call from GEP"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test3"
+gdb_test_no_output "record" "turn on process record for test4"
+
+
+### TEST 4: reverse finish from the body of function 1 when calling using the
+### alternate entrypoint (GEP).
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of funp call" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# Step into body of funp, called via GEP.
+gdb_test "step" ".*int ret = 0;.*" "step test 2"
+
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "reverse-finish function1 GEP call, from function body  "
+
+# Check to make sure we stopped at the first instruction in the source code
+# line.  It should only take one reverse next command to get to the previous
+# source line.  If GDB stops at the last instruction in the source code line
+# it will take two reverse next instructions to get to the previous source
+# line.
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next at b = 50 from function body"
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-20  0:03                                                         ` [PATCH 1/2 version 3] " Carl Love
@ 2023-01-23 19:17                                                           ` Pedro Alves
  2023-01-23 21:13                                                             ` Carl Love
  2023-01-24 15:53                                                             ` [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp Tom de Vries
  0 siblings, 2 replies; 105+ messages in thread
From: Pedro Alves @ 2023-01-23 19:17 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches

On 2023-01-20 12:03 a.m., Carl Love via Gdb-patches wrote:

> X86: reverse-finish fix
> 
> PR record/29927  - reverse-finish requires two reverse next instructions to
> reach previous source line
> 
> Currently on X86, when executing the finish command in reverse, gdb does a
> single step from the first instruction in the callee to get back to the
> caller.  GDB stops on the last instruction in the source code line where
> the call was made.  When stopped at the last instruction of the source code
> line, a reverse next or step command will stop at the first instruction
> of the same source code line thus requiring two step/next commands to
> reach the previous source code line.  It should only require one step/next
> command to reach the previous source code line.
> 
> By contrast, a reverse next or step command from the first line in a
> function stops at the first instruction in the source code line where the
> call was made.

I'd think this was on purpose.  Note that next/step/reverse-{next/step} are line-oriented
stepping commands, they step/next until the previous/next line.  While "finish" is described
as undoing the _function call_.

The manual says:

 reverse-finish
 Just as the finish command takes you to the point where the current function returns,
 reverse-finish takes you to the point where it was called. Instead of ending up at the end of
 the current function invocation, you end up at the beginning.

Say you have a line with multiple statements involving multiple function calls.
The simplest would be:

  func1 ();  func2 ();

Say you'd stopped inside 'func2'.  If you do finish there, in current master gdb
stops at the call to 'func2', and you can then decide to reverse step into 'func1'.
While with your change, reverse-finish in func2 will make gdb stop at the beginning
of the line, before the call to func1.

Thus I'm really not convinced (yet) this change is a good one.  It removes
a user choice.  You can always do reverse-next/step do get what you want
reverse-finish do to, already.

Pedro Alves

> 
> This patch fixes the reverse finish command so it will stop at the first
> instruction of the source line where the function call was made.  The
> behavior on X86 for the reverse-finish command now matches doing a
> reverse-next from the beginning of the function.
> 
> The proceed_to_finish flag in struct thread_control_state is no longer
> used.  This patch removes the declaration, initialization and setting of
> the flag.
> 
> This patch requires a number of regression tests to be updated.  Test
> gdb.mi/mi-reverse.exp no longer needs to execute two steps to get to the
> previous line.  The gdb output for tests gdb.reverse/until-precsave.exp
> and gdb.reverse/until-reverse.exp changed slightly.  The expected result in
> tests gdb.reverse/amd64-failcall-reverse.exp and
> gdb.reverse/singlejmp-reverse.exp are updated to the correct expected
> result.  The expected result in btrace/tailcall.exp also changes since
> the reverse-next now only steps back thru one function call not two
> function calls.
> 
> This patch adds a new test gdb.reverse/finish-reverse-next.exp to test the
> reverse-finish command when returning from the entry point and from the
> body of the function.
> 
> The step_until proceedure in test gdb.reverse/step-indirect-call-thunk.exp

Typo: proceedure -> procedure

> was moved to lib/gdb.exp and renamed cmd_until.

"cmd_until" here is stale.

> 
> The patch has been tested on X86 and PowerPC to verify no additional
> regression failures occured.

occured -> occurred

> 
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> ---
>  gdb/gdbthread.h                               |   4 -
>  gdb/infcall.c                                 |   3 -
>  gdb/infcmd.c                                  |  32 +++---
>  gdb/infrun.c                                  |  40 +++----
>  gdb/testsuite/gdb.btrace/tailcall.exp         |   4 +-
>  gdb/testsuite/gdb.mi/mi-reverse.exp           |   9 +-
>  .../gdb.reverse/amd64-tailcall-reverse.exp    |   5 +-
>  .../gdb.reverse/finish-reverse-next.c         |  48 ++++++++
>  .../gdb.reverse/finish-reverse-next.exp       | 104 ++++++++++++++++++
>  .../gdb.reverse/singlejmp-reverse.exp         |   5 +-
>  .../gdb.reverse/step-indirect-call-thunk.exp  |  49 ++-------
>  gdb/testsuite/gdb.reverse/until-precsave.exp  |   2 +-
>  gdb/testsuite/gdb.reverse/until-reverse.exp   |   2 +-
>  gdb/testsuite/lib/gdb.exp                     |  33 ++++++
>  14 files changed, 232 insertions(+), 108 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
>  create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> 
> diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
> index 11d69fceab0..e4edff2d621 100644
> --- a/gdb/gdbthread.h
> +++ b/gdb/gdbthread.h
> @@ -150,10 +150,6 @@ struct thread_control_state
>       the finished single step.  */
>    int trap_expected = 0;
>  
> -  /* Nonzero if the thread is being proceeded for a "finish" command
> -     or a similar situation when return value should be printed.  */
> -  int proceed_to_finish = 0;
> -
>    /* Nonzero if the thread is being proceeded for an inferior function
>       call.  */
>    int in_infcall = 0;
> diff --git a/gdb/infcall.c b/gdb/infcall.c
> index e09904f9a35..116605c43ef 100644
> --- a/gdb/infcall.c
> +++ b/gdb/infcall.c
> @@ -625,9 +625,6 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
>  
>    disable_watchpoints_before_interactive_call_start ();
>  
> -  /* We want to print return value, please...  */
> -  call_thread->control.proceed_to_finish = 1;
> -
>    try
>      {
>        /* Infcalls run synchronously, in the foreground.  */
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 0497ad05091..9c42efeae8d 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1721,19 +1721,10 @@ finish_backward (struct finish_command_fsm *sm)
>  
>    sal = find_pc_line (func_addr, 0);
>  
> -  tp->control.proceed_to_finish = 1;
> -  /* Special case: if we're sitting at the function entry point,
> -     then all we need to do is take a reverse singlestep.  We
> -     don't need to set a breakpoint, and indeed it would do us
> -     no good to do so.
> -
> -     Note that this can only happen at frame #0, since there's
> -     no way that a function up the stack can have a return address
> -     that's equal to its entry point.  */
> +  frame_info_ptr frame = get_selected_frame (nullptr);
>  
>    if (sal.pc != pc)
>      {
> -      frame_info_ptr frame = get_selected_frame (nullptr);
>        struct gdbarch *gdbarch = get_frame_arch (frame);
>  
>        /* Set a step-resume at the function's entry point.  Once that's
> @@ -1743,16 +1734,22 @@ finish_backward (struct finish_command_fsm *sm)
>        sr_sal.pspace = get_frame_program_space (frame);
>        insert_step_resume_breakpoint_at_sal (gdbarch,
>  					    sr_sal, null_frame_id);
> -
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>      }
>    else
>      {
> -      /* We're almost there -- we just need to back up by one more
> -	 single-step.  */
> -      tp->control.step_range_start = tp->control.step_range_end = 1;
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> +      /* We are exactly at the function entry point.  Note that this
> +	 can only happen at frame #0.
> +
> +	 When setting a step range, need to call set_step_info
> +	 to setup the current_line/symtab fields as well.  */
> +      set_step_info (tp, frame, find_pc_line (pc, 0));
> +
> +      /* Return using a step range so we will keep stepping back
> +	 to the first instruction in the source code line.  */
> +      tp->control.step_range_start = sal.pc;
> +      tp->control.step_range_end = sal.pc;
>      }
> +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>  }
>  
>  /* finish_forward -- helper function for finish_command.  FRAME is the
> @@ -1778,9 +1775,6 @@ finish_forward (struct finish_command_fsm *sm, frame_info_ptr frame)
>  
>    set_longjmp_breakpoint (tp, frame_id);
>  
> -  /* We want to print return value, please...  */
> -  tp->control.proceed_to_finish = 1;
> -
>    proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>  }
>  
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 181d961d80d..86e5ef1ed12 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -2748,8 +2748,6 @@ clear_proceed_status_thread (struct thread_info *tp)
>  
>    tp->control.stop_step = 0;
>  
> -  tp->control.proceed_to_finish = 0;
> -
>    tp->control.stepping_command = 0;
>  
>    /* Discard any remaining commands or status from previous stop.  */
> @@ -6737,31 +6735,27 @@ process_event_stop_test (struct execution_control_state *ecs)
>  
>      case BPSTAT_WHAT_STEP_RESUME:
>        infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
> -
>        delete_step_resume_breakpoint (ecs->event_thread);
> -      if (ecs->event_thread->control.proceed_to_finish
> -	  && execution_direction == EXEC_REVERSE)
> +      fill_in_stop_func (gdbarch, ecs);
> +
> +      if (execution_direction == EXEC_REVERSE)
>  	{
>  	  struct thread_info *tp = ecs->event_thread;
> +	  /* We are finishing a function in reverse or stepping over a function
> +	     call in reverse, and just hit the step-resume breakpoint at the
> +	     start address of the function, and we're almost there -- just need
> +	     to back up to the function call.  */
>  
> -	  /* We are finishing a function in reverse, and just hit the
> -	     step-resume breakpoint at the start address of the
> -	     function, and we're almost there -- just need to back up
> -	     by one more single-step, which should take us back to the
> -	     function call.  */
> -	  tp->control.step_range_start = tp->control.step_range_end = 1;
> -	  keep_going (ecs);
> -	  return;
> -	}
> -      fill_in_stop_func (gdbarch, ecs);
> -      if (ecs->event_thread->stop_pc () == ecs->stop_func_start
> -	  && execution_direction == EXEC_REVERSE)
> -	{
> -	  /* We are stepping over a function call in reverse, and just
> -	     hit the step-resume breakpoint at the start address of
> -	     the function.  Go back to single-stepping, which should
> -	     take us back to the function call.  */
> -	  ecs->event_thread->stepping_over_breakpoint = 1;
> +	  stop_pc_sal = find_pc_line (ecs->event_thread->stop_pc (), 0);
> +
> +	  /* When setting a step range, need to call set_step_info
> +	     to setup the current_line/symtab fields as well.  */
> +	  set_step_info (tp, frame, stop_pc_sal);
> +
> +	  /* Return using a step range so we will keep stepping back to the
> +	     first instruction in the source code line.  */
> +	  tp->control.step_range_start = ecs->stop_func_start;
> +	  tp->control.step_range_end = ecs->stop_func_start;
>  	  keep_going (ecs);
>  	  return;
>  	}
> diff --git a/gdb/testsuite/gdb.btrace/tailcall.exp b/gdb/testsuite/gdb.btrace/tailcall.exp
> index 028e03fc6f6..fa254664a09 100644
> --- a/gdb/testsuite/gdb.btrace/tailcall.exp
> +++ b/gdb/testsuite/gdb.btrace/tailcall.exp
> @@ -102,9 +102,9 @@ gdb_test "reverse-step" "\[^\r\n\]*main \\(\\) at tailcall.c:37\r\n.*" \
>      "reverse-step.2"
>  gdb_test "next" "\[^\r\n\]*38.*" \
>      "next.1"
> -gdb_test "reverse-next" "\[^\r\n\]*main \\(\\) at tailcall.c:37\r\n.*" \
> +gdb_test "reverse-next" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
>      "reverse-next.1"
> -gdb_test "step" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
> +gdb_test "step" "\[^\r\n\]*bar \\(\\) at tailcall.c:24\r\n.*" \
>      "step.1"
>  gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:38\r\n.*" \
>      "finish.2"
> diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
> index d631beb17c8..30635ab1754 100644
> --- a/gdb/testsuite/gdb.mi/mi-reverse.exp
> +++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
> @@ -97,15 +97,10 @@ proc test_controlled_execution_reverse {} {
>  	"basics.c" $line_main_callme_1 "" \
>  	"reverse finish from callme"
>  
> -    # Test exec-reverse-next
> -    #   It takes two steps to get back to the previous line,
> -    #   as the first step moves us to the start of the current line,
> -    #   and the one after that moves back to the previous line.
> -
> -    mi_execute_to "exec-next --reverse 2" \
> +    mi_execute_to "exec-next --reverse" \
>   	"end-stepping-range" "main" "" \
>   	"basics.c" $line_main_hello "" \
> - 	"reverse next to get over the call to do_nothing"
> +	"reverse next to get over the call to do_nothing"
>  
>      # Test exec-reverse-step
>  
> diff --git a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> index 52a87faabf7..9964b4f8e4b 100644
> --- a/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> +++ b/gdb/testsuite/gdb.reverse/amd64-tailcall-reverse.exp
> @@ -44,6 +44,5 @@ if [supports_process_record] {
>  gdb_test "next" {f \(\);} "next to f"
>  gdb_test "next" {v = 3;} "next to v = 3"
>  
> -# FAIL was:
> -# 29        g ();
> -gdb_test "reverse-next" {f \(\);}
> +# Reverse step back into f ().  Puts us at call to g () in function f ().
> +gdb_test "reverse-next" {g \(\);}
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> new file mode 100644
> index 00000000000..f90ecbb93cb
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> @@ -0,0 +1,48 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2012-2023 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +/* The reverse finish command should return from a function and stop on
> +   the first instruction of the source line where the function call is made.
> +   Specifically, the behavior should match doing a reverse next from the
> +   first instruction in the function.  GDB should only require one reverse
> +   step or next statement to reach the previous source code line.
> +
> +   This test verifies the fix for gdb bugzilla:
> +
> +   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +*/
> +
> +int
> +function1 (int a, int b)   // FUNCTION1
> +{
> +  int ret = 0;
> +
> +  ret = a + b;
> +  return ret;
> +}
> +
> +int
> +main(int argc, char* argv[])
> +{
> +  int a, b;
> +
> +  a = 1;
> +  b = 5;
> +
> +  function1 (a, b);   // CALL FUNCTION
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> new file mode 100644
> index 00000000000..63305c109e1
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> @@ -0,0 +1,104 @@
> +# Copyright 2008-2023 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +# This file is part of the GDB testsuite.  It tests reverse stepping.
> +# Lots of code borrowed from "step-test.exp".
> +
> +# The reverse finish command should return from a function and stop on
> +# the first instruction of the source line where the function call is made.
> +# Specifically, the behavior should match doing a reverse next from the
> +# first instruction in the function.  GDB should only take one reverse step
> +# or next statement to reach the previous source code line.
> +
> +# This testcase verifies the reverse-finish command stops at the first
> +# instruction in the source code line where the function was called.  There
> +# are two scenarios that must be checked:
> +#   1) gdb is at the entry point instruction for the function
> +#   2) gdb is in the body of the function.
> +
> +# This test verifies the fix for gdb bugzilla:
> +#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +if ![supports_reverse] {
> +    return
> +}
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
> +    return -1
> +}
> +
> +runto_main
> +set target_remote [gdb_is_target_remote]
> +
> +if [supports_process_record] {
> +    # Activate process record/replay.
> +    gdb_test_no_output "record" "turn on process record for test1"
> +}
> +
> +
> +### TEST 1: reverse finish from the entry point instruction in
> +### function1.
> +
> +# Set breakpoint at call to function1 in main.
> +set bp_FUNCTION [gdb_get_line_number "CALL FUNCTION" $srcfile]
> +gdb_breakpoint $srcfile:$bp_FUNCTION temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into function" \
> +    ".*$srcfile:$bp_FUNCTION\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function1
> +repeat_cmd_until "stepi" "CALL FUNCTION" "{" "stepi into function1 call"
> +
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
> +    "reverse-finish function1 "
> +
> +# Check to make sure we stopped at the first instruction in the source code
> +# line.  It should only take one reverse next command to get to the previous
> +# source line.   If GDB stops at the last instruction in the source code line
> +# it will take two reverse next instructions to get to the previous source
> +# line.
> +gdb_test "reverse-next" ".*b = 5;.*" "reverse next at b = 5, call from function"
> +
> +# Clear the recorded log.
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test1"
> +gdb_test_no_output "record" "turn on process record for test2"
> +
> +
> +### TEST 2: reverse finish from the body of function1.
> +
> +# Set breakpoint at call to function1 in main.
> +gdb_breakpoint $srcfile:$bp_FUNCTION temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "at function1 entry point instruction to step to body of function" \
> +    ".*$srcfile:$bp_FUNCTION\r\n.*"
> +
> +# do a step instruction to get to the body of the function
> +gdb_test "step" ".*int ret = 0;.*" "step test 1"
> +
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL FUNCTION.*" \
> +    "reverse-finish function1 call from function body"
> +
> +# Check to make sure we stopped at the first instruction in the source code
> +# line.  It should only take one reverse next command to get to the previous
> +# source line.
> +gdb_test "reverse-next" ".*b = 5;.*" \
> +    "reverse next at b = 5, from function body"
> diff --git a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> index 1ca7c2ce559..eb03051625a 100644
> --- a/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> +++ b/gdb/testsuite/gdb.reverse/singlejmp-reverse.exp
> @@ -56,7 +56,4 @@ gdb_test "next" {v = 3;} "next to v = 3"
>  # {
>  gdb_test "reverse-step" {nodebug \(\);}
>  
> -# FAIL was:
> -# No more reverse-execution history.
> -# {
> -gdb_test "reverse-next" {f \(\);}
> +gdb_test "reverse-next" {g \(\);}
> diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> index ad637899e5b..b82e5663bd5 100644
> --- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> +++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> @@ -39,39 +39,6 @@ if { ![runto_main] } {
>      return -1
>  }
>  
> -# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
> -#
> -#  COMMAND is a stepping command
> -#  CURRENT is a string matching the current location
> -#  TARGET  is a string matching the target location
> -#  TEST    is the test name
> -#
> -# The function issues repeated COMMANDs as long as the location matches
> -# CURRENT up to a maximum of 100 steps.
> -#
> -# TEST passes if the resulting location matches TARGET and fails
> -# otherwise.
> -#
> -proc step_until { command current target test } {
> -    global gdb_prompt
> -
> -    set count 0
> -    gdb_test_multiple "$command" "$test" {
> -        -re "$current.*$gdb_prompt $" {
> -            incr count
> -            if { $count < 100 } {
> -                send_gdb "$command\n"
> -                exp_continue
> -            } else {
> -                fail "$test"
> -            }
> -        }
> -        -re "$target.*$gdb_prompt $" {
> -            pass "$test"
> -        }
> -    }
> -}
> -
>  gdb_test_no_output "record"
>  gdb_test "next" ".*" "record trace"
>  
> @@ -91,20 +58,20 @@ gdb_test "reverse-next" "apply\.2.*" \
>      "reverse-step through thunks and over inc"
>  
>  # We can use instruction stepping to step into thunks.
> -step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
> -step_until "stepi" "indirect_thunk" "inc" \
> +repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
> +repeat_cmd_until "stepi" "indirect_thunk" "inc" \
>      "stepi out of call thunk into inc"
>  set alphanum_re "\[a-zA-Z0-9\]"
>  set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
> -step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
> -step_until "stepi" "return_thunk" "apply" \
> +repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
> +repeat_cmd_until "stepi" "return_thunk" "apply" \
>      "stepi out of return thunk back into apply"
>  
> -step_until "reverse-stepi" "apply" "return_thunk" \
> +repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
>      "reverse-stepi into return thunk"
> -step_until "reverse-stepi" "return_thunk" "inc" \
> +repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
>      "reverse-stepi out of return thunk into inc"
> -step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
> +repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
>      "reverse-stepi into call thunk"
> -step_until "reverse-stepi" "indirect_thunk" "apply" \
> +repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
>      "reverse-stepi out of call thunk into apply"
> diff --git a/gdb/testsuite/gdb.reverse/until-precsave.exp b/gdb/testsuite/gdb.reverse/until-precsave.exp
> index 0c2d7537cd6..777aec94ac1 100644
> --- a/gdb/testsuite/gdb.reverse/until-precsave.exp
> +++ b/gdb/testsuite/gdb.reverse/until-precsave.exp
> @@ -142,7 +142,7 @@ gdb_test "advance marker2" \
>  # Finish out to main scope (backward)
>  
>  gdb_test "finish" \
> -    " in main .*$srcfile:$bp_location20.*" \
> +    "main .*$srcfile:$bp_location20.*" \
>      "reverse-finish from marker2"
>  
>  # Advance backward to last line of factorial (outer invocation)
> diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp b/gdb/testsuite/gdb.reverse/until-reverse.exp
> index 23fc881dbf2..3a05953329f 100644
> --- a/gdb/testsuite/gdb.reverse/until-reverse.exp
> +++ b/gdb/testsuite/gdb.reverse/until-reverse.exp
> @@ -113,7 +113,7 @@ gdb_test "advance marker2" \
>  # Finish out to main scope (backward)
>  
>  gdb_test "finish" \
> -    " in main .*$srcfile:$bp_location20.*" \
> +    "main .*$srcfile:$bp_location20.*" \
>      "reverse-finish from marker2"
>  
>  # Advance backward to last line of factorial (outer invocation)
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index c41d4698d66..234c21a04ea 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -9301,6 +9301,39 @@ proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
>      }
>  }
>  
> +# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
> +#
> +#  COMMAND is a stepping command
> +#  CURRENT is a string matching the current location
> +#  TARGET  is a string matching the target location
> +#  TEST    is the test name
> +#
> +# The function issues repeated COMMANDs as long as the location matches
> +# CURRENT up to a maximum of 100 steps.
> +#
> +# TEST passes if the resulting location matches TARGET and fails
> +# otherwise.
> +
> +proc repeat_cmd_until { command current target test } {
> +    global gdb_prompt
> +
> +    set count 0
> +    gdb_test_multiple "$command" "$test" {
> +	-re "$current.*$gdb_prompt $" {
> +	    incr count
> +	    if { $count < 100 } {
> +		send_gdb "$command\n"
> +		exp_continue
> +	    } else {
> +		fail "$test"
> +	    }
> +	}
> +	-re "$target.*$gdb_prompt $" {
> +	    pass "$test"
> +	}
> +    }
> +}
> +
>  # Check if the compiler emits epilogue information associated
>  # with the closing brace or with the last statement line.
>  #
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-23 19:17                                                           ` Pedro Alves
@ 2023-01-23 21:13                                                             ` Carl Love
  2023-01-24 14:08                                                               ` Pedro Alves
  2023-01-24 15:53                                                             ` [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp Tom de Vries
  1 sibling, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-23 21:13 UTC (permalink / raw)
  To: Pedro Alves, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches

Pedro:

On Mon, 2023-01-23 at 19:17 +0000, Pedro Alves wrote:
> > Currently on X86, when executing the finish command in reverse, gdb
> > does a
> > single step from the first instruction in the callee to get back to
> > the
> > caller.  GDB stops on the last instruction in the source code line
> > where
> > the call was made.  When stopped at the last instruction of the
> > source code
> > line, a reverse next or step command will stop at the first
> > instruction
> > of the same source code line thus requiring two step/next commands
> > to
> > reach the previous source code line.  It should only require one
> > step/next
> > command to reach the previous source code line.
> > 
> > By contrast, a reverse next or step command from the first line in
> > a
> > function stops at the first instruction in the source code line
> > where the
> > call was made.
> 
> I'd think this was on purpose.  Note that next/step/reverse-
> {next/step} are line-oriented
> stepping commands, they step/next until the previous/next line. 
> While "finish" is described
> as undoing the _function call_.
> 
> The manual says:
> 
>  reverse-finish
>  Just as the finish command takes you to the point where the current
> function returns,
>  reverse-finish takes you to the point where it was called. Instead
> of ending up at the end of
>  the current function invocation, you end up at the beginning.
> 
> Say you have a line with multiple statements involving multiple
> function calls.
> The simplest would be:
> 
>   func1 ();  func2 ();
> 
> Say you'd stopped inside 'func2'.  If you do finish there, in current
> master gdb
> stops at the call to 'func2', and you can then decide to reverse step
> into 'func1'.

I don't think you followed the issue.  

So, if you are in func2 and do a reverse-finish, without the patch gdb
stops on the last instruction for the line that calls func2.  Now if
you issue a reverse-step, you stop at the first instruction for the
call to func2, i.e. you are still on the same source code line.  You
have not stepped back into func1 like you wanted to.  Now you have to
issue a second reverse-step to get into func1.   With the patch, you
issue the reverse-finish from func2 and stop at the first instruction
in the line that calls func2.  Now when you issue the reverse-step you
step back into func1 as expected.

> While with your change, reverse-finish in func2 will make gdb stop at
> the beginning
> of the line, before the call to func1.
> 
> Thus I'm really not convinced (yet) this change is a good one.  It
> removes
> a user choice.  You can always do reverse-next/step do get what you
> want
> reverse-finish do to, already.

                                    Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-23 21:13                                                             ` Carl Love
@ 2023-01-24 14:08                                                               ` Pedro Alves
  2023-01-24 14:23                                                                 ` Bruno Larsen
                                                                                   ` (3 more replies)
  0 siblings, 4 replies; 105+ messages in thread
From: Pedro Alves @ 2023-01-24 14:08 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches

On 2023-01-23 9:13 p.m., Carl Love wrote:
> Pedro:
> 
> On Mon, 2023-01-23 at 19:17 +0000, Pedro Alves wrote:
>>> Currently on X86, when executing the finish command in reverse, gdb
>>> does a
>>> single step from the first instruction in the callee to get back to
>>> the
>>> caller.  GDB stops on the last instruction in the source code line
>>> where
>>> the call was made.  When stopped at the last instruction of the
>>> source code
>>> line, a reverse next or step command will stop at the first
>>> instruction
>>> of the same source code line thus requiring two step/next commands
>>> to
>>> reach the previous source code line.  It should only require one
>>> step/next
>>> command to reach the previous source code line.
>>>
>>> By contrast, a reverse next or step command from the first line in
>>> a
>>> function stops at the first instruction in the source code line
>>> where the
>>> call was made.
>>
>> I'd think this was on purpose.  Note that next/step/reverse-
>> {next/step} are line-oriented
>> stepping commands, they step/next until the previous/next line. 
>> While "finish" is described
>> as undoing the _function call_.
>>
>> The manual says:
>>
>>  reverse-finish
>>  Just as the finish command takes you to the point where the current
>> function returns,
>>  reverse-finish takes you to the point where it was called. Instead
>> of ending up at the end of
>>  the current function invocation, you end up at the beginning.
>>
>> Say you have a line with multiple statements involving multiple
>> function calls.
>> The simplest would be:
>>
>>   func1 ();  func2 ();
>>
>> Say you'd stopped inside 'func2'.  If you do finish there, in current
>> master gdb
>> stops at the call to 'func2', and you can then decide to reverse step
>> into 'func1'.
> 
> I don't think you followed the issue.  

Totally possible!

> 
> So, if you are in func2 and do a reverse-finish, without the patch gdb
> stops on the last instruction for the line that calls func2.  

Right.

> Now if
> you issue a reverse-step, you stop at the first instruction for the
> call to func2, i.e. you are still on the same source code line.  

Wait.  That right there sounds bogus.  The source line looks like:

   func1 ();  func2 ();

so stepping backwards over that line should always stop at the first
instruction of the line, not in the middle.  Let's simplify this.

Here's the full source code of my example:

(gdb) list 1
1       void func1 ()
2       {
3       }
4
5       void func2 ()
6       {
7       }
8
9       int main ()
10      {
11        func1 (); func2 ();
12      }

Compiled with:

 $ gcc reverse.c -o reverse -g3 -O0
 $ gcc -v
 ...
 gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)

Now let's debug it with target record, using current gdb git master (f3d8ae90b236),
without your patch:

 $ gdb ~/reverse
 GNU gdb (GDB) 14.0.50.20230124-git
 ...
 Reading symbols from /home/pedro/reverse...
 (gdb) start
 Temporary breakpoint 1 at 0x1147: file reverse.c, line 11.
 Starting program: /home/pedro/reverse 
 [Thread debugging using libthread_db enabled]
 Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
 
 Temporary breakpoint 1, main () at reverse.c:11
 11        func1 (); func2 ();
 (gdb) record 

 (gdb) disassemble /s
 Dump of assembler code for function main:
 reverse.c:
 10      {
    0x000055555555513f <+0>:     endbr64
    0x0000555555555143 <+4>:     push   %rbp
    0x0000555555555144 <+5>:     mov    %rsp,%rbp
 
 11        func1 (); func2 ();
 => 0x0000555555555147 <+8>:     mov    $0x0,%eax
    0x000055555555514c <+13>:    call   0x555555555129 <func1>
    0x0000555555555151 <+18>:    mov    $0x0,%eax
    0x0000555555555156 <+23>:    call   0x555555555134 <func2>
    0x000055555555515b <+28>:    mov    $0x0,%eax
 
 12      }
    0x0000555555555160 <+33>:    pop    %rbp
    0x0000555555555161 <+34>:    ret
 End of assembler dump.

 (gdb) n
 12      }

So far so good, a "next" stepped over the whole of line 11 and stopped at line 12.

Let's confirm where we are now:

 (gdb) disassemble /s
 Dump of assembler code for function main:
 reverse.c:
 10      {
    0x000055555555513f <+0>:     endbr64
    0x0000555555555143 <+4>:     push   %rbp
    0x0000555555555144 <+5>:     mov    %rsp,%rbp
 
 11        func1 (); func2 ();
    0x0000555555555147 <+8>:     mov    $0x0,%eax
    0x000055555555514c <+13>:    call   0x555555555129 <func1>
    0x0000555555555151 <+18>:    mov    $0x0,%eax
    0x0000555555555156 <+23>:    call   0x555555555134 <func2>
    0x000055555555515b <+28>:    mov    $0x0,%eax
 
 12      }
 => 0x0000555555555160 <+33>:    pop    %rbp
    0x0000555555555161 <+34>:    ret
 End of assembler dump.

Good, we're at the first instruction of line 12.

Now let's undo the "next", with "reverse-next":

 (gdb) reverse-next
 11        func1 (); func2 ();

Seemingly stopped at line 11.  Let's see exactly where:

 (gdb) disassemble /s
 Dump of assembler code for function main:
 reverse.c:
 10      {
    0x000055555555513f <+0>:     endbr64
    0x0000555555555143 <+4>:     push   %rbp
    0x0000555555555144 <+5>:     mov    %rsp,%rbp
 
 11        func1 (); func2 ();
    0x0000555555555147 <+8>:     mov    $0x0,%eax
    0x000055555555514c <+13>:    call   0x555555555129 <func1>
 => 0x0000555555555151 <+18>:    mov    $0x0,%eax
    0x0000555555555156 <+23>:    call   0x555555555134 <func2>
    0x000055555555515b <+28>:    mov    $0x0,%eax
 
 12      }
    0x0000555555555160 <+33>:    pop    %rbp
    0x0000555555555161 <+34>:    ret
 End of assembler dump.
 (gdb) 

And lo, we stopped in the middle of line 11!  That is a bug, we should have stepped
back all the way to the beginning of the line.  The "reverse-next" should have fully
undone the prior "next" command.  Here's the same thing without the distracting
disassemble commands:

 (gdb) b 11
 Breakpoint 1 at 0x1147: file reverse.c, line 11.
 (gdb) r
 Starting program: /home/pedro/reverse 
 [Thread debugging using libthread_db enabled]
 Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
 
 Breakpoint 1, main () at reverse.c:11
 11        func1 (); func2 ();
 (gdb) p $pc
 $1 = (void (*)()) 0x555555555147 <main+8>
 (gdb) record 
 (gdb) next
 12      }
 (gdb) reverse-next
 11        func1 (); func2 ();
 (gdb) p $pc
 $2 = (void (*)()) 0x555555555151 <main+18>
 (gdb) 


This:

 next -> reverse-next -> next -> reverse-next

... should leave you at the same instruction.  But it doesn't in this example!

How does this happen?  Let's look at the line table as seen by GDB:

 (gdb) maint info line-table reverse.c
 objfile: /home/pedro/reverse ((struct objfile *) 0x55dd5df77c50)
 compunit_symtab: reverse.c ((struct compunit_symtab *) 0x55dd5de6b2e0)
 symtab: /home/pedro/reverse.c ((struct symtab *) 0x55dd5de6b360)
 linetable: ((struct linetable *) 0x55dd5dfd3290):
 INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END 
 0      2      0x0000555555555129 Y                    
 1      3      0x0000555555555131 Y                    
 2      6      0x0000555555555134 Y                    
 3      7      0x000055555555513c Y                    
 4      10     0x000055555555513f Y                    
 5      11     0x0000555555555147 Y                      <<< here 
 6      11     0x0000555555555151 Y                      <<< here
 7      12     0x0000555555555160 Y                    
 8      END    0x0000555555555162 Y                    

Ah, there are two entries for line 11, both marked with IS-STMT.  So when
stepping backward GDB only considered the region with index 6, that's why it
stopped at 0x0000555555555151.



Let's look at what we get with clang instead (Ubuntu clang version 14.0.0-1ubuntu1) :

 (gdb) maintenance info line-table reverse.c
 objfile: /home/pedro/reverse.clang ((struct objfile *) 0x5576be591ca0)
 compunit_symtab: reverse.c ((struct compunit_symtab *) 0x5576be485300)
 symtab: /home/pedro/reverse.c ((struct symtab *) 0x5576be485380)
 linetable: ((struct linetable *) 0x5576be5ec8e0):
 INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END 
 0      2      0x0000555555555130 Y                    
 1      3      0x0000555555555134 Y       Y            
 2      6      0x0000555555555140 Y                    
 3      7      0x0000555555555144 Y       Y            
 4      10     0x0000555555555150 Y                    
 5      11     0x0000555555555154 Y       Y            
 6      11     0x0000555555555159                      
 7      12     0x000055555555515e Y                    
 8      END    0x0000555555555162 Y                    

Note no IS-STMT for the second range.  And let's look at how GDB behaves with it:

 (gdb) b 11
 Breakpoint 1 at 0x1154: file reverse.c, line 11.
 (gdb) r
 Starting program: /home/pedro/reverse.clang 
 [Thread debugging using libthread_db enabled]
 Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
 
 Breakpoint 1, main () at reverse.c:11
 11        func1 (); func2 ();
 (gdb) record
 (gdb) p $pc
 $1 = (void (*)()) 0x555555555154 <main+4>
 (gdb) n
 12      }
 (gdb) reverse-next
 
 No more reverse-execution history.
 main () at reverse.c:11
 11        func1 (); func2 ();
 (gdb) p $pc
 $2 = (void (*)()) 0x555555555154 <main+4>
 (gdb) 

Bingo.  reverse-next fully stepped the whole line backwards.

> You
> have not stepped back into func1 like you wanted to.  Now you have to
> issue a second reverse-step to get into func1.   With the patch, you
> issue the reverse-finish from func2 and stop at the first instruction
> in the line that calls func2.  Now when you issue the reverse-step you
> step back into func1 as expected.
> 

So this fix is assuming that the reverse step stops in the middle of a
line, which I think is the real bug to fix.  Once that is fixed, then
you will no longer need two reverse-steps after reverse-finish.

Here's what you get with current master without your patch, but using
the test program compiled with clang.  Actually, let's use a slightly
modified program to force clang to emit some instructions between
the two calls.  Like this:

 $ cat reverse.c
 void func1 (int i)
 {
 }
 
 void func2 (int i)
 {
 }
 
 int main (int argc, char **argv)
 {
   func1 (argc); func2 (argc);
 }

Alright, here's the gdb session, with clang, no gdb patch:

 Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc48) at reverse.c:11
 11        func1 (argc); func2 (argc);
 (gdb) disassemble /s
 Dump of assembler code for function main:
 reverse.c:
 10      {
    0x0000555555555150 <+0>:     push   %rbp
    0x0000555555555151 <+1>:     mov    %rsp,%rbp
    0x0000555555555154 <+4>:     sub    $0x10,%rsp
    0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
    0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
 
 11        func1 (argc); func2 (argc);
 => 0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
    0x0000555555555162 <+18>:    call   0x555555555130 <func1>
    0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
    0x000055555555516a <+26>:    call   0x555555555140 <func2>
 
 12      }
    0x000055555555516f <+31>:    xor    %eax,%eax
    0x0000555555555171 <+33>:    add    $0x10,%rsp
    0x0000555555555175 <+37>:    pop    %rbp
    0x0000555555555176 <+38>:    ret
 End of assembler dump.
 (gdb) record 
 (gdb) b func2
 Breakpoint 2 at 0x555555555147: file reverse.c, line 7.
 (gdb) c
 Continuing.
 
 Breakpoint 2, func2 (i=1) at reverse.c:7
 7       }
 (gdb) reverse-finish 
 Run back to call of #0  func2 (i=1) at reverse.c:7
 0x000055555555516a in main (argc=1, argv=0x7fffffffdc48) at reverse.c:11
 11        func1 (argc); func2 (argc);
 (gdb) disassemble /s
 Dump of assembler code for function main:
 reverse.c:
 10      {
    0x0000555555555150 <+0>:     push   %rbp
    0x0000555555555151 <+1>:     mov    %rsp,%rbp
    0x0000555555555154 <+4>:     sub    $0x10,%rsp
    0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
    0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
 
 11        func1 (argc); func2 (argc);
    0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
    0x0000555555555162 <+18>:    call   0x555555555130 <func1>
    0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
 => 0x000055555555516a <+26>:    call   0x555555555140 <func2>
 
 12      }
    0x000055555555516f <+31>:    xor    %eax,%eax
    0x0000555555555171 <+33>:    add    $0x10,%rsp
    0x0000555555555175 <+37>:    pop    %rbp
    0x0000555555555176 <+38>:    ret
 End of assembler dump.
 (gdb) reverse-step
 func1 (i=1) at reverse.c:3
 3       }
 (gdb) 
 
 
Note how a single reverse-step after the reverse-finish immediately
stepped backwards into func1.  Exactly how I describing it originally.

With your patch, you'd break reverse-finish with clang:

 (gdb) record 
 (gdb) b func2
 Breakpoint 2 at 0x555555555147: file reverse.c, line 7.
 (gdb) c
 Continuing.

 Breakpoint 2, func2 (i=1) at reverse.c:7
 7       }
 (gdb) reverse-finish 
 Run back to call of #0  func2 (i=1) at reverse.c:7
 func1 (i=1) at reverse.c:3
 3       }
 (gdb) 

GDB stopped at line 3, info func1 which means it stepped too far without
stopping at func2's call site.

GDB is misbehaving with GCC's debug info.  I suspect the reason we get
the two line entries for line 11 and both with IS-STMT is because GCC emits
column debug info nowadays by default.   Here's what e.g.,
"llvm-dwarfdump --debug-line reverse" shows:

 ~~~
 Address            Line   Column File   ISA Discriminator Flags
 ------------------ ------ ------ ------ --- ------------- -------------
 0x0000000000001129      2      1      1   0             0  is_stmt
 0x0000000000001131      3      1      1   0             0  is_stmt
 0x0000000000001134      6      1      1   0             0  is_stmt
 0x000000000000113c      7      1      1   0             0  is_stmt
 0x000000000000113f     10      1      1   0             0  is_stmt
 0x0000000000001147     11      3      1   0             0  is_stmt
 0x0000000000001151     11     13      1   0             0  is_stmt
 0x0000000000001160     12      1      1   0             0  is_stmt
 0x0000000000001162     12      1      1   0             0  is_stmt end_sequence
 ~~~

We can try disabling that with -gno-column-info, let's see what we get:

 (gdb) maint info line-table reverse.c
 objfile: /home/pedro/reverse.nocol ((struct objfile *) 0x5611464f6c10)
 compunit_symtab: reverse.c ((struct compunit_symtab *) 0x5611463ea2e0)
 symtab: /home/pedro/reverse.c ((struct symtab *) 0x5611463ea360)
 linetable: ((struct linetable *) 0x561146474c80):
 INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END 
 0      2      0x0000555555555129 Y                    
 1      3      0x0000555555555134 Y                    
 2      6      0x0000555555555137 Y                    
 3      7      0x0000555555555142 Y                    
 4      10     0x0000555555555145 Y                    
 5      11     0x0000555555555158 Y                    
 6      12     0x0000555555555171 Y                    
 7      END    0x0000555555555173 Y                    
 
 (gdb) 

... and in llvm-dwarfdump:

 Address            Line   Column File   ISA Discriminator Flags
 ------------------ ------ ------ ------ --- ------------- -------------
 0x0000000000001129      2      0      1   0             0  is_stmt
 0x0000000000001134      3      0      1   0             0  is_stmt
 0x0000000000001137      6      0      1   0             0  is_stmt
 0x0000000000001142      7      0      1   0             0  is_stmt
 0x0000000000001145     10      0      1   0             0  is_stmt
 0x0000000000001158     11      0      1   0             0  is_stmt
 0x0000000000001171     12      0      1   0             0  is_stmt
 0x0000000000001173     12      0      1   0             0  is_stmt end_sequence

Bingo.  With no column info, only one entry for line 11.

Pedro Alves

>> While with your change, reverse-finish in func2 will make gdb stop at
>> the beginning
>> of the line, before the call to func1.
>>
>> Thus I'm really not convinced (yet) this change is a good one.  It
>> removes
>> a user choice.  You can always do reverse-next/step do get what you
>> want
>> reverse-finish do to, already.
> 
>                                     Carl 
> 

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 14:08                                                               ` Pedro Alves
@ 2023-01-24 14:23                                                                 ` Bruno Larsen
  2023-01-24 15:06                                                                   ` Pedro Alves
  2023-01-24 15:51                                                                 ` Carl Love
                                                                                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-01-24 14:23 UTC (permalink / raw)
  To: Pedro Alves, Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 24/01/2023 15:08, Pedro Alves wrote:
> On 2023-01-23 9:13 p.m., Carl Love wrote:
>> Pedro:
>>
>> On Mon, 2023-01-23 at 19:17 +0000, Pedro Alves wrote:
>>>> Currently on X86, when executing the finish command in reverse, gdb
>>>> does a
>>>> single step from the first instruction in the callee to get back to
>>>> the
>>>> caller.  GDB stops on the last instruction in the source code line
>>>> where
>>>> the call was made.  When stopped at the last instruction of the
>>>> source code
>>>> line, a reverse next or step command will stop at the first
>>>> instruction
>>>> of the same source code line thus requiring two step/next commands
>>>> to
>>>> reach the previous source code line.  It should only require one
>>>> step/next
>>>> command to reach the previous source code line.
>>>>
>>>> By contrast, a reverse next or step command from the first line in
>>>> a
>>>> function stops at the first instruction in the source code line
>>>> where the
>>>> call was made.
>>> I'd think this was on purpose.  Note that next/step/reverse-
>>> {next/step} are line-oriented
>>> stepping commands, they step/next until the previous/next line.
>>> While "finish" is described
>>> as undoing the _function call_.
>>>
>>> The manual says:
>>>
>>>   reverse-finish
>>>   Just as the finish command takes you to the point where the current
>>> function returns,
>>>   reverse-finish takes you to the point where it was called. Instead
>>> of ending up at the end of
>>>   the current function invocation, you end up at the beginning.
>>>
>>> Say you have a line with multiple statements involving multiple
>>> function calls.
>>> The simplest would be:
>>>
>>>    func1 ();  func2 ();
>>>
>>> Say you'd stopped inside 'func2'.  If you do finish there, in current
>>> master gdb
>>> stops at the call to 'func2', and you can then decide to reverse step
>>> into 'func1'.
>> I don't think you followed the issue.
> Totally possible!
>
>> So, if you are in func2 and do a reverse-finish, without the patch gdb
>> stops on the last instruction for the line that calls func2.
> Right.
>
>> Now if
>> you issue a reverse-step, you stop at the first instruction for the
>> call to func2, i.e. you are still on the same source code line.
> Wait.  That right there sounds bogus.  The source line looks like:
>
>     func1 ();  func2 ();
>
> so stepping backwards over that line should always stop at the first
> instruction of the line, not in the middle.  Let's simplify this.
>
> Here's the full source code of my example:
>
> (gdb) list 1
> 1       void func1 ()
> 2       {
> 3       }
> 4
> 5       void func2 ()
> 6       {
> 7       }
> 8
> 9       int main ()
> 10      {
> 11        func1 (); func2 ();
> 12      }
>
I think you are describing a different issue to what Carl is trying to 
solve. Using your example code, I have the following debugging session:

$ ./gdb -q reverse
Reading symbols from reverse...
(gdb) start
Temporary breakpoint 1 at 0x401118: file t.c, line 8.
Starting program: /home/blarsen/Documents/build/gdb/reverse
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Temporary breakpoint 1, main () at t.c:8
8           func1(); func2();
(gdb) record
(gdb) n
9       }
(gdb) rs
func2 () at t.c:5
5       }
(gdb) reverse-finish
Run back to call of #0  func2 () at t.c:5
0x0000000000401127 in main () at t.c:8
8           func1(); func2();
(gdb) rs
8           func1(); func2();
(gdb)
func1 () at t.c:2
2       }
(gdb)

Notice how there were two "reverse-step" commands needed after the 
"reverse-finish" used to exit func2. What Carl is proposing we do is 
make it so GDB only needs one command. If I compare the $pc of where GDB 
is stopped and the linetable, we get:

(gdb) print $pc
$2 = (void (*)()) 0x401127 <main+19>
(gdb) maint info line-table
objfile: /home/blarsen/Documents/downstream_build/gdb/reverse ((struct 
objfile *) 0x10f7750)
compunit_symtab: t.c ((struct compunit_symtab *) 0x116c330)
symtab: /home/blarsen/Documents/downstream_build/gdb/t.c ((struct symtab 
*) 0x116c3b0)
linetable: ((struct linetable *) 0x11aec80):
INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END
0      1      0x0000000000401106 Y
1      2      0x000000000040110a Y
2      4      0x000000000040110d Y
3      5      0x0000000000401111 Y
4      7      0x0000000000401114 Y
5      8      0x0000000000401118 Y
6      8      0x0000000000401122 Y
7      9      0x0000000000401131 Y
8      END    0x0000000000401133 Y

We can see that GDB shouldn't even be able to stop at that $pc, it isn't 
an is_stmt. We should have stopped at 0x401122, which is where the first 
reverse-step stops:

(gdb) rs
8           f1(); f2();
(gdb) p $pc
$4 = (void (*)()) 0x401122 <main+14>

So not only are we needing an extra command to re-sync with user 
expectations, we are in an instruction where the inferior state might be 
all over the place.

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 14:23                                                                 ` Bruno Larsen
@ 2023-01-24 15:06                                                                   ` Pedro Alves
  2023-01-24 16:04                                                                     ` Bruno Larsen
  0 siblings, 1 reply; 105+ messages in thread
From: Pedro Alves @ 2023-01-24 15:06 UTC (permalink / raw)
  To: Bruno Larsen, Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 2023-01-24 2:23 p.m., Bruno Larsen wrote:
> On 24/01/2023 15:08, Pedro Alves wrote:
>> On 2023-01-23 9:13 p.m., Carl Love wrote:
>>> Pedro:
>>>
>>> On Mon, 2023-01-23 at 19:17 +0000, Pedro Alves wrote:
>>>>> Currently on X86, when executing the finish command in reverse, gdb
>>>>> does a
>>>>> single step from the first instruction in the callee to get back to
>>>>> the
>>>>> caller.  GDB stops on the last instruction in the source code line
>>>>> where
>>>>> the call was made.  When stopped at the last instruction of the
>>>>> source code
>>>>> line, a reverse next or step command will stop at the first
>>>>> instruction
>>>>> of the same source code line thus requiring two step/next commands
>>>>> to
>>>>> reach the previous source code line.  It should only require one
>>>>> step/next
>>>>> command to reach the previous source code line.
>>>>>
>>>>> By contrast, a reverse next or step command from the first line in
>>>>> a
>>>>> function stops at the first instruction in the source code line
>>>>> where the
>>>>> call was made.
>>>> I'd think this was on purpose.  Note that next/step/reverse-
>>>> {next/step} are line-oriented
>>>> stepping commands, they step/next until the previous/next line.
>>>> While "finish" is described
>>>> as undoing the _function call_.
>>>>
>>>> The manual says:
>>>>
>>>>   reverse-finish
>>>>   Just as the finish command takes you to the point where the current
>>>> function returns,
>>>>   reverse-finish takes you to the point where it was called. Instead
>>>> of ending up at the end of
>>>>   the current function invocation, you end up at the beginning.
>>>>
>>>> Say you have a line with multiple statements involving multiple
>>>> function calls.
>>>> The simplest would be:
>>>>
>>>>    func1 ();  func2 ();
>>>>
>>>> Say you'd stopped inside 'func2'.  If you do finish there, in current
>>>> master gdb
>>>> stops at the call to 'func2', and you can then decide to reverse step
>>>> into 'func1'.
>>> I don't think you followed the issue.
>> Totally possible!
>>
>>> So, if you are in func2 and do a reverse-finish, without the patch gdb
>>> stops on the last instruction for the line that calls func2.
>> Right.
>>
>>> Now if
>>> you issue a reverse-step, you stop at the first instruction for the
>>> call to func2, i.e. you are still on the same source code line.
>> Wait.  That right there sounds bogus.  The source line looks like:
>>
>>     func1 ();  func2 ();
>>
>> so stepping backwards over that line should always stop at the first
>> instruction of the line, not in the middle.  Let's simplify this.
>>
>> Here's the full source code of my example:
>>
>> (gdb) list 1
>> 1       void func1 ()
>> 2       {
>> 3       }
>> 4
>> 5       void func2 ()
>> 6       {
>> 7       }
>> 8
>> 9       int main ()
>> 10      {
>> 11        func1 (); func2 ();
>> 12      }
>>
> I think you are describing a different issue to what Carl is trying to solve. Using your example code, I have the following debugging session:

No, it's the exact same.  Please re-read.

> 
> $ ./gdb -q reverse
> Reading symbols from reverse...
> (gdb) start
> Temporary breakpoint 1 at 0x401118: file t.c, line 8.
> Starting program: /home/blarsen/Documents/build/gdb/reverse
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib64/libthread_db.so.1".
> 
> Temporary breakpoint 1, main () at t.c:8
> 8           func1(); func2();
> (gdb) record
> (gdb) n
> 9       }
> (gdb) rs
> func2 () at t.c:5
> 5       }
> (gdb) reverse-finish
> Run back to call of #0  func2 () at t.c:5
> 0x0000000000401127 in main () at t.c:8
> 8           func1(); func2();
> (gdb) rs
> 8           func1(); func2();
> (gdb)
> func1 () at t.c:2
> 2       }
> (gdb)
> 
> Notice how there were two "reverse-step" commands needed after the "reverse-finish" used to exit func2. 

Yes.  And the reason you need two "reverse-step" is because there are two line ranges for line 8, and reverse-step stops
at the beginning of the second range instead of at the beginning of the first.  It's the exact same as with my simpler
example of just doing "next" -> "reverse-next", which I used as a simpler example to explain the problem.

> What Carl is proposing we do is make it so GDB only needs one command.

I understand.  However, I am saying that that is papering over the actual problem, _and_ it only works in the situation
where you ended up with two line entries with is-stmt for the same line.  Note how the patch breaks clang, and gcc with
-gno-column-info...

> If I compare the $pc of where GDB is stopped and the linetable, we get:
> 
> (gdb) print $pc
> $2 = (void (*)()) 0x401127 <main+19>
> (gdb) maint info line-table
> objfile: /home/blarsen/Documents/downstream_build/gdb/reverse ((struct objfile *) 0x10f7750)
> compunit_symtab: t.c ((struct compunit_symtab *) 0x116c330)
> symtab: /home/blarsen/Documents/downstream_build/gdb/t.c ((struct symtab *) 0x116c3b0)
> linetable: ((struct linetable *) 0x11aec80):
> INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END
> 0      1      0x0000000000401106 Y
> 1      2      0x000000000040110a Y
> 2      4      0x000000000040110d Y
> 3      5      0x0000000000401111 Y
> 4      7      0x0000000000401114 Y
> 5      8      0x0000000000401118 Y
> 6      8      0x0000000000401122 Y
> 7      9      0x0000000000401131 Y
> 8      END    0x0000000000401133 Y
> 
> We can see that GDB shouldn't even be able to stop at that $pc, it isn't an is_stmt. 

reverse-finish is not supposed to step backwards until it reaches is_stmt.  Doing so makes it
step backwards too much, as I've shown in my previous example.

> We should have stopped at 0x401122, which is where the first reverse-step stops:

No...

> 
> (gdb) rs
> 8           f1(); f2();
> (gdb) p $pc
> $4 = (void (*)()) 0x401122 <main+14>

... no because in the case where you don't have column debug info (or with clang), there won't be
an is-stmt entry for the f2 call/column, there will only be one single line entry for the whole of
line 8, so gdb would step back too much.

> 
> So not only are we needing an extra command to re-sync with user expectations, we are in an instruction where the inferior state might be all over the place.
> 

What does that mean, the state might be all over the place?  The DWARF should describe the locations of all variables accurately at all instructions.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 14:08                                                               ` Pedro Alves
  2023-01-24 14:23                                                                 ` Bruno Larsen
@ 2023-01-24 15:51                                                                 ` Carl Love
  2023-01-24 18:37                                                                   ` Pedro Alves
  2023-01-24 18:25                                                                 ` Carl Love
  2023-01-31  0:17                                                                 ` Reverse-next bug test case Carl Love
  3 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-24 15:51 UTC (permalink / raw)
  To: Pedro Alves, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches
  Cc: Luis Machado, cel


Pedro:

On Tue, 2023-01-24 at 14:08 +0000, Pedro Alves wrote:
> On 2023-01-23 9:13 p.m., Carl Love wrote:
> > Pedro:
> > 
> > On Mon, 2023-01-23 at 19:17 +0000, Pedro Alves wrote:
> > > > Currently on X86, when executing the finish command in reverse,
> > > > gdb
> > > > does a
> > > > single step from the first instruction in the callee to get
> > > > back to
> > > > the
> > > > caller.  GDB stops on the last instruction in the source code
> > > > line
> > > > where
> > > > the call was made.  When stopped at the last instruction of the
> > > > source code
> > > > line, a reverse next or step command will stop at the first
> > > > instruction
> > > > of the same source code line thus requiring two step/next
> > > > commands
> > > > to
> > > > reach the previous source code line.  It should only require
> > > > one
> > > > step/next
> > > > command to reach the previous source code line.
> > > > 
> > > > By contrast, a reverse next or step command from the first line
> > > > in
> > > > a
> > > > function stops at the first instruction in the source code line
> > > > where the
> > > > call was made.
> > > 
> > > I'd think this was on purpose.  Note that next/step/reverse-
> > > {next/step} are line-oriented
> > > stepping commands, they step/next until the previous/next line. 
> > > While "finish" is described
> > > as undoing the _function call_.
> > > 
> > > The manual says:
> > > 
> > >   reverse-finish
> > >   Just as the finish command takes you to the point where the
> > > current
> > > function returns,
> > >   reverse-finish takes you to the point where it was called.
> > > Instead
> > > of ending up at the end of
> > >   the current function invocation, you end up at the beginning.
> > > 
> > > Say you have a line with multiple statements involving multiple
> > > function calls.
> > > The simplest would be:
> > > 
> > >    func1 ();  func2 ();
> > > 
> > > Say you'd stopped inside 'func2'.  If you do finish there, in
> > > current
> > > master gdb
> > > stops at the call to 'func2', and you can then decide to reverse
> > > step
> > > into 'func1'.
> > 
> > I don't think you followed the issue.  
> 
> Totally possible!
> 
> > So, if you are in func2 and do a reverse-finish, without the patch
> > gdb
> > stops on the last instruction for the line that calls func2.  
> 
> Right.
> 
> > Now if
> > you issue a reverse-step, you stop at the first instruction for the
> > call to func2, i.e. you are still on the same source code line.  
> 
> Wait.  That right there sounds bogus.  The source line looks like:
> 
>    func1 ();  func2 ();

My bad, I didn't catch that you were implying func1 and func2 as being
on the same source line.  There is an existing bugzilla for the case of
multiple executable statements on the same line.

https://sourceware.org/bugzilla/show_bug.cgi?id=28426

I have worked with Luis Machado <luis.machado@arm.com> on a patch to
address that issue.  We have posted a few versions of the patch but it
still needs some work for finish.  I wanted to get back to that patch
once the reverse-finish issue is done.

I need to spend some more time looking at the rest of your response to
understand everything you are talking about.  That said, my first read
looked like the issue in the bugzilla I mentioned.  The patch Luis and
I have for addressing multiple statements on the same line applies on
top of the X86 and PowerPC reverse-finish patches.  

Let me spend some more time looking at your response.  Thanks.

                      Carl 


> 
> so stepping backwards over that line should always stop at the first
> instruction of the line, not in the middle.  Let's simplify this.


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-23 19:17                                                           ` Pedro Alves
  2023-01-23 21:13                                                             ` Carl Love
@ 2023-01-24 15:53                                                             ` Tom de Vries
  2023-01-24 18:48                                                               ` Pedro Alves
  1 sibling, 1 reply; 105+ messages in thread
From: Tom de Vries @ 2023-01-24 15:53 UTC (permalink / raw)
  To: Pedro Alves, Carl Love, Bruno Larsen, Ulrich Weigand,
	will_schmidt, gdb-patches

On 1/23/23 20:17, Pedro Alves wrote:
> I'd think this was on purpose.  Note that next/step/reverse-{next/step} are line-oriented
> stepping commands, they step/next until the previous/next line.  While "finish" is described
> as undoing the_function call_.
> 
> The manual says:
> 
>   reverse-finish
>   Just as the finish command takes you to the point where the current function returns,
>   reverse-finish takes you to the point where it was called. Instead of ending up at the end of
>   the current function invocation, you end up at the beginning.

As well as:
...
finish
Continue running until just after function in the selected stack frame 
returns. Print the returned value (if any). This command can be 
abbreviated as fin.
...

It's only now that you mention the non-line nature of 
finish/reverse-finish that I realize that that is the case.  So I 
suppose the docs could be a bit more explicit about this aspect.

I suppose an intuitive way to make available the two approaches (so 
without the user losing options) would be to introduce finishi next to 
finish and reverse-finishi next to finish, with the new commands 
retaining the current functionality and the old ones being adjusted to 
respect line boundaries.  But having the commands change behaviour is 
likely to cause confusion (well, assuming users notice the difference in 
the first place), so I'm not sure if that's a good idea.

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 15:06                                                                   ` Pedro Alves
@ 2023-01-24 16:04                                                                     ` Bruno Larsen
  2023-01-24 19:12                                                                       ` Pedro Alves
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-01-24 16:04 UTC (permalink / raw)
  To: Pedro Alves, Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 24/01/2023 16:06, Pedro Alves wrote:
> On 2023-01-24 2:23 p.m., Bruno Larsen wrote:
>> On 24/01/2023 15:08, Pedro Alves wrote:
>>> On 2023-01-23 9:13 p.m., Carl Love wrote:
>>>> Pedro:
>>>>
>>>> On Mon, 2023-01-23 at 19:17 +0000, Pedro Alves wrote:
>>>>>> Currently on X86, when executing the finish command in reverse, gdb
>>>>>> does a
>>>>>> single step from the first instruction in the callee to get back to
>>>>>> the
>>>>>> caller.  GDB stops on the last instruction in the source code line
>>>>>> where
>>>>>> the call was made.  When stopped at the last instruction of the
>>>>>> source code
>>>>>> line, a reverse next or step command will stop at the first
>>>>>> instruction
>>>>>> of the same source code line thus requiring two step/next commands
>>>>>> to
>>>>>> reach the previous source code line.  It should only require one
>>>>>> step/next
>>>>>> command to reach the previous source code line.
>>>>>>
>>>>>> By contrast, a reverse next or step command from the first line in
>>>>>> a
>>>>>> function stops at the first instruction in the source code line
>>>>>> where the
>>>>>> call was made.
>>>>> I'd think this was on purpose.  Note that next/step/reverse-
>>>>> {next/step} are line-oriented
>>>>> stepping commands, they step/next until the previous/next line.
>>>>> While "finish" is described
>>>>> as undoing the _function call_.
>>>>>
>>>>> The manual says:
>>>>>
>>>>>    reverse-finish
>>>>>    Just as the finish command takes you to the point where the current
>>>>> function returns,
>>>>>    reverse-finish takes you to the point where it was called. Instead
>>>>> of ending up at the end of
>>>>>    the current function invocation, you end up at the beginning.
>>>>>
>>>>> Say you have a line with multiple statements involving multiple
>>>>> function calls.
>>>>> The simplest would be:
>>>>>
>>>>>     func1 ();  func2 ();
>>>>>
>>>>> Say you'd stopped inside 'func2'.  If you do finish there, in current
>>>>> master gdb
>>>>> stops at the call to 'func2', and you can then decide to reverse step
>>>>> into 'func1'.
>>>> I don't think you followed the issue.
>>> Totally possible!
>>>
>>>> So, if you are in func2 and do a reverse-finish, without the patch gdb
>>>> stops on the last instruction for the line that calls func2.
>>> Right.
>>>
>>>> Now if
>>>> you issue a reverse-step, you stop at the first instruction for the
>>>> call to func2, i.e. you are still on the same source code line.
>>> Wait.  That right there sounds bogus.  The source line looks like:
>>>
>>>      func1 ();  func2 ();
>>>
>>> so stepping backwards over that line should always stop at the first
>>> instruction of the line, not in the middle.  Let's simplify this.
>>>
>>> Here's the full source code of my example:
>>>
>>> (gdb) list 1
>>> 1       void func1 ()
>>> 2       {
>>> 3       }
>>> 4
>>> 5       void func2 ()
>>> 6       {
>>> 7       }
>>> 8
>>> 9       int main ()
>>> 10      {
>>> 11        func1 (); func2 ();
>>> 12      }
>>>
>> I think you are describing a different issue to what Carl is trying to solve. Using your example code, I have the following debugging session:
> No, it's the exact same.  Please re-read.
>
>> $ ./gdb -q reverse
>> Reading symbols from reverse...
>> (gdb) start
>> Temporary breakpoint 1 at 0x401118: file t.c, line 8.
>> Starting program: /home/blarsen/Documents/build/gdb/reverse
>> [Thread debugging using libthread_db enabled]
>> Using host libthread_db library "/lib64/libthread_db.so.1".
>>
>> Temporary breakpoint 1, main () at t.c:8
>> 8           func1(); func2();
>> (gdb) record
>> (gdb) n
>> 9       }
>> (gdb) rs
>> func2 () at t.c:5
>> 5       }
>> (gdb) reverse-finish
>> Run back to call of #0  func2 () at t.c:5
>> 0x0000000000401127 in main () at t.c:8
>> 8           func1(); func2();
>> (gdb) rs
>> 8           func1(); func2();
>> (gdb)
>> func1 () at t.c:2
>> 2       }
>> (gdb)
>>
>> Notice how there were two "reverse-step" commands needed after the "reverse-finish" used to exit func2.
> Yes.  And the reason you need two "reverse-step" is because there are two line ranges for line 8, and reverse-step stops
> at the beginning of the second range instead of at the beginning of the first.  It's the exact same as with my simpler
> example of just doing "next" -> "reverse-next", which I used as a simpler example to explain the problem.

The simplified example is not the exact same use case. Looking at how 
the program executes forward, if we next over this line we skip 
everything, but if we step into func1 and use finish we will still stop 
in line 11 and the user can decide to step into func2 or not. That is 
why I assumed you were thinking of a different issue when I saw you 
using next and reverse-next as examples.

Looking at where GDB lands when finishing from func1 we get (code 
compiled with gcc -gno-column-info):

(gdb) start
Temporary breakpoint 1 at 0x401118: file t.c, line 8.
Starting program: /home/blarsen/Documents/downstream_build/gdb/reverse
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Temporary breakpoint 1, main () at t.c:8
8           f1(); f2();
(gdb) s
f1 () at t.c:2
2       }
(gdb) finish
Run till exit from #0  f1 () at t.c:2
0x0000000000401122 in main () at t.c:8
8           f1(); f2();
(gdb) disas /s
Dump of assembler code for function main:
t.c:
7       int main(){
    0x0000000000401114 <+0>:     push   %rbp
    0x0000000000401115 <+1>:     mov    %rsp,%rbp

8           f1(); f2();
    0x0000000000401118 <+4>:     mov    $0x0,%eax
    0x000000000040111d <+9>:     call   0x401106 <f1>
=> 0x0000000000401122 <+14>:    mov    $0x0,%eax
    0x0000000000401127 <+19>:    call   0x40110d <f2>
    0x000000000040112c <+24>:    mov    $0x0,%eax

9       }
    0x0000000000401131 <+29>:    pop    %rbp
    0x0000000000401132 <+30>:    ret
End of assembler dump.

The behavior that we should emulate when going backwards is that 
finishing from func2 stops us on the 'mov' instruction between the 
calls. Looking at the clang session that I cut off from the previous email:

Alright, here's the gdb session, with clang, no gdb patch:

  Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc48) at reverse.c:11
  11        func1 (argc); func2 (argc);
  (gdb) disassemble /s
  Dump of assembler code for function main:
  reverse.c:
  10      {
     0x0000555555555150 <+0>:     push   %rbp
     0x0000555555555151 <+1>:     mov    %rsp,%rbp
     0x0000555555555154 <+4>:     sub    $0x10,%rsp
     0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
     0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
  
  11        func1 (argc); func2 (argc);
  => 0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
     0x0000555555555162 <+18>:    call   0x555555555130 <func1>
     0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
     0x000055555555516a <+26>:    call   0x555555555140 <func2>
  
  12      }
     0x000055555555516f <+31>:    xor    %eax,%eax
     0x0000555555555171 <+33>:    add    $0x10,%rsp
     0x0000555555555175 <+37>:    pop    %rbp
     0x0000555555555176 <+38>:    ret
  End of assembler dump.
  (gdb) record
  (gdb) b func2
  Breakpoint 2 at 0x555555555147: file reverse.c, line 7.
  (gdb) c
  Continuing.
  
  Breakpoint 2, func2 (i=1) at reverse.c:7
  7       }
  (gdb) reverse-finish
  Run back to call of #0  func2 (i=1) at reverse.c:7
  0x000055555555516a in main (argc=1, argv=0x7fffffffdc48) at reverse.c:11
  11        func1 (argc); func2 (argc);
  (gdb) disassemble /s
  Dump of assembler code for function main:
  reverse.c:
  10      {
     0x0000555555555150 <+0>:     push   %rbp
     0x0000555555555151 <+1>:     mov    %rsp,%rbp
     0x0000555555555154 <+4>:     sub    $0x10,%rsp
     0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
     0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
  
  11        func1 (argc); func2 (argc);
     0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
     0x0000555555555162 <+18>:    call   0x555555555130 <func1>
     0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
  => 0x000055555555516a <+26>:    call   0x555555555140 <func2>
  
  12      }
     0x000055555555516f <+31>:    xor    %eax,%eax
     0x0000555555555171 <+33>:    add    $0x10,%rsp
     0x0000555555555175 <+37>:    pop    %rbp
     0x0000555555555176 <+38>:    ret
  End of assembler dump.
  (gdb) reverse-step
  func1 (i=1) at reverse.c:3
  3       }
  (gdb)

We can see that GDB stopped on the call instruction instead. So a user 
that finished from func1 or reverse-finished from func2 may see 
different inferior states.


>
>> What Carl is proposing we do is make it so GDB only needs one command.
> I understand.  However, I am saying that that is papering over the actual problem, _and_ it only works in the situation
> where you ended up with two line entries with is-stmt for the same line.  Note how the patch breaks clang, and gcc with
> -gno-column-info...
>
>> If I compare the $pc of where GDB is stopped and the linetable, we get:
>>
>> (gdb) print $pc
>> $2 = (void (*)()) 0x401127 <main+19>
>> (gdb) maint info line-table
>> objfile: /home/blarsen/Documents/downstream_build/gdb/reverse ((struct objfile *) 0x10f7750)
>> compunit_symtab: t.c ((struct compunit_symtab *) 0x116c330)
>> symtab: /home/blarsen/Documents/downstream_build/gdb/t.c ((struct symtab *) 0x116c3b0)
>> linetable: ((struct linetable *) 0x11aec80):
>> INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END
>> 0      1      0x0000000000401106 Y
>> 1      2      0x000000000040110a Y
>> 2      4      0x000000000040110d Y
>> 3      5      0x0000000000401111 Y
>> 4      7      0x0000000000401114 Y
>> 5      8      0x0000000000401118 Y
>> 6      8      0x0000000000401122 Y
>> 7      9      0x0000000000401131 Y
>> 8      END    0x0000000000401133 Y
>>
>> We can see that GDB shouldn't even be able to stop at that $pc, it isn't an is_stmt.
> reverse-finish is not supposed to step backwards until it reaches is_stmt.  Doing so makes it
> step backwards too much, as I've shown in my previous example.
>
>> We should have stopped at 0x401122, which is where the first reverse-step stops:
> No...
>
>> (gdb) rs
>> 8           f1(); f2();
>> (gdb) p $pc
>> $4 = (void (*)()) 0x401122 <main+14>
> ... no because in the case where you don't have column debug info (or with clang), there won't be
> an is-stmt entry for the f2 call/column, there will only be one single line entry for the whole of
> line 8, so gdb would step back too much.
>
>> So not only are we needing an extra command to re-sync with user expectations, we are in an instruction where the inferior state might be all over the place.
>>
> What does that mean, the state might be all over the place?  The DWARF should describe the locations of all variables accurately at all instructions.
>
Unrelated to this specific issue, but I was looking at record/30025 
(https://sourceware.org/bugzilla/show_bug.cgi?id=30025) and it confused 
me because because GDB sometimes reported the incorrect parameter, but 
if we continue single-stepping through instructions, GDB eventually 
finds the correct value when we stop at an is_stmt instruction.

If I misunderstood something about 30025 and is_stmt, please let me 
know! but as far as I can see, this is what happened.

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 14:08                                                               ` Pedro Alves
  2023-01-24 14:23                                                                 ` Bruno Larsen
  2023-01-24 15:51                                                                 ` Carl Love
@ 2023-01-24 18:25                                                                 ` Carl Love
  2023-01-24 19:21                                                                   ` Pedro Alves
  2023-01-31  0:17                                                                 ` Reverse-next bug test case Carl Love
  3 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-24 18:25 UTC (permalink / raw)
  To: Pedro Alves, Bruno Larsen, Ulrich Weigand, gdb-patches; +Cc: Luis Machado, cel

Pedro:

On Tue, 2023-01-24 at 14:08 +0000, Pedro Alves wrote:
> On 2023-01-23 9:13 p.m., Carl Love wrote:
> > Pedro:
> > 
> > On Mon, 2023-01-23 at 19:17 +0000, Pedro Alves wrote:
> > > > Currently on X86, when executing the finish command in reverse,
> > > > gdb
> > > > does a
> > > > single step from the first instruction in the callee to get
> > > > back to
> > > > the
> > > > caller.  GDB stops on the last instruction in the source code
> > > > line
> > > > where
> > > > the call was made.  When stopped at the last instruction of the
> > > > source code
> > > > line, a reverse next or step command will stop at the first
> > > > instruction
> > > > of the same source code line thus requiring two step/next
> > > > commands
> > > > to
> > > > reach the previous source code line.  It should only require
> > > > one
> > > > step/next
> > > > command to reach the previous source code line.
> > > > 
> > > > By contrast, a reverse next or step command from the first line
> > > > in
> > > > a
> > > > function stops at the first instruction in the source code line
> > > > where the
> > > > call was made.
> > > 
> > > I'd think this was on purpose.  Note that next/step/reverse-
> > > {next/step} are line-oriented
> > > stepping commands, they step/next until the previous/next line. 
> > > While "finish" is described
> > > as undoing the _function call_.
> > > 
> > > The manual says:
> > > 
> > >  reverse-finish
> > >  Just as the finish command takes you to the point where the
> > > current
> > > function returns,
> > >  reverse-finish takes you to the point where it was called.
> > > Instead
> > > of ending up at the end of
> > >  the current function invocation, you end up at the beginning.
> > > 
> > > Say you have a line with multiple statements involving multiple
> > > function calls.
> > > The simplest would be:
> > > 
> > >   func1 ();  func2 ();
> > > 
> > > Say you'd stopped inside 'func2'.  If you do finish there, in
> > > current
> > > master gdb
> > > stops at the call to 'func2', and you can then decide to reverse
> > > step
> > > into 'func1'.
> > 
> > I don't think you followed the issue.  
> 
> Totally possible!
> 
> > So, if you are in func2 and do a reverse-finish, without the patch
> > gdb
> > stops on the last instruction for the line that calls func2.  
> 
> Right.
> 
> > Now if
> > you issue a reverse-step, you stop at the first instruction for the
> > call to func2, i.e. you are still on the same source code line.  
> 
> Wait.  That right there sounds bogus.  The source line looks like:
> 
>    func1 ();  func2 ();
> 
> so stepping backwards over that line should always stop at the first
> instruction of the line, not in the middle.  Let's simplify this.
> 
> Here's the full source code of my example:
> 
> (gdb) list 1
> 1       void func1 ()
> 2       {
> 3       }
> 4
> 5       void func2 ()
> 6       {
> 7       }
> 8
> 9       int main ()
> 10      {
> 11        func1 (); func2 ();
> 12      }
> 
> Compiled with:
> 
>  $ gcc reverse.c -o reverse -g3 -O0
>  $ gcc -v
>  ...
>  gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)
> 
> Now let's debug it with target record, using current gdb git master
> (f3d8ae90b236),
> without your patch:
> 
>  $ gdb ~/reverse
>  GNU gdb (GDB) 14.0.50.20230124-git
>  ...
>  Reading symbols from /home/pedro/reverse...
>  (gdb) start
>  Temporary breakpoint 1 at 0x1147: file reverse.c, line 11.
>  Starting program: /home/pedro/reverse 
>  [Thread debugging using libthread_db enabled]
>  Using host libthread_db library "/lib/x86_64-linux-
> gnu/libthread_db.so.1".
> 
>  Temporary breakpoint 1, main () at reverse.c:11
>  11        func1 (); func2 ();
>  (gdb) record 
> 
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x000055555555513f <+0>:     endbr64
>     0x0000555555555143 <+4>:     push   %rbp
>     0x0000555555555144 <+5>:     mov    %rsp,%rbp
> 
>  11        func1 (); func2 ();
>  => 0x0000555555555147 <+8>:     mov    $0x0,%eax
>     0x000055555555514c <+13>:    call   0x555555555129 <func1>
>     0x0000555555555151 <+18>:    mov    $0x0,%eax
>     0x0000555555555156 <+23>:    call   0x555555555134 <func2>
>     0x000055555555515b <+28>:    mov    $0x0,%eax
> 
>  12      }
>     0x0000555555555160 <+33>:    pop    %rbp
>     0x0000555555555161 <+34>:    ret
>  End of assembler dump.
> 
>  (gdb) n
>  12      }
> 
> So far so good, a "next" stepped over the whole of line 11 and
> stopped at line 12.
> 
> Let's confirm where we are now:
> 
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x000055555555513f <+0>:     endbr64
>     0x0000555555555143 <+4>:     push   %rbp
>     0x0000555555555144 <+5>:     mov    %rsp,%rbp
> 
>  11        func1 (); func2 ();
>     0x0000555555555147 <+8>:     mov    $0x0,%eax
>     0x000055555555514c <+13>:    call   0x555555555129 <func1>
>     0x0000555555555151 <+18>:    mov    $0x0,%eax
>     0x0000555555555156 <+23>:    call   0x555555555134 <func2>
>     0x000055555555515b <+28>:    mov    $0x0,%eax
> 
>  12      }
>  => 0x0000555555555160 <+33>:    pop    %rbp
>     0x0000555555555161 <+34>:    ret
>  End of assembler dump.
> 
> Good, we're at the first instruction of line 12.
> 
> Now let's undo the "next", with "reverse-next":
> 
>  (gdb) reverse-next
>  11        func1 (); func2 ();
> 
> Seemingly stopped at line 11.  Let's see exactly where:
> 
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x000055555555513f <+0>:     endbr64
>     0x0000555555555143 <+4>:     push   %rbp
>     0x0000555555555144 <+5>:     mov    %rsp,%rbp
> 
>  11        func1 (); func2 ();
>     0x0000555555555147 <+8>:     mov    $0x0,%eax
>     0x000055555555514c <+13>:    call   0x555555555129 <func1>
>  => 0x0000555555555151 <+18>:    mov    $0x0,%eax
>     0x0000555555555156 <+23>:    call   0x555555555134 <func2>
>     0x000055555555515b <+28>:    mov    $0x0,%eax
> 
>  12      }
>     0x0000555555555160 <+33>:    pop    %rbp
>     0x0000555555555161 <+34>:    ret
>  End of assembler dump.
>  (gdb) 
> 
> And lo, we stopped in the middle of line 11!  That is a bug, we
> should have stepped
> back all the way to the beginning of the line.  The "reverse-next"
> should have fully
> undone the prior "next" command.  Here's the same thing without the
> distracting
> disassemble commands:
> 
>  (gdb) b 11
>  Breakpoint 1 at 0x1147: file reverse.c, line 11.
>  (gdb) r
>  Starting program: /home/pedro/reverse 
>  [Thread debugging using libthread_db enabled]
>  Using host libthread_db library "/lib/x86_64-linux-
> gnu/libthread_db.so.1".
> 
>  Breakpoint 1, main () at reverse.c:11
>  11        func1 (); func2 ();
>  (gdb) p $pc
>  $1 = (void (*)()) 0x555555555147 <main+8>
>  (gdb) record 
>  (gdb) next
>  12      }
>  (gdb) reverse-next
>  11        func1 (); func2 ();
>  (gdb) p $pc
>  $2 = (void (*)()) 0x555555555151 <main+18>
>  (gdb) 
> 
> 
> This:
> 
>  next -> reverse-next -> next -> reverse-next
> 
> ... should leave you at the same instruction.  But it doesn't in this
> example!
> 
> How does this happen?  Let's look at the line table as seen by GDB:
> 
>  (gdb) maint info line-table reverse.c
>  objfile: /home/pedro/reverse ((struct objfile *) 0x55dd5df77c50)
>  compunit_symtab: reverse.c ((struct compunit_symtab *)
> 0x55dd5de6b2e0)
>  symtab: /home/pedro/reverse.c ((struct symtab *) 0x55dd5de6b360)
>  linetable: ((struct linetable *) 0x55dd5dfd3290):
>  INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END 
>  0      2      0x0000555555555129 Y                    
>  1      3      0x0000555555555131 Y                    
>  2      6      0x0000555555555134 Y                    
>  3      7      0x000055555555513c Y                    
>  4      10     0x000055555555513f Y                    
>  5      11     0x0000555555555147 Y                      <<< here 
>  6      11     0x0000555555555151 Y                      <<< here
>  7      12     0x0000555555555160 Y                    
>  8      END    0x0000555555555162 Y                    
> 
> Ah, there are two entries for line 11, both marked with IS-STMT.  So
> when
> stepping backward GDB only considered the region with index 6, that's
> why it
> stopped at 0x0000555555555151.

So, I walked thru your example on PowerPC and agree that the case where
we have  func1 (); func2 (); on the same source line fails with the
reverse-next command.  However, I think this is actually a "new"
regression failure for my patch.  My patch was trying to fix the
behavior of the reverse-finish command and appears to have broken the
reverse-next command for this scenario.

Note, the initial version of this patch also broke the reverse-next
command (gdb.btrace/rn-dl-bind.exp and gdb.btrace/tailcall.exp) but the
current version of the patch fixed the tailcall.exp failure.  Bruno and
I were not able to reproduce the failure for the rn-dl-bind.exp test. 
Not sure if the test still fails for Tom with the latest patch or not.

Anyway, see the status summary below.
> 
> 
> 
> Let's look at what we get with clang instead (Ubuntu clang version
> 14.0.0-1ubuntu1) :
> 
>  (gdb) maintenance info line-table reverse.c
>  objfile: /home/pedro/reverse.clang ((struct objfile *)
> 0x5576be591ca0)
>  compunit_symtab: reverse.c ((struct compunit_symtab *)
> 0x5576be485300)
>  symtab: /home/pedro/reverse.c ((struct symtab *) 0x5576be485380)
>  linetable: ((struct linetable *) 0x5576be5ec8e0):
>  INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END 
>  0      2      0x0000555555555130 Y                    
>  1      3      0x0000555555555134 Y       Y            
>  2      6      0x0000555555555140 Y                    
>  3      7      0x0000555555555144 Y       Y            
>  4      10     0x0000555555555150 Y                    
>  5      11     0x0000555555555154 Y       Y            
>  6      11     0x0000555555555159                      
>  7      12     0x000055555555515e Y                    
>  8      END    0x0000555555555162 Y                    
> 
> Note no IS-STMT for the second range.  And let's look at how GDB
> behaves with it:
> 
>  (gdb) b 11
>  Breakpoint 1 at 0x1154: file reverse.c, line 11.
>  (gdb) r
>  Starting program: /home/pedro/reverse.clang 
>  [Thread debugging using libthread_db enabled]
>  Using host libthread_db library "/lib/x86_64-linux-
> gnu/libthread_db.so.1".
> 
>  Breakpoint 1, main () at reverse.c:11
>  11        func1 (); func2 ();
>  (gdb) record
>  (gdb) p $pc
>  $1 = (void (*)()) 0x555555555154 <main+4>
>  (gdb) n
>  12      }
>  (gdb) reverse-next
> 
>  No more reverse-execution history.
>  main () at reverse.c:11
>  11        func1 (); func2 ();
>  (gdb) p $pc
>  $2 = (void (*)()) 0x555555555154 <main+4>
>  (gdb) 
> 
> Bingo.  reverse-next fully stepped the whole line backwards.
> 
> > You
> > have not stepped back into func1 like you wanted to.  Now you have
> > to
> > issue a second reverse-step to get into func1.   With the patch,
> > you
> > issue the reverse-finish from func2 and stop at the first
> > instruction
> > in the line that calls func2.  Now when you issue the reverse-step
> > you
> > step back into func1 as expected.
> > 
> 
> So this fix is assuming that the reverse step stops in the middle of
> a
> line, which I think is the real bug to fix.  Once that is fixed, then
> you will no longer need two reverse-steps after reverse-finish.
> 
> Here's what you get with current master without your patch, but using
> the test program compiled with clang.  Actually, let's use a slightly
> modified program to force clang to emit some instructions between
> the two calls.  Like this:
> 
>  $ cat reverse.c
>  void func1 (int i)
>  {
>  }
> 
>  void func2 (int i)
>  {
>  }
> 
>  int main (int argc, char **argv)
>  {
>    func1 (argc); func2 (argc);
>  }
> 
> Alright, here's the gdb session, with clang, no gdb patch:
> 
>  Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc48) at
> reverse.c:11
>  11        func1 (argc); func2 (argc);
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x0000555555555150 <+0>:     push   %rbp
>     0x0000555555555151 <+1>:     mov    %rsp,%rbp
>     0x0000555555555154 <+4>:     sub    $0x10,%rsp
>     0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
>     0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
> 
>  11        func1 (argc); func2 (argc);
>  => 0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
>     0x0000555555555162 <+18>:    call   0x555555555130 <func1>
>     0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
>     0x000055555555516a <+26>:    call   0x555555555140 <func2>
> 
>  12      }
>     0x000055555555516f <+31>:    xor    %eax,%eax
>     0x0000555555555171 <+33>:    add    $0x10,%rsp
>     0x0000555555555175 <+37>:    pop    %rbp
>     0x0000555555555176 <+38>:    ret
>  End of assembler dump.
>  (gdb) record 
>  (gdb) b func2
>  Breakpoint 2 at 0x555555555147: file reverse.c, line 7.
>  (gdb) c
>  Continuing.
> 
>  Breakpoint 2, func2 (i=1) at reverse.c:7
>  7       }
>  (gdb) reverse-finish 
>  Run back to call of #0  func2 (i=1) at reverse.c:7
>  0x000055555555516a in main (argc=1, argv=0x7fffffffdc48) at
> reverse.c:11
>  11        func1 (argc); func2 (argc);
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x0000555555555150 <+0>:     push   %rbp
>     0x0000555555555151 <+1>:     mov    %rsp,%rbp
>     0x0000555555555154 <+4>:     sub    $0x10,%rsp
>     0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
>     0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
> 
>  11        func1 (argc); func2 (argc);
>     0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
>     0x0000555555555162 <+18>:    call   0x555555555130 <func1>
>     0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
>  => 0x000055555555516a <+26>:    call   0x555555555140 <func2>
> 
>  12      }
>     0x000055555555516f <+31>:    xor    %eax,%eax
>     0x0000555555555171 <+33>:    add    $0x10,%rsp
>     0x0000555555555175 <+37>:    pop    %rbp
>     0x0000555555555176 <+38>:    ret
>  End of assembler dump.
>  (gdb) reverse-step
>  func1 (i=1) at reverse.c:3
>  3       }
>  (gdb) 
> 
> 
> Note how a single reverse-step after the reverse-finish immediately
> stepped backwards into func1.  Exactly how I describing it
> originally.
> 
> With your patch, you'd break reverse-finish with clang:
> 
>  (gdb) record 
>  (gdb) b func2
>  Breakpoint 2 at 0x555555555147: file reverse.c, line 7.
>  (gdb) c
>  Continuing.
> 
>  Breakpoint 2, func2 (i=1) at reverse.c:7
>  7       }
>  (gdb) reverse-finish 
>  Run back to call of #0  func2 (i=1) at reverse.c:7
>  func1 (i=1) at reverse.c:3
>  3       }
>  (gdb) 
> 
> GDB stopped at line 3, info func1 which means it stepped too far
> without
> stopping at func2's call site.
> 
> GDB is misbehaving with GCC's debug info.  I suspect the reason we
> get
> the two line entries for line 11 and both with IS-STMT is because GCC
> emits
> column debug info nowadays by default.   Here's what e.g.,
> "llvm-dwarfdump --debug-line reverse" shows:
> 
>  ~~~
>  Address            Line   Column File   ISA Discriminator Flags
>  ------------------ ------ ------ ------ --- ------------- ----------
> ---
>  0x0000000000001129      2      1      1   0             0  is_stmt
>  0x0000000000001131      3      1      1   0             0  is_stmt
>  0x0000000000001134      6      1      1   0             0  is_stmt
>  0x000000000000113c      7      1      1   0             0  is_stmt
>  0x000000000000113f     10      1      1   0             0  is_stmt
>  0x0000000000001147     11      3      1   0             0  is_stmt
>  0x0000000000001151     11     13      1   0             0  is_stmt
>  0x0000000000001160     12      1      1   0             0  is_stmt
>  0x0000000000001162     12      1      1   0             0  is_stmt
> end_sequence
>  ~~~
> 
> We can try disabling that with -gno-column-info, let's see what we
> get:
> 
>  (gdb) maint info line-table reverse.c
>  objfile: /home/pedro/reverse.nocol ((struct objfile *)
> 0x5611464f6c10)
>  compunit_symtab: reverse.c ((struct compunit_symtab *)
> 0x5611463ea2e0)
>  symtab: /home/pedro/reverse.c ((struct symtab *) 0x5611463ea360)
>  linetable: ((struct linetable *) 0x561146474c80):
>  INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END 
>  0      2      0x0000555555555129 Y                    
>  1      3      0x0000555555555134 Y                    
>  2      6      0x0000555555555137 Y                    
>  3      7      0x0000555555555142 Y                    
>  4      10     0x0000555555555145 Y                    
>  5      11     0x0000555555555158 Y                    
>  6      12     0x0000555555555171 Y                    
>  7      END    0x0000555555555173 Y                    
> 
>  (gdb) 
> 
> ... and in llvm-dwarfdump:
> 
>  Address            Line   Column File   ISA Discriminator Flags
>  ------------------ ------ ------ ------ --- ------------- ----------
> ---
>  0x0000000000001129      2      0      1   0             0  is_stmt
>  0x0000000000001134      3      0      1   0             0  is_stmt
>  0x0000000000001137      6      0      1   0             0  is_stmt
>  0x0000000000001142      7      0      1   0             0  is_stmt
>  0x0000000000001145     10      0      1   0             0  is_stmt
>  0x0000000000001158     11      0      1   0             0  is_stmt
>  0x0000000000001171     12      0      1   0             0  is_stmt
>  0x0000000000001173     12      0      1   0             0  is_stmt
> end_sequence
> 
> Bingo.  With no column info, only one entry for line 11.
> 

I have not tested with clang.  Actually I have never used clang so this
is another thing to look at and test.


Let me see if I can summarize the current situation.

1) The goal of the current X86 reverse patch is to fix the case where
we have called function foo () and are trying to do a reverse-finish
from inside the function.  The mainline gdb code stops at the entry to
foo () then does a single instruction in the reverse direction to get
to the caller.  Specifically, the code that this patch removes:

-      if (ecs->event_thread->control.proceed_to_finish  
-         && execution_direction == EXEC_REVERSE)
-       {         
-         struct thread_info *tp = ecs->event_thread;
-                  
-         /* We are finishing a function in reverse, and just hit the
-            step-resume breakpoint at the start address of the
-            function, and we're almost there -- just need to back up
-            by one more single-step, which should take us back to the
-            function call.  */
-         tp->control.step_range_start = tp->control.step_range_end = 1;
-         keep_going (ecs);
-         return;

The single-step in gdb results in stopping at the last instruction in
the line where function foo is called. The result here is that you now
need to do two reverse-next instructions to get to the previous line. 
The command sequence is:  reverse-finish; reverse-next; reverst-next to
go from inside the function to the previous line in the caller.

Note, in this case you are in the function and trying to return to the
caller with the reverse-finish command.  That is a different scenario
from what Pedro is talking about in 2) below.

2) The scenario that Pedro brings up is a reverse-next over a line with
two function calls on the same source line, i.e.

> 9       int main ()
> 10      {
> 11        func1 (); func2 ();
> 12      }

In this case you are in the caller and are trying to do a reverse-next
over the two function callers.  This is a different scenario from 1).

This looks to me like an additional regression failure of the patch. 
Unfortunately, this scenario does not seem to exit in any of the
current tests.  Mainline gdb handles this case correctly.  With my
patch, the reverse-next over the line now fails.

With out the patch, you just need reverse-next to step back over func1
(); func2 ();

With the patch you need reverse-next, reverse-next to step back over
the line with the two function calls.

3)  The bug that I mentioned earlier for the case of
multiple executable statements on the same line.

https://sourceware.org/bugzilla/show_bug.cgi?id=28426

is for a case like:

int main ()
{
  int a, b, c, d;
  a = 1;
  b = 2;
  c = 3; d = 4;
  a = a + b + c + d;
}

In this case the reverse-next from the last line a = a + b + c + d; is
not stepping all the way back over the line c = 3; d = 4;.  This is a
simpler version of 2).  Specifically the command sequence to step over
line c = 3; d = 4; is reverse-next, reverse-next.  Only one reverse-
next should be required.

The patch that Luis and I have worked on fixes this issue, however it
does not fix the case of the multiple statements being function calls,
i.e. 2) above that Pedro is bringing up.


From a subsequent message from Pedro in this thread:

   On Tue, 2023-01-24 at 15:06 +0000, Pedro Alves wrote:
   > Yes.  And the reason you need two "reverse-step" is because there are
   > two line ranges for line 8, and reverse-step stops
   > at the beginning of the second range instead of at the beginning of
   > the first.  It's the exact same as with my simpler
   > example of just doing "next" -> "reverse-next", which I used as a
   > simpler example to explain the problem.
   > 
   > > What Carl is proposing we do is make it so GDB only needs one
   > > command.
   > 
   > I understand.  However, I am saying that that is papering over the
   > actual problem, _and_ it only works in the situation
   > where you ended up with two line entries with is-stmt for the same
   > line.  Note how the patch breaks clang, and gcc with
   > -gno-column-info...

I don't agree that I am "papering over the actual problem" rather I
think at this point that Pedro's test case is an additional case of the
reverse-next command being broken by my patch to fix the reverse-finish 
command.  The problem doesn't exist without my patch.  


So at this point, I need to go see if I can figure out how the patch to
fix the reverse-finish command causes the regression in 2) for the
reverse-next command.

Looks like we also need an to add an additional test case for 2). 
Also, will need to look at how any new fix for 2) behaves with clang.

Thanks for all the input on this issue.  It seems that there is still
work to do.  

                         Carl 








^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 15:51                                                                 ` Carl Love
@ 2023-01-24 18:37                                                                   ` Pedro Alves
  0 siblings, 0 replies; 105+ messages in thread
From: Pedro Alves @ 2023-01-24 18:37 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Ulrich Weigand, will_schmidt, gdb-patches
  Cc: Luis Machado

On 2023-01-24 3:51 p.m., Carl Love wrote:

> On Tue, 2023-01-24 at 14:08 +0000, Pedro Alves wrote:

>> Wait.  That right there sounds bogus.  The source line looks like:
>>
>>    func1 ();  func2 ();
> 
> My bad, I didn't catch that you were implying func1 and func2 as being
> on the same source line.  There is an existing bugzilla for the case of
> multiple executable statements on the same line.
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=28426
> 
> I have worked with Luis Machado <luis.machado@arm.com> on a patch to
> address that issue.  We have posted a few versions of the patch but it
> still needs some work for finish.  I wanted to get back to that patch
> once the reverse-finish issue is done.
> 
> I need to spend some more time looking at the rest of your response to
> understand everything you are talking about.  That said, my first read
> looked like the issue in the bugzilla I mentioned.  The patch Luis and
> I have for addressing multiple statements on the same line applies on
> top of the X86 and PowerPC reverse-finish patches.  

You should fix the reverse-stepping multiple statements issue first, and
then the reverse-finish problems go away, you won't need that patch any more.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 15:53                                                             ` [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp Tom de Vries
@ 2023-01-24 18:48                                                               ` Pedro Alves
  0 siblings, 0 replies; 105+ messages in thread
From: Pedro Alves @ 2023-01-24 18:48 UTC (permalink / raw)
  To: Tom de Vries, Carl Love, Bruno Larsen, Ulrich Weigand,
	will_schmidt, gdb-patches

On 2023-01-24 3:53 p.m., Tom de Vries wrote:

> On 1/23/23 20:17, Pedro Alves wrote:
>> I'd think this was on purpose.  Note that next/step/reverse-{next/step} are line-oriented
>> stepping commands, they step/next until the previous/next line.  While "finish" is described
>> as undoing the_function call_.
>>
>> The manual says:
>>
>>   reverse-finish
>>   Just as the finish command takes you to the point where the current function returns,
>>   reverse-finish takes you to the point where it was called. Instead of ending up at the end of
>>   the current function invocation, you end up at the beginning.
> 
> As well as:
> ...
> finish
> Continue running until just after function in the selected stack frame returns. Print the returned value (if any). This command can be abbreviated as fin.
> ...
> 
> It's only now that you mention the non-line nature of finish/reverse-finish that I realize that that is the case.  So I suppose the docs could be a bit more explicit about this aspect.

I guess.

> 
> I suppose an intuitive way to make available the two approaches (so without the user losing options) would be to introduce finishi next to finish and reverse-finishi next to finish, with the new commands retaining the current functionality and the old ones being adjusted to respect line boundaries.  But having the commands change behaviour is likely to cause confusion (well, assuming users notice the difference in the first place), so I'm not sure if that's a good idea.

They sure would notice a difference.  Say for example, a source line like:

   func1 (func2 (func3 ())));

and if you break in func3, and then do "finish", you expect that "step" steps into func2, while "next" would move to the next line.

If you changed finish to be line-oriented, then a "finish" while inside "func3" would either step over the whole "func1" call line instead,
or step into func2, depending on how you implement it.  Regardless, it'd be a noticeable change, and I think a bad one.
Also, it complicates where we print the return value, as we would no longer present the stop at the instruction where we are able
to retrieve it.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 16:04                                                                     ` Bruno Larsen
@ 2023-01-24 19:12                                                                       ` Pedro Alves
  2023-01-25  9:49                                                                         ` Bruno Larsen
  2023-01-25 14:11                                                                         ` Ulrich Weigand
  0 siblings, 2 replies; 105+ messages in thread
From: Pedro Alves @ 2023-01-24 19:12 UTC (permalink / raw)
  To: Bruno Larsen, Carl Love, Ulrich Weigand, will_schmidt, gdb-patches


On 2023-01-24 4:04 p.m., Bruno Larsen wrote:
> On 24/01/2023 16:06, Pedro Alves wrote:

>>> Notice how there were two "reverse-step" commands needed after the "reverse-finish" used to exit func2.
>> Yes.  And the reason you need two "reverse-step" is because there are two line ranges for line 8, and reverse-step stops
>> at the beginning of the second range instead of at the beginning of the first.  It's the exact same as with my simpler
>> example of just doing "next" -> "reverse-next", which I used as a simpler example to explain the problem.
> 
> The simplified example is not the exact same use case. 

Correct, but it's the same root cause.  Forget at reverse-finish, that is doing what it says it should do, that is,
to stop at the call to the function.  You can just put a breakpoint at that same instruction, and once there, do a
reverse-step.  GDB should then reverse step until it reaches a different line.  But it does not.  _That_ is the bug.

Vis (with gcc and column info):

 ...
 (gdb) reverse-finish 
 Run back to call of #0  func2 (i=1) at reverse.c:7
 0x0000555555555167 in main (argc=1, argv=0x7fffffffdc58) at reverse.c:11
 ^^^^^^^^^^^^^^^^^^
 11        func1 (argc); func2 (argc);
 (gdb) start
 The program being debugged has been started already.
 Start it from the beginning? (y or n) y
 Temporary breakpoint 2 at 0x555555555158: file reverse.c, line 11.
 Starting program: /home/pedro/reverse 
 [Thread debugging using libthread_db enabled]
 Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
 
 Temporary breakpoint 2, main (argc=1, argv=0x7fffffffdc58) at reverse.c:11
 11        func1 (argc); func2 (argc);
 (gdb) record
 (gdb) b *0x0000555555555167              << manually set the breakpoint where the reverse-finish would stop
 Breakpoint 4 at 0x555555555167: file reverse.c, line 11.
 (gdb) c
 Continuing.

 Breakpoint 4, 0x0000555555555167 in main (argc=1, argv=0x7fffffffdc58) at reverse.c:11
 11        func1 (argc); func2 (argc);    << started at line 11
 (gdb) reverse-step
 11        func1 (argc); func2 (argc);    << stopped at the same line, bug!

See, reverse-step stopped in the same line you started with.  That is a bug, it should never
happen.  Just like forward "step" never steps in the same line.  Because that's how the
commands are supposed to work -- step until the line number changes!

> Looking at how the program executes forward, if we next over this line we skip everything, but if we step into func1 and use finish we will still stop in line 11 and the user can decide to step into func2 or not. That is why I assumed you were thinking of a different issue when I saw you using next and reverse-next as examples.
> 
> Looking at where GDB lands when finishing from func1 we get (code compiled with gcc -gno-column-info):
> 
> (gdb) start
> Temporary breakpoint 1 at 0x401118: file t.c, line 8.
> Starting program: /home/blarsen/Documents/downstream_build/gdb/reverse
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib64/libthread_db.so.1".
> 
> Temporary breakpoint 1, main () at t.c:8
> 8           f1(); f2();
> (gdb) s
> f1 () at t.c:2
> 2       }
> (gdb) finish
> Run till exit from #0  f1 () at t.c:2
> 0x0000000000401122 in main () at t.c:8
> 8           f1(); f2();
> (gdb) disas /s
> Dump of assembler code for function main:
> t.c:
> 7       int main(){
>    0x0000000000401114 <+0>:     push   %rbp
>    0x0000000000401115 <+1>:     mov    %rsp,%rbp
> 
> 8           f1(); f2();
>    0x0000000000401118 <+4>:     mov    $0x0,%eax
>    0x000000000040111d <+9>:     call   0x401106 <f1>
> => 0x0000000000401122 <+14>:    mov    $0x0,%eax
>    0x0000000000401127 <+19>:    call   0x40110d <f2>
>    0x000000000040112c <+24>:    mov    $0x0,%eax
> 
> 9       }
>    0x0000000000401131 <+29>:    pop    %rbp
>    0x0000000000401132 <+30>:    ret
> End of assembler dump.
> 
> The behavior that we should emulate when going backwards is that finishing from func2 stops us on the 'mov' instruction between the calls. Looking at the clang session that I cut off from the previous email:
> 

What is there are more instructions in between the calls?  How do you know where to stop?

> Alright, here's the gdb session, with clang, no gdb patch:
> 
>  Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc48) at reverse.c:11
>  11        func1 (argc); func2 (argc);
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x0000555555555150 <+0>:     push   %rbp
>     0x0000555555555151 <+1>:     mov    %rsp,%rbp
>     0x0000555555555154 <+4>:     sub    $0x10,%rsp
>     0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
>     0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
>  
>  11        func1 (argc); func2 (argc);
>  => 0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
>     0x0000555555555162 <+18>:    call   0x555555555130 <func1>
>     0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
>     0x000055555555516a <+26>:    call   0x555555555140 <func2>
>  
>  12      }
>     0x000055555555516f <+31>:    xor    %eax,%eax
>     0x0000555555555171 <+33>:    add    $0x10,%rsp
>     0x0000555555555175 <+37>:    pop    %rbp
>     0x0000555555555176 <+38>:    ret
>  End of assembler dump.
>  (gdb) record
>  (gdb) b func2
>  Breakpoint 2 at 0x555555555147: file reverse.c, line 7.
>  (gdb) c
>  Continuing.
>  
>  Breakpoint 2, func2 (i=1) at reverse.c:7
>  7       }
>  (gdb) reverse-finish
>  Run back to call of #0  func2 (i=1) at reverse.c:7
>  0x000055555555516a in main (argc=1, argv=0x7fffffffdc48) at reverse.c:11
>  11        func1 (argc); func2 (argc);
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x0000555555555150 <+0>:     push   %rbp
>     0x0000555555555151 <+1>:     mov    %rsp,%rbp
>     0x0000555555555154 <+4>:     sub    $0x10,%rsp
>     0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
>     0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
>  
>  11        func1 (argc); func2 (argc);
>     0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
>     0x0000555555555162 <+18>:    call   0x555555555130 <func1>
>     0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
>  => 0x000055555555516a <+26>:    call   0x555555555140 <func2>
>  
>  12      }
>     0x000055555555516f <+31>:    xor    %eax,%eax
>     0x0000555555555171 <+33>:    add    $0x10,%rsp
>     0x0000555555555175 <+37>:    pop    %rbp
>     0x0000555555555176 <+38>:    ret
>  End of assembler dump.
>  (gdb) reverse-step
>  func1 (i=1) at reverse.c:3
>  3       }
>  (gdb)
> 
> We can see that GDB stopped on the call instruction instead. So a user that finished from func1 or reverse-finished from func2 may see different inferior states.
> 

Seeing different inferior states is expected, as finish and reverse-finish are not the exact mirror of one another, like step
and reverse-step are.  The exact reversal of finish would be the equivalent of being stopped at a function call return insn after
a "finish" (and the command could only be used while stopped there), and stepping back into the function up until the point
where you had typed "finish" and stopping there.  Obviously impossible to implement.  So we made "reverse-finish" do something
sensible, such as stepping backwards up until the call site.

> 
>>
>>> What Carl is proposing we do is make it so GDB only needs one command.
>> I understand.  However, I am saying that that is papering over the actual problem, _and_ it only works in the situation
>> where you ended up with two line entries with is-stmt for the same line.  Note how the patch breaks clang, and gcc with
>> -gno-column-info...
>>
>>> If I compare the $pc of where GDB is stopped and the linetable, we get:
>>>
>>> (gdb) print $pc
>>> $2 = (void (*)()) 0x401127 <main+19>
>>> (gdb) maint info line-table
>>> objfile: /home/blarsen/Documents/downstream_build/gdb/reverse ((struct objfile *) 0x10f7750)
>>> compunit_symtab: t.c ((struct compunit_symtab *) 0x116c330)
>>> symtab: /home/blarsen/Documents/downstream_build/gdb/t.c ((struct symtab *) 0x116c3b0)
>>> linetable: ((struct linetable *) 0x11aec80):
>>> INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END
>>> 0      1      0x0000000000401106 Y
>>> 1      2      0x000000000040110a Y
>>> 2      4      0x000000000040110d Y
>>> 3      5      0x0000000000401111 Y
>>> 4      7      0x0000000000401114 Y
>>> 5      8      0x0000000000401118 Y
>>> 6      8      0x0000000000401122 Y
>>> 7      9      0x0000000000401131 Y
>>> 8      END    0x0000000000401133 Y
>>>
>>> We can see that GDB shouldn't even be able to stop at that $pc, it isn't an is_stmt.
>> reverse-finish is not supposed to step backwards until it reaches is_stmt.  Doing so makes it
>> step backwards too much, as I've shown in my previous example.
>>
>>> We should have stopped at 0x401122, which is where the first reverse-step stops:
>> No...
>>
>>> (gdb) rs
>>> 8           f1(); f2();
>>> (gdb) p $pc
>>> $4 = (void (*)()) 0x401122 <main+14>
>> ... no because in the case where you don't have column debug info (or with clang), there won't be
>> an is-stmt entry for the f2 call/column, there will only be one single line entry for the whole of
>> line 8, so gdb would step back too much.
>>
>>> So not only are we needing an extra command to re-sync with user expectations, we are in an instruction where the inferior state might be all over the place.
>>>
>> What does that mean, the state might be all over the place?  The DWARF should describe the locations of all variables accurately at all instructions.
>>
> Unrelated to this specific issue, but I was looking at record/30025 (https://sourceware.org/bugzilla/show_bug.cgi?id=30025) and it confused me because because GDB sometimes reported the incorrect parameter, but if we continue single-stepping through instructions, GDB eventually finds the correct value when we stop at an is_stmt instruction.
> 
> If I misunderstood something about 30025 and is_stmt, please let me know! but as far as I can see, this is what happened.
> 

I can't tell what is going on in that bug without debugging it myself, but seeing SIGTRAP makes me suspect that
one thing that could be going on is that GDB didn't apply the decr-pc-after-break adjustment properly, so
then the PC is pointing into the middle of an instruction and then all hell breaks loose.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 18:25                                                                 ` Carl Love
@ 2023-01-24 19:21                                                                   ` Pedro Alves
  2023-01-24 19:26                                                                     ` Pedro Alves
  0 siblings, 1 reply; 105+ messages in thread
From: Pedro Alves @ 2023-01-24 19:21 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Ulrich Weigand, gdb-patches; +Cc: Luis Machado

On 2023-01-24 6:25 p.m., Carl Love wrote:

> I have not tested with clang.  Actually I have never used clang so this
> is another thing to look at and test.
> 
> 
> Let me see if I can summarize the current situation.
> 
> 1) The goal of the current X86 reverse patch is to fix the case where
> we have called function foo () and are trying to do a reverse-finish
> from inside the function.

Wrong goal.  There's nothing to fix there.  The command is working as designed.


>  The mainline gdb code stops at the entry to
> foo () then does a single instruction in the reverse direction to get
> to the caller.  Specifically, the code that this patch removes:
> 
> -      if (ecs->event_thread->control.proceed_to_finish  
> -         && execution_direction == EXEC_REVERSE)
> -       {         
> -         struct thread_info *tp = ecs->event_thread;
> -                  
> -         /* We are finishing a function in reverse, and just hit the
> -            step-resume breakpoint at the start address of the
> -            function, and we're almost there -- just need to back up
> -            by one more single-step, which should take us back to the
> -            function call.  */
> -         tp->control.step_range_start = tp->control.step_range_end = 1;
> -         keep_going (ecs);
> -         return;
> 
> The single-step in gdb results in stopping at the last instruction in
> the line where function foo is called. The result here is that you now
> need to do two reverse-next instructions to get to the previous line. 

And that is the bug.  reverse-next/reverse-step should _never_ stop at the same line.
Same as forward step/next.  For instance, this "next" command will just continue
stepping forever:

 Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc98) at reverse.c:11
 11        while (1);
 (gdb) next

Same for "step" instead of "next".

It turns out that reverse-next/step do stop immediately!

 (gdb) reverse-next
 11        while (1);
 (gdb) reverse-next
 11        while (1);
 (gdb) 

That's probably caused by the same bug.

> The command sequence is:  reverse-finish; reverse-next; reverst-next to
> go from inside the function to the previous line in the caller.
> 
> Note, in this case you are in the function and trying to return to the
> caller with the reverse-finish command.  That is a different scenario
> from what Pedro is talking about in 2) below.
> 
> 2) The scenario that Pedro brings up is a reverse-next over a line with
> two function calls on the same source line, i.e.
> 
>> 9       int main ()
>> 10      {
>> 11        func1 (); func2 ();
>> 12      }
> 
> In this case you are in the caller and are trying to do a reverse-next
> over the two function callers.  This is a different scenario from 1).
> 

I know it's a different scenario, but my scenario is just a way to show
up that the root of the problem can be seen with a simpler scenario.  The
problem is in the reverse-step command, and you are focusing on the reverse-finish
command, incorrectly.  Please read my responses to Bruno as well.

> 3)  The bug that I mentioned earlier for the case of
> multiple executable statements on the same line.
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=28426
> 
> is for a case like:
> 
> int main ()
> {
>   int a, b, c, d;
>   a = 1;
>   b = 2;
>   c = 3; d = 4;
>   a = a + b + c + d;
> }
> 
> In this case the reverse-next from the last line a = a + b + c + d; is
> not stepping all the way back over the line c = 3; d = 4;.  This is a
> simpler version of 2).  Specifically the command sequence to step over
> line c = 3; d = 4; is reverse-next, reverse-next.  Only one reverse-
> next should be required.
> 

Exactly.  It's all the same bug.

> The patch that Luis and I have worked on fixes this issue, however it
> does not fix the case of the multiple statements being function calls,
> i.e. 2) above that Pedro is bringing up.

I have said it numerous times now, but it's worth repeating.  It's all
the same bug.  :-)  Fix reverse-step, and then the reverse-finish
scenario fixes itself, because you will no longer need to issue
two reverse-step commands after reverse-finish.

> 
> 
> From a subsequent message from Pedro in this thread:
> 
>    On Tue, 2023-01-24 at 15:06 +0000, Pedro Alves wrote:
>    > Yes.  And the reason you need two "reverse-step" is because there are
>    > two line ranges for line 8, and reverse-step stops
>    > at the beginning of the second range instead of at the beginning of
>    > the first.  It's the exact same as with my simpler
>    > example of just doing "next" -> "reverse-next", which I used as a
>    > simpler example to explain the problem.
>    > 
>    > > What Carl is proposing we do is make it so GDB only needs one
>    > > command.
>    > 
>    > I understand.  However, I am saying that that is papering over the
>    > actual problem, _and_ it only works in the situation
>    > where you ended up with two line entries with is-stmt for the same
>    > line.  Note how the patch breaks clang, and gcc with
>    > -gno-column-info...
> 
> I don't agree that I am "papering over the actual problem" rather I
> think at this point that Pedro's test case is an additional case of the
> reverse-next command being broken by my patch to fix the reverse-finish 
> command.  The problem doesn't exist without my patch.  
> 
> 
> So at this point, I need to go see if I can figure out how the patch to
> fix the reverse-finish command causes the regression in 2) for the
> reverse-next command.

At this point.  NAK on the reverse-finish fix.

> 
> Looks like we also need an to add an additional test case for 2). 
> Also, will need to look at how any new fix for 2) behaves with clang.
> 
> Thanks for all the input on this issue.  It seems that there is still
> work to do.  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 19:21                                                                   ` Pedro Alves
@ 2023-01-24 19:26                                                                     ` Pedro Alves
  0 siblings, 0 replies; 105+ messages in thread
From: Pedro Alves @ 2023-01-24 19:26 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Ulrich Weigand, gdb-patches; +Cc: Luis Machado

On 2023-01-24 7:21 p.m., Pedro Alves wrote:
> And that is the bug.  reverse-next/reverse-step should _never_ stop at the same line.
> Same as forward step/next.  For instance, this "next" command will just continue
> stepping forever:
> 
>  Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc98) at reverse.c:11
>  11        while (1);
>  (gdb) next
> 
> Same for "step" instead of "next".
> 
> It turns out that reverse-next/step do stop immediately!
> 
>  (gdb) reverse-next
>  11        while (1);
>  (gdb) reverse-next
>  11        while (1);
>  (gdb) 
> 
> That's probably caused by the same bug.


From the documentation:

 reverse-step [count]
 Run the program backward until control reaches the start of a different source line;
                                                               ^^^^^^^^^

Emphasis mine.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 19:12                                                                       ` Pedro Alves
@ 2023-01-25  9:49                                                                         ` Bruno Larsen
  2023-01-25 14:11                                                                         ` Ulrich Weigand
  1 sibling, 0 replies; 105+ messages in thread
From: Bruno Larsen @ 2023-01-25  9:49 UTC (permalink / raw)
  To: Pedro Alves, Carl Love, Ulrich Weigand, will_schmidt, gdb-patches

On 24/01/2023 20:12, Pedro Alves wrote:
> On 2023-01-24 4:04 p.m., Bruno Larsen wrote:
>> On 24/01/2023 16:06, Pedro Alves wrote:
>>>> Notice how there were two "reverse-step" commands needed after the "reverse-finish" used to exit func2.
>>> Yes.  And the reason you need two "reverse-step" is because there are two line ranges for line 8, and reverse-step stops
>>> at the beginning of the second range instead of at the beginning of the first.  It's the exact same as with my simpler
>>> example of just doing "next" -> "reverse-next", which I used as a simpler example to explain the problem.
>> The simplified example is not the exact same use case.
> Correct, but it's the same root cause.  Forget at reverse-finish, that is doing what it says it should do, that is,
> to stop at the call to the function.  You can just put a breakpoint at that same instruction, and once there, do a
> reverse-step.  GDB should then reverse step until it reaches a different line.  But it does not.  _That_ is the bug.
Ok, you convinced me. I played around some more with the no-column-info 
example and what you said and I agree that fixing the column info bug 
would fix Carl's bug for this patch. I'll update the relevant bug 
(https://sourceware.org/bugzilla/show_bug.cgi?id=28426) and now we have 
a way to reproduce that!
>
> Vis (with gcc and column info):
>
>   ...
>   (gdb) reverse-finish
>   Run back to call of #0  func2 (i=1) at reverse.c:7
>   0x0000555555555167 in main (argc=1, argv=0x7fffffffdc58) at reverse.c:11
>   ^^^^^^^^^^^^^^^^^^
>   11        func1 (argc); func2 (argc);
>   (gdb) start
>   The program being debugged has been started already.
>   Start it from the beginning? (y or n) y
>   Temporary breakpoint 2 at 0x555555555158: file reverse.c, line 11.
>   Starting program: /home/pedro/reverse
>   [Thread debugging using libthread_db enabled]
>   Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
>   
>   Temporary breakpoint 2, main (argc=1, argv=0x7fffffffdc58) at reverse.c:11
>   11        func1 (argc); func2 (argc);
>   (gdb) record
>   (gdb) b *0x0000555555555167              << manually set the breakpoint where the reverse-finish would stop
>   Breakpoint 4 at 0x555555555167: file reverse.c, line 11.
>   (gdb) c
>   Continuing.
>
>   Breakpoint 4, 0x0000555555555167 in main (argc=1, argv=0x7fffffffdc58) at reverse.c:11
>   11        func1 (argc); func2 (argc);    << started at line 11
>   (gdb) reverse-step
>   11        func1 (argc); func2 (argc);    << stopped at the same line, bug!
>
> See, reverse-step stopped in the same line you started with.  That is a bug, it should never
> happen.  Just like forward "step" never steps in the same line.  Because that's how the
> commands are supposed to work -- step until the line number changes!
>
>> Looking at how the program executes forward, if we next over this line we skip everything, but if we step into func1 and use finish we will still stop in line 11 and the user can decide to step into func2 or not. That is why I assumed you were thinking of a different issue when I saw you using next and reverse-next as examples.
>>
>> Looking at where GDB lands when finishing from func1 we get (code compiled with gcc -gno-column-info):
>>
>> (gdb) start
>> Temporary breakpoint 1 at 0x401118: file t.c, line 8.
>> Starting program: /home/blarsen/Documents/downstream_build/gdb/reverse
>> [Thread debugging using libthread_db enabled]
>> Using host libthread_db library "/lib64/libthread_db.so.1".
>>
>> Temporary breakpoint 1, main () at t.c:8
>> 8           f1(); f2();
>> (gdb) s
>> f1 () at t.c:2
>> 2       }
>> (gdb) finish
>> Run till exit from #0  f1 () at t.c:2
>> 0x0000000000401122 in main () at t.c:8
>> 8           f1(); f2();
>> (gdb) disas /s
>> Dump of assembler code for function main:
>> t.c:
>> 7       int main(){
>>     0x0000000000401114 <+0>:     push   %rbp
>>     0x0000000000401115 <+1>:     mov    %rsp,%rbp
>>
>> 8           f1(); f2();
>>     0x0000000000401118 <+4>:     mov    $0x0,%eax
>>     0x000000000040111d <+9>:     call   0x401106 <f1>
>> => 0x0000000000401122 <+14>:    mov    $0x0,%eax
>>     0x0000000000401127 <+19>:    call   0x40110d <f2>
>>     0x000000000040112c <+24>:    mov    $0x0,%eax
>>
>> 9       }
>>     0x0000000000401131 <+29>:    pop    %rbp
>>     0x0000000000401132 <+30>:    ret
>> End of assembler dump.
>>
>> The behavior that we should emulate when going backwards is that finishing from func2 stops us on the 'mov' instruction between the calls. Looking at the clang session that I cut off from the previous email:
>>
> What is there are more instructions in between the calls?  How do you know where to stop?
>
>> Alright, here's the gdb session, with clang, no gdb patch:
>>
>>   Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc48) at reverse.c:11
>>   11        func1 (argc); func2 (argc);
>>   (gdb) disassemble /s
>>   Dump of assembler code for function main:
>>   reverse.c:
>>   10      {
>>      0x0000555555555150 <+0>:     push   %rbp
>>      0x0000555555555151 <+1>:     mov    %rsp,%rbp
>>      0x0000555555555154 <+4>:     sub    $0x10,%rsp
>>      0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
>>      0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
>>   
>>   11        func1 (argc); func2 (argc);
>>   => 0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
>>      0x0000555555555162 <+18>:    call   0x555555555130 <func1>
>>      0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
>>      0x000055555555516a <+26>:    call   0x555555555140 <func2>
>>   
>>   12      }
>>      0x000055555555516f <+31>:    xor    %eax,%eax
>>      0x0000555555555171 <+33>:    add    $0x10,%rsp
>>      0x0000555555555175 <+37>:    pop    %rbp
>>      0x0000555555555176 <+38>:    ret
>>   End of assembler dump.
>>   (gdb) record
>>   (gdb) b func2
>>   Breakpoint 2 at 0x555555555147: file reverse.c, line 7.
>>   (gdb) c
>>   Continuing.
>>   
>>   Breakpoint 2, func2 (i=1) at reverse.c:7
>>   7       }
>>   (gdb) reverse-finish
>>   Run back to call of #0  func2 (i=1) at reverse.c:7
>>   0x000055555555516a in main (argc=1, argv=0x7fffffffdc48) at reverse.c:11
>>   11        func1 (argc); func2 (argc);
>>   (gdb) disassemble /s
>>   Dump of assembler code for function main:
>>   reverse.c:
>>   10      {
>>      0x0000555555555150 <+0>:     push   %rbp
>>      0x0000555555555151 <+1>:     mov    %rsp,%rbp
>>      0x0000555555555154 <+4>:     sub    $0x10,%rsp
>>      0x0000555555555158 <+8>:     mov    %edi,-0x4(%rbp)
>>      0x000055555555515b <+11>:    mov    %rsi,-0x10(%rbp)
>>   
>>   11        func1 (argc); func2 (argc);
>>      0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
>>      0x0000555555555162 <+18>:    call   0x555555555130 <func1>
>>      0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
>>   => 0x000055555555516a <+26>:    call   0x555555555140 <func2>
>>   
>>   12      }
>>      0x000055555555516f <+31>:    xor    %eax,%eax
>>      0x0000555555555171 <+33>:    add    $0x10,%rsp
>>      0x0000555555555175 <+37>:    pop    %rbp
>>      0x0000555555555176 <+38>:    ret
>>   End of assembler dump.
>>   (gdb) reverse-step
>>   func1 (i=1) at reverse.c:3
>>   3       }
>>   (gdb)
>>
>> We can see that GDB stopped on the call instruction instead. So a user that finished from func1 or reverse-finished from func2 may see different inferior states.
>>
> Seeing different inferior states is expected, as finish and reverse-finish are not the exact mirror of one another, like step
> and reverse-step are.  The exact reversal of finish would be the equivalent of being stopped at a function call return insn after
> a "finish" (and the command could only be used while stopped there), and stepping back into the function up until the point
> where you had typed "finish" and stopping there.  Obviously impossible to implement.  So we made "reverse-finish" do something
> sensible, such as stepping backwards up until the call site.
>
>>>> What Carl is proposing we do is make it so GDB only needs one command.
>>> I understand.  However, I am saying that that is papering over the actual problem, _and_ it only works in the situation
>>> where you ended up with two line entries with is-stmt for the same line.  Note how the patch breaks clang, and gcc with
>>> -gno-column-info...
>>>
>>>> If I compare the $pc of where GDB is stopped and the linetable, we get:
>>>>
>>>> (gdb) print $pc
>>>> $2 = (void (*)()) 0x401127 <main+19>
>>>> (gdb) maint info line-table
>>>> objfile: /home/blarsen/Documents/downstream_build/gdb/reverse ((struct objfile *) 0x10f7750)
>>>> compunit_symtab: t.c ((struct compunit_symtab *) 0x116c330)
>>>> symtab: /home/blarsen/Documents/downstream_build/gdb/t.c ((struct symtab *) 0x116c3b0)
>>>> linetable: ((struct linetable *) 0x11aec80):
>>>> INDEX  LINE   ADDRESS            IS-STMT PROLOGUE-END
>>>> 0      1      0x0000000000401106 Y
>>>> 1      2      0x000000000040110a Y
>>>> 2      4      0x000000000040110d Y
>>>> 3      5      0x0000000000401111 Y
>>>> 4      7      0x0000000000401114 Y
>>>> 5      8      0x0000000000401118 Y
>>>> 6      8      0x0000000000401122 Y
>>>> 7      9      0x0000000000401131 Y
>>>> 8      END    0x0000000000401133 Y
>>>>
>>>> We can see that GDB shouldn't even be able to stop at that $pc, it isn't an is_stmt.
>>> reverse-finish is not supposed to step backwards until it reaches is_stmt.  Doing so makes it
>>> step backwards too much, as I've shown in my previous example.
>>>
>>>> We should have stopped at 0x401122, which is where the first reverse-step stops:
>>> No...
>>>
>>>> (gdb) rs
>>>> 8           f1(); f2();
>>>> (gdb) p $pc
>>>> $4 = (void (*)()) 0x401122 <main+14>
>>> ... no because in the case where you don't have column debug info (or with clang), there won't be
>>> an is-stmt entry for the f2 call/column, there will only be one single line entry for the whole of
>>> line 8, so gdb would step back too much.
>>>
>>>> So not only are we needing an extra command to re-sync with user expectations, we are in an instruction where the inferior state might be all over the place.
>>>>
>>> What does that mean, the state might be all over the place?  The DWARF should describe the locations of all variables accurately at all instructions.
>>>
>> Unrelated to this specific issue, but I was looking at record/30025 (https://sourceware.org/bugzilla/show_bug.cgi?id=30025) and it confused me because because GDB sometimes reported the incorrect parameter, but if we continue single-stepping through instructions, GDB eventually finds the correct value when we stop at an is_stmt instruction.
>>
>> If I misunderstood something about 30025 and is_stmt, please let me know! but as far as I can see, this is what happened.
>>
> I can't tell what is going on in that bug without debugging it myself, but seeing SIGTRAP makes me suspect that
> one thing that could be going on is that GDB didn't apply the decr-pc-after-break adjustment properly, so
> then the PC is pointing into the middle of an instruction and then all hell breaks loose.
>
oh! This is very helpful, thank you!

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-24 19:12                                                                       ` Pedro Alves
  2023-01-25  9:49                                                                         ` Bruno Larsen
@ 2023-01-25 14:11                                                                         ` Ulrich Weigand
  2023-01-25 16:42                                                                           ` Pedro Alves
  1 sibling, 1 reply; 105+ messages in thread
From: Ulrich Weigand @ 2023-01-25 14:11 UTC (permalink / raw)
  To: gdb-patches, will_schmidt, Bruno Larsen, cel, pedro

Pedro Alves <pedro@palves.net> wrote:

> > 11        func1 (argc); func2 (argc);
> >    0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
> >    0x0000555555555162 <+18>:    call   0x555555555130 <func1>
> >    0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
> > => 0x000055555555516a <+26>:    call   0x555555555140 <func2>
> > 
> > 12      }
> >    0x000055555555516f <+31>:    xor    %eax,%eax
> >    0x0000555555555171 <+33>:    add    $0x10,%rsp
> >    0x0000555555555175 <+37>:    pop    %rbp
> >    0x0000555555555176 <+38>:    ret
> > End of assembler dump.
> > (gdb) reverse-step
> > func1 (i=1) at reverse.c:3
> > 3       }
> > (gdb)
> >
> >We can see that GDB stopped on the call instruction instead. So a user that finished from func1 or reverse-finished from func2 may see different inferior states.

>Seeing different inferior states is expected, as finish and reverse-finish are not the exact mirror of one another, like step
>and reverse-step are.  The exact reversal of finish would be the equivalent of being stopped at a function call return insn after
>a "finish" (and the command could only be used while stopped there), and stepping back into the function up until the point
>where you had typed "finish" and stopping there.  Obviously impossible to implement.  So we made "reverse-finish" do something
>sensible, such as stepping backwards up until the call site.

Hi Pedro,

I certainly agree with you that reverse-step needs to be fixed,
and this explains at least part of the problems we were seeing.

However, I do think there is still another issue specific to
reverse-finish, along the lines Bruno pointed out.  And in fact,
I do think that there is (or at least should be!) a well-defined
symmetry between finish and reverse-finish:

The effect of "finish" is: skip until the end of the current
function and then do a "step".  (Semantically equivalently,
do a series of "next" until you leave the current function.)

Similarly, the effect of "reverse-finish" *should* be: reverse-skip
until the beginning of the current function and then do a reverse-step.
(Or semantically equivalent, do a series of "reverse-next" until you
leave the current function.)

However, the actual implementation of reverse-finish is subtly but
significantly different: it reverse-skips until the beginning of the
current function and then does a reverse-stepi (not reverse-step).

This has the at least surprising, but IMO even incorrect, effect
that when on the first line of a function, "reverse-finish" ends
up in a different place than "reverse-step".  I believe they 
ought to end up in the same place.


This was one of the primary intentions behind Carl's patch: change
reverse-finish so it does a reverse-step instead of a reverse-stepi.
(Of course, for this to be useful, reverse-step itself needs to work
correctly - which it doesn't right now as you point out.)

Bye,
Ulrich


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-25 14:11                                                                         ` Ulrich Weigand
@ 2023-01-25 16:42                                                                           ` Pedro Alves
  2023-01-25 17:13                                                                             ` Ulrich Weigand
  0 siblings, 1 reply; 105+ messages in thread
From: Pedro Alves @ 2023-01-25 16:42 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches, will_schmidt, Bruno Larsen, cel



On 2023-01-25 2:11 p.m., Ulrich Weigand wrote:
> Pedro Alves <pedro@palves.net> wrote:
> 
>>> 11        func1 (argc); func2 (argc);
>>>    0x000055555555515f <+15>:    mov    -0x4(%rbp),%edi
>>>    0x0000555555555162 <+18>:    call   0x555555555130 <func1>
>>>    0x0000555555555167 <+23>:    mov    -0x4(%rbp),%edi
>>> => 0x000055555555516a <+26>:    call   0x555555555140 <func2>
>>>
>>> 12      }
>>>    0x000055555555516f <+31>:    xor    %eax,%eax
>>>    0x0000555555555171 <+33>:    add    $0x10,%rsp
>>>    0x0000555555555175 <+37>:    pop    %rbp
>>>    0x0000555555555176 <+38>:    ret
>>> End of assembler dump.
>>> (gdb) reverse-step
>>> func1 (i=1) at reverse.c:3
>>> 3       }
>>> (gdb)
>>>
>>> We can see that GDB stopped on the call instruction instead. So a user that finished from func1 or reverse-finished from func2 may see different inferior states.
> 
>> Seeing different inferior states is expected, as finish and reverse-finish are not the exact mirror of one another, like step
>> and reverse-step are.  The exact reversal of finish would be the equivalent of being stopped at a function call return insn after
>> a "finish" (and the command could only be used while stopped there), and stepping back into the function up until the point
>> where you had typed "finish" and stopping there.  Obviously impossible to implement.  So we made "reverse-finish" do something
>> sensible, such as stepping backwards up until the call site.
> 
> Hi Pedro,
> 
> I certainly agree with you that reverse-step needs to be fixed,
> and this explains at least part of the problems we were seeing.
> 
> However, I do think there is still another issue specific to
> reverse-finish, along the lines Bruno pointed out.  And in fact,
> I do think that there is (or at least should be!) a well-defined
> symmetry between finish and reverse-finish:
> 
> The effect of "finish" is: skip until the end of the current
> function and then do a "step".  (Semantically equivalently,
> do a series of "next" until you leave the current function.)

But that this is not actually true -- this is not how finish is implemented.

Instead, we unwind to the caller frame, and put a breakpoint at that
frame'c PC, and run freely to that.  A frame's PC is defined as the address
of the instruction that is executed once the callee returns.

OTOH, a (forward) step at the return line of a function steps until a different
line is reached, and in the case we step out of a function, once it reaches the
caller it notices we ended up in the middle of a line so it continues stepping until
the next line.

Note that finish vs step difference visible here:

(gdb) list 1
1       int func1 (int i)
2       {
3         return i + 1;
4       }
5
6       int func2 (int i)
7       {
8         return i + 1;
9       }
10
11      int main (int argc, char **argv)
12      {
13        func1 (func2 (argc));
14        return 0;
15      }
(gdb) 

(gdb) b func2
Breakpoint 1 at 0x1147: file finish.c, line 8.
(gdb) r
Starting program: /home/pedro/finish 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, func2 (i=1) at finish.c:8
8         return i + 1;
(gdb) finish
Run till exit from #0  func2 (i=1) at finish.c:8
0x000055555555516c in main (argc=1, argv=0x7fffffffdcb8) at finish.c:13    <<< stopped in the middle of the line, as indicated by address on the left
13        func1 (func2 (argc));
Value returned is $1 = 2                                                   <<< at this location we can use ABI knowledge to retrieve the return value
(gdb) p $pc
$2 = (void (*)()) 0x55555555516c <main+29>                                 <<< matches the "0x000055555555516c in main" above, of course

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/pedro/finish 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, func2 (i=1) at finish.c:8
8         return i + 1;
(gdb) step
9       }                                                                  <<< stopped a line bounary, and stepped over the func1 call as well!
(gdb) p $pc
$3 = (void (*)()) 0x55555555514d <func2+17>


> 
> Similarly, the effect of "reverse-finish" *should* be: reverse-skip
> until the beginning of the current function and then do a reverse-step.
> (Or semantically equivalent, do a series of "reverse-next" until you
> leave the current function.)

I disagree, because that reverse-step would step backwards too much.  Instead of stepping back to the
call of the function, it would step back further, as reverse-step will try to stop at the
beginning of a line.  By doing that, you'll potentially step backwards more statements that
exist in the same line.  Like:

  a = 1; b = 2; func();

stepping back from inside func should stop at the first instruction of that whole line.
But finishing backwards should stop at the call to func(), without considering line
boundaries, just like forward finish does not.

From the manual:

   "Like the step command, reverse-step will only stop at the beginning of a source line. It “un-executes” the previously executed source line."

> 
> However, the actual implementation of reverse-finish is subtly but
> significantly different: it reverse-skips until the beginning of the
> current function and then does a reverse-stepi (not reverse-step).
> 
> This has the at least surprising, but IMO even incorrect, effect
> that when on the first line of a function, "reverse-finish" ends
> up in a different place than "reverse-step".  I believe they 
> ought to end up in the same place.

I disagree.

Pedro Alves

> 
> 
> This was one of the primary intentions behind Carl's patch: change
> reverse-finish so it does a reverse-step instead of a reverse-stepi.
> (Of course, for this to be useful, reverse-step itself needs to work
> correctly - which it doesn't right now as you point out.)
> 
> Bye,
> Ulrich
> 

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-25 16:42                                                                           ` Pedro Alves
@ 2023-01-25 17:13                                                                             ` Ulrich Weigand
  2023-01-25 17:24                                                                               ` Pedro Alves
  0 siblings, 1 reply; 105+ messages in thread
From: Ulrich Weigand @ 2023-01-25 17:13 UTC (permalink / raw)
  To: gdb-patches, will_schmidt, Bruno Larsen, cel, pedro

Pedro Alves <pedro@palves.net> wrote:
On 2023-01-25 2:11 p.m., Ulrich Weigand wrote:
> >The effect of "finish" is: skip until the end of the current
> >function and then do a "step".  (Semantically equivalently,
> >do a series of "next" until you leave the current function.)
>
>But that this is not actually true -- this is not how finish is implemented.

Ah, you're right.  I misremembered - I thought we were still stepping
after the step-resume breakpoint, but looks like we are not.

>Breakpoint 1, func2 (i=1) at finish.c:8
>8         return i + 1;
>(gdb) step
>9       }                                                                  <<< stopped a line bounary, and stepped over the func1 call as well!
>(gdb) p $pc
>$3 = (void (*)()) 0x55555555514d <func2+17>

So this is still at the return in func2, but you're right,
the next step brings us directly to func1 without stopping
in main at all.  This is indeed unlike finish.

>I disagree.

OK, you've convinced me as well.  Sorry for the confusion ...

Bye,
Ulrich


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-25 17:13                                                                             ` Ulrich Weigand
@ 2023-01-25 17:24                                                                               ` Pedro Alves
  2023-01-25 19:38                                                                                 ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Pedro Alves @ 2023-01-25 17:24 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches, will_schmidt, Bruno Larsen, cel

On 2023-01-25 5:13 p.m., Ulrich Weigand wrote:
>> Breakpoint 1, func2 (i=1) at finish.c:8
>> 8         return i + 1;
>> (gdb) step
>> 9       }                                                                  <<< stopped a line bounary, and stepped over the func1 call as well!
>> (gdb) p $pc
>> $3 = (void (*)()) 0x55555555514d <func2+17>
> So this is still at the return in func2, 

Whoops, the example that I quickly typed up didn't actually have an explicit return
line when I first tried it (it returned void), and then I thought of adding one and I added it
I missed that I now needed one extra step to get out of func, thinking I was at the last
line of main already.

> but you're right,
> the next step brings us directly to func1 without stopping
> in main at all.  This is indeed unlike finish.
> 

Exactly.

>> I disagree.
> OK, you've convinced me as well.  Sorry for the confusion ...

No worries!

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-25 17:24                                                                               ` Pedro Alves
@ 2023-01-25 19:38                                                                                 ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-01-25 19:38 UTC (permalink / raw)
  To: Pedro Alves, Ulrich Weigand, gdb-patches, Bruno Larsen; +Cc: cel, luis.machado

Pedro, Ulrich, Tom, Bruno:

On Wed, 2023-01-25 at 17:24 +0000, Pedro Alves wrote:
> On 2023-01-25 5:13 p.m., Ulrich Weigand wrote:
> > > Breakpoint 1, func2 (i=1) at finish.c:8
> > > 8         return i + 1;
> > > (gdb) step
> > > 9       }                                                        
> > >           <<< stopped a line bounary, and stepped over the func1
> > > call as well!
> > > (gdb) p $pc
> > > $3 = (void (*)()) 0x55555555514d <func2+17>
> > So this is still at the return in func2, 
> 
> Whoops, the example that I quickly typed up didn't actually have an
> explicit return
> line when I first tried it (it returned void), and then I thought of
> adding one and I added it
> I missed that I now needed one extra step to get out of func,
> thinking I was at the last
> line of main already.
> 
> > but you're right,
> > the next step brings us directly to func1 without stopping
> > in main at all.  This is indeed unlike finish.
> > 
> 
> Exactly.
> 
> > > I disagree.
> > OK, you've convinced me as well.  Sorry for the confusion ...
> 
> No worries!

OK, so there seems to be agreement that we do not want to move forward
with this patch to change the behavior of the reverse-finish command. 
The consensus is the reverse-finish command is working as expected. So,
I formally withdraw patch 1 of 2 from consideration.

I worked on a patch with Luis, who is now busy with other things, to
fix the issue of two "simple" executable statements on a line not
working.  The patch fixed that issue, but does not fix the example from
Pedro of two function calls in the same source line.  So, I will pickup
this patch again and see if I can get the patch to correctly handle
column debug info and the is-stmt entry stuff and not break clang.

The second patch in this series address the reverse-finish command on
PowerPC which does not work due to the multiple entry points used in
PowerPC.  I will rework the PowerPC patch to apply on mainline to
address the PowerPC issues so the reverse-finish command will behave
the same as on X86.  This is probably the simpler/easier of the two
patches to do.

Thanks for all the discussion and help with this issue.

                                Carl 




^ permalink raw reply	[flat|nested] 105+ messages in thread

* Reverse-next bug test case
  2023-01-24 14:08                                                               ` Pedro Alves
                                                                                   ` (2 preceding siblings ...)
  2023-01-24 18:25                                                                 ` Carl Love
@ 2023-01-31  0:17                                                                 ` Carl Love
  2023-02-01 14:37                                                                   ` Pedro Alves
  3 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-01-31  0:17 UTC (permalink / raw)
  To: Pedro Alves, Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches; +Cc: cel

Pedro, Ulrich, Tom, Bruno:

I put together a test case that demonstrates the error in the reverse-
next command based on Pedro's example from our earlier discussion.  I
thought it would be best to make sure we all agree what the expected
behavior of the test should be before attempting to fix the issue.  :-)

The first test scenario in the test is the example that Pedo gave.  The
test expects that the reverse-next will stop at the beginning of the
line containing the two function calls.  Then a reverse-step command
should then stop at the previous source code line.  The test currently
fails the same on X86 and PowerPC, as expected, because the reverse-
next in correctly stops between func1 and func2.  The following
reverse-step stops at the end of func1 not at the previous source code
line as it should.  

I added a second test to do a reverse-step all the way back thru the
source line with the two function calls on it to make sure we agree on
the expected results for that scenario as well.  The second test passes
on X86 and PowerPC.

The test case, explanation from Pedro's test, i.e. my first test case.

The patch for the new test case is attached at the end.

Thanks for the help reviewing this test.

                  Carl 

On Tue, 2023-01-24 at 14:08 +0000, Pedro Alves wrote:

<snip>
 
> 
> Wait.  That right there sounds bogus.  The source line looks like:
> 
>    func1 ();  func2 ();
> 
> so stepping backwards over that line should always stop at the first
> instruction of the line, not in the middle.  Let's simplify this.
> 
> Here's the full source code of my example:
> 
> (gdb) list 1
> 1       void func1 ()
> 2       {
> 3       }
> 4
> 5       void func2 ()
> 6       {
> 7       }
> 8
> 9       int main ()
> 10      {
> 11        func1 (); func2 ();
> 12      }
> 
> Compiled with:
> 
>  $ gcc reverse.c -o reverse -g3 -O0
>  $ gcc -v
>  ...
>  gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)
> 
> Now let's debug it with target record, using current gdb git master
> (f3d8ae90b236),
> without your patch:
> 
>  $ gdb ~/reverse
>  GNU gdb (GDB) 14.0.50.20230124-git
>  ...
>  Reading symbols from /home/pedro/reverse...
>  (gdb) start
>  Temporary breakpoint 1 at 0x1147: file reverse.c, line 11.
>  Starting program: /home/pedro/reverse 
>  [Thread debugging using libthread_db enabled]
>  Using host libthread_db library "/lib/x86_64-linux-
> gnu/libthread_db.so.1".
> 
>  Temporary breakpoint 1, main () at reverse.c:11
>  11        func1 (); func2 ();
>  (gdb) record 
> 
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x000055555555513f <+0>:     endbr64
>     0x0000555555555143 <+4>:     push   %rbp
>     0x0000555555555144 <+5>:     mov    %rsp,%rbp
> 
>  11        func1 (); func2 ();
>  => 0x0000555555555147 <+8>:     mov    $0x0,%eax
>     0x000055555555514c <+13>:    call   0x555555555129 <func1>
>     0x0000555555555151 <+18>:    mov    $0x0,%eax
>     0x0000555555555156 <+23>:    call   0x555555555134 <func2>
>     0x000055555555515b <+28>:    mov    $0x0,%eax
> 
>  12      }
>     0x0000555555555160 <+33>:    pop    %rbp
>     0x0000555555555161 <+34>:    ret
>  End of assembler dump.
> 
>  (gdb) n
>  12      }
> 
> So far so good, a "next" stepped over the whole of line 11 and
> stopped at line 12.
> 
> Let's confirm where we are now:
> 
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x000055555555513f <+0>:     endbr64
>     0x0000555555555143 <+4>:     push   %rbp
>     0x0000555555555144 <+5>:     mov    %rsp,%rbp
> 
>  11        func1 (); func2 ();
>     0x0000555555555147 <+8>:     mov    $0x0,%eax
>     0x000055555555514c <+13>:    call   0x555555555129 <func1>
>     0x0000555555555151 <+18>:    mov    $0x0,%eax
>     0x0000555555555156 <+23>:    call   0x555555555134 <func2>
>     0x000055555555515b <+28>:    mov    $0x0,%eax
> 
>  12      }
>  => 0x0000555555555160 <+33>:    pop    %rbp
>     0x0000555555555161 <+34>:    ret
>  End of assembler dump.
> 
> Good, we're at the first instruction of line 12.
> 
> Now let's undo the "next", with "reverse-next":
> 
>  (gdb) reverse-next
>  11        func1 (); func2 ();
> 
> Seemingly stopped at line 11.  Let's see exactly where:
> 
>  (gdb) disassemble /s
>  Dump of assembler code for function main:
>  reverse.c:
>  10      {
>     0x000055555555513f <+0>:     endbr64
>     0x0000555555555143 <+4>:     push   %rbp
>     0x0000555555555144 <+5>:     mov    %rsp,%rbp
> 
>  11        func1 (); func2 ();
>     0x0000555555555147 <+8>:     mov    $0x0,%eax
>     0x000055555555514c <+13>:    call   0x555555555129 <func1>
>  => 0x0000555555555151 <+18>:    mov    $0x0,%eax
>     0x0000555555555156 <+23>:    call   0x555555555134 <func2>
>     0x000055555555515b <+28>:    mov    $0x0,%eax
> 
>  12      }
>     0x0000555555555160 <+33>:    pop    %rbp
>     0x0000555555555161 <+34>:    ret
>  End of assembler dump.
>  (gdb) 
> 
> And lo, we stopped in the middle of line 11!  That is a bug, we
> should have stepped
> back all the way to the beginning of the line.  The "reverse-next"
> should have fully
> undone the prior "next" command.  Here's the same thing without the
> distracting
> disassemble commands:
> 
>  (gdb) b 11
>  Breakpoint 1 at 0x1147: file reverse.c, line 11.
>  (gdb) r
>  Starting program: /home/pedro/reverse 
>  [Thread debugging using libthread_db enabled]
>  Using host libthread_db library "/lib/x86_64-linux-
> gnu/libthread_db.so.1".
> 
>  Breakpoint 1, main () at reverse.c:11
>  11        func1 (); func2 ();
>  (gdb) p $pc
>  $1 = (void (*)()) 0x555555555147 <main+8>
>  (gdb) record 
>  (gdb) next
>  12      }
>  (gdb) reverse-next
>  11        func1 (); func2 ();
>  (gdb) p $pc
>  $2 = (void (*)()) 0x555555555151 <main+18>
>  (gdb) 
> 
> 
> This:
> 
>  next -> reverse-next -> next -> reverse-next
> 
> ... should leave you at the same instruction.  But it doesn't in this
> example!
> 

-------------------------------------------------------
Patch for the test case based on Pedro's test

New pedro test

---
 gdb/testsuite/gdb.reverse/pedro_test.c   |  18 ++++
 gdb/testsuite/gdb.reverse/pedro_test.exp | 118 +++++++++++++++++++++++
 2 files changed, 136 insertions(+)
 create mode 100644 gdb/testsuite/gdb.reverse/pedro_test.c
 create mode 100644 gdb/testsuite/gdb.reverse/pedro_test.exp

diff --git a/gdb/testsuite/gdb.reverse/pedro_test.c b/gdb/testsuite/gdb.reverse/pedro_test.c
new file mode 100644
index 00000000000..e3183356ff6
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/pedro_test.c
@@ -0,0 +1,18 @@
+void
+func1 ()
+{
+}
+
+void
+func2 ()
+{
+}
+
+int main ()
+{
+  int a, b;
+  a = 1;
+  b = 2;
+  func1 (); func2 ();
+  a = a + b;     // START REVERSE TEST
+}
diff --git a/gdb/testsuite/gdb.reverse/pedro_test.exp b/gdb/testsuite/gdb.reverse/pedro_test.exp
new file mode 100644
index 00000000000..d315e993d5f
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/pedro_test.exp
@@ -0,0 +1,118 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# This test checks to make sure there is no regression failures for
+# the reverse-next command when stepping back over two functions in
+# the same line.
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+# Test 1, reverse-next command
+# Set breakpoint at the line after the function calls.
+set bp_start_reverse_test [gdb_get_line_number "START REVERSE TEST" $srcfile]
+gdb_breakpoint $srcfile:$bp_start_reverse_test temporary
+
+# Continue to break point for reverse-next test.
+# Command definition:  reverse-next [count]
+#   Run backward to the beginning of the previous line executed in the current
+#   (innermost) stack frame. If the line contains function calls, they will be
+#   “un-executed” without stopping. Starting from the first line of a function,
+#   reverse-next will take you back to the caller of that function, before the
+#   function was called, just as the normal next command would take you from
+#   the last line of a function back to its return to its caller 2 .
+
+gdb_continue_to_breakpoint \
+    "stopped at command reverse-next test start location" \
+    ".*$srcfile:$bp_start_reverse_test\r\n.*"
+
+# The reverse-next should step all the way back to the begining of the line,
+# i.e. at the begining of the func1 call.
+gdb_test "reverse-next" ".*func1 \\(\\); func2 \\(\\);.*" \
+    "reverse-next to line with two functions"
+
+# A reverse-step should step back and stop at the begining
+# of the previous line b = 2, i.e. not in func1 ().
+gdb_test "reverse-step" ".*b = 2;.*" \
+    "reverse-step to previous line b = 2"
+
+
+# Setup for test 2
+# Go back to the start of the function
+gdb_test "reverse-continue" "a = 1;" "At start of main, setup for test 2"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+# Test 2, reverse-step command
+# Set breakpoint at the line after the function calls.
+gdb_breakpoint $srcfile:$bp_start_reverse_test temporary
+
+#  Continue to the start of the reverse-step test.
+#  Command definition:  reverse-step [count]
+#    Run the program backward until control reaches the start of a
+#    different source line; then stop it, and return control to gdb.
+#    Like the step command, reverse-step will only stop at the beginning of a
+#    source line. It “un-executes” the previously executed source line. If the 
+#    previous source line included calls to debuggable functions, reverse-step
+#    will step (backward) into the called function, stopping at the beginning
+#    of the last statement in the called function (typically a return
+#    statement).  Also, as with the step command, if non-debuggable functions
+#    are called, reverse-step will run thru them backward without stopping.
+
+gdb_continue_to_breakpoint \
+    "stopped at command reverse-step test start location" \
+    ".*$srcfile:$bp_start_reverse_test\r\n.*"
+
+# The first reverse step should take us call of func2 ().
+gdb_test "reverse-step" ".*}.*" \
+    "reverse-step into func2 "
+
+# The second reverse step should take us call of func2 ().
+gdb_test "reverse-step" ".*func1 \\(\\); func2 \\(\\);.*" \
+    "reverse-step to line func1(); func2(), at call for func2 "
+
+# The third reverse step should take us into func1 ().
+gdb_test "reverse-step" ".*}.*" \
+    "reverse-step into func1 "
+
+# The fourth reverse step should take us call of func1 ().
+gdb_test "reverse-step" ".*func1 \\(\\); func2 \\(\\);.*" \
+    "reverse-step to line func1(); func2(), at call for func1 "
+
+# The fifth reverse step should take us to b = 2 ().
+gdb_test "reverse-step" ".*b = 2;.*" \
+    "reverse-step to line b = 2 "
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: Reverse-next bug test case
  2023-01-31  0:17                                                                 ` Reverse-next bug test case Carl Love
@ 2023-02-01 14:37                                                                   ` Pedro Alves
  2023-02-01 18:40                                                                     ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Pedro Alves @ 2023-02-01 14:37 UTC (permalink / raw)
  To: Carl Love, Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches

On 2023-01-31 12:17 a.m., Carl Love wrote:
> +# The second reverse step should take us call of func2 ().
> +gdb_test "reverse-step" ".*func1 \\(\\); func2 \\(\\);.*" \
> +    "reverse-step to line func1(); func2(), at call for func2 "
> +

From <https://sourceware.org/gdb/current/onlinedocs/gdb.html/Reverse-Execution.html> :

 "Like the step command, reverse-step will only stop at the beginning of a source line. "

So when reverse-stepping is ongoing and execution internally stops at the call to func2, gdb
should realize it is not really at the beginning of a source line, and continue stepping.
That should take it inside func1, and stop there (at the beginning of a line), as it will have
reached a different line.

I would start by looking at making either of these pass:

 $ make check TESTS="*/pedro_test.exp" RUNTESTFLAGS="CC_FOR_TARGET='gcc -gno-column-info'"

 $ make check TESTS="*/pedro_test.exp" RUNTESTFLAGS="CC_FOR_TARGET=clang"

... as the misbehavior happens due to GDB misinterpreting multiple lines entries for the
same line when column info is emitted by current gcc.  If you disable the column info, then gdb
should not stop in the middle of a line, and that's how gdb should always behave.  (Making use
of column info is certainly interesting to support statement stepping, but that's orthogonal.)

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: Reverse-next bug test case
  2023-02-01 14:37                                                                   ` Pedro Alves
@ 2023-02-01 18:40                                                                     ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-02-01 18:40 UTC (permalink / raw)
  To: Pedro Alves, Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches; +Cc: cel

Pedro:

On Wed, 2023-02-01 at 14:37 +0000, Pedro Alves wrote:
> On 2023-01-31 12:17 a.m., Carl Love wrote:
> > +# The second reverse step should take us call of func2 ().
> > +gdb_test "reverse-step" ".*func1 \\(\\); func2 \\(\\);.*" \
> > +    "reverse-step to line func1(); func2(), at call for func2 "
> > +
> 
> From <
> https://sourceware.org/gdb/current/onlinedocs/gdb.html/Reverse-Execution.html
>  > :
> 
>  "Like the step command, reverse-step will only stop at the beginning
> of a source line. "
> 
> So when reverse-stepping is ongoing and execution internally stops at
> the call to func2, gdb
> should realize it is not really at the beginning of a source line,
> and continue stepping.
> That should take it inside func1, and stop there (at the beginning of
> a line), as it will have
> reached a different line.
> 
> I would start by looking at making either of these pass:
> 
>  $ make check TESTS="*/pedro_test.exp"
> RUNTESTFLAGS="CC_FOR_TARGET='gcc -gno-column-info'"

OK, when I try the test with no column info, the test on PowerPC fails.
The initial Test 2 expected the second reverse-step to stop at func1();
func2() after stepping into func2 ().  When the Test 2 is updated to
remove the second reverse-step:

...
gdb_continue_to_breakpoint \
    "stopped at command reverse-step test start location" \
    ".*$srcfile:$bp_start_reverse_test\r\n.*"

# The first reverse step should take us call of func2 ().                                       
gdb_test "reverse-step" ".*}.*" \
    "reverse-step into func2 "

# The second reverse step should take us call of func2 ().                                      
## ERROR, should not stop here as that is in the middle of the source line                      
#gdb_test "reverse-step" ".*func1 \\(\\); func2 \\(\\);.*" \                                    
#    "reverse-step to line func1(); func2(), at call for func2 "                                

# The third reverse step should take us into func1 ().                                          
gdb_test "reverse-step" ".*}.*" \
    "reverse-step into func1 "

# The fourth reverse step should take us call of func1 ().                                      
gdb_test "reverse-step" ".*func1 \\(\\); func2 \\(\\);.*" \
    "reverse-step to line func1(); func2(), at call for func1 "

# The fifth reverse step should take us to b = 2 ().                                            
gdb_test "reverse-step" ".*b = 2;.*" \
    "reverse-step to line b = 2 "

Then the test passes when running with no column info.  

OK, that helps.  Thanks.

                   Carl 

> 
>  $ make check TESTS="*/pedro_test.exp"
> RUNTESTFLAGS="CC_FOR_TARGET=clang"
> 
> ... as the misbehavior happens due to GDB misinterpreting multiple
> lines entries for the
> same line when column info is emitted by current gcc.  If you disable
> the column info, then gdb
> should not stop in the middle of a line, and that's how gdb should
> always behave.  (Making use
> of column info is certainly interesting to support statement
> stepping, but that's orthogonal.)


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-01-20 20:04                                                                             ` Carl Love
  2023-01-23 16:42                                                                               ` [PATCH 1/2 version 3] " Carl Love
  2023-01-23 16:42                                                                               ` [PATCH 2/2 " Carl Love
@ 2023-02-10 20:55                                                                               ` Carl Love
  2023-02-17 12:24                                                                                 ` Ulrich Weigand
  2 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-02-10 20:55 UTC (permalink / raw)
  To: Bruno Larsen, PedroAlves, Tom de Vries, Ulrich Weigand, gdb-patches; +Cc: cel

GDB maintainers:

I have reworked the PowerPC patch from the previous series to fix the
behavior of the reverse-finish command on PowerPC.  The patch does not
change the behavior of the reverse-finish command on other
architectures.  The patch simply make the command on PowerPC behave the
same as other architectures, specifically X86.

The issue with the reverse-finish command on PowerPC is the reverse-
finish command doesn't stop at the function call.  The issue is PowerPC
uses two entry points.  PowerPC calls the two entry points the local
entry point (LEP) and the global entry point (GEP).  The LEP is
normally used when calling a function.  The GEP is used when the table
of contents (TOC) needs to be setup before continuing execution at the
LEP.  GDB is not handling the two entry points correctly.  On systems
that don't use two entry points the LEP and the GEP are the same.

A new test case is added to verify the reverse-finish command works
properly.  It checks five cases for the reverse-finish command,
executing the command when stopped on the alternate entry point, the
normal entry point, between the entry points, the body of the function
when it is called via the normal entry point and finally the body of
the function when called via the alternate entry point.

The patch and new test have been run on Power 10, Intel X86 pre
generation 5 and an Intel X86 system with a generation 5 processor. 
The 5th generation X86 system is needed to run the btrace/tailcall.exp
and btrace/tailcall-only.exp tests that were an issue with the previous
patch series which was withdrawn from consideration.

Please let me know if the patch is acceptable.  Thanks. 

                Carl 

----------------------------------------------------------
PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp

PPC64 multiple entry points.  When executing in reverse the function
finish_backward sets the break point at the alternate entry point, known
as the global entry point (GEP) in PowerPC.  However if the forward
execution enters via the normal entry point, known as the local entry
point (LEP) on PowerPC, reverse execution never sees the break point at the
alternate entry point of the function.  Reverse execution continues until
the next break point is encountered thus stopping at the wrong place.

This patch adds a new address to struct execution_control_state to hold the
address of the alternate entry point (GEP).  The finish_backwards function
is updated, if the stopping point is between the normal entry point (LEP)
and the end of the function, a breakpoint is set at the normal entry point.
If the stopping point is between the entry points, a breakpoint is set to
the alternate entry point.

The patch fixes the behavior of the reverse-finish command on PowerPC to
match the behavior of the command on other platforms, specifically X86.
The patch does not change the behavior of the command on X86.

A new test is added to verify the reverse-finish command on PowerPC
correctly stops at the instruction where the function call is made.  A new
test, finish-reverse-next.exp, is added to verify the correct functionality
of the reverse-finish command.  The reverse-finish comand is expected to
stop on the instruction that jumps to the function.  Procedure
proc_step_until from test gdb.reverse/step-indirect-call-thunk.exp is moved
to lib/gdb.exp and renamed repeat_cmd_until.

The patch fixes 11 regression errors in test gdb.reverse/finish-precsave.exp
and 11 regression errors in test gdb.reverse/finish-reverse.exp.

The patch has been tested on Power 10 and X86 processor with no new
regression failures.
---
 gdb/infcmd.c                                  |  47 ++--
 gdb/infrun.c                                  |  26 ++
 .../gdb.reverse/finish-reverse-next.c         |  91 +++++++
 .../gdb.reverse/finish-reverse-next.exp       | 224 ++++++++++++++++++
 .../gdb.reverse/step-indirect-call-thunk.exp  |  33 ---
 gdb/testsuite/lib/gdb.exp                     |  33 +++
 6 files changed, 404 insertions(+), 50 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 77206fcbfe8..a65cc700fc9 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm *sm)
      no way that a function up the stack can have a return address
      that's equal to its entry point.  */
 
-  if (sal.pc != pc)
-    {
-      frame_info_ptr frame = get_selected_frame (nullptr);
-      struct gdbarch *gdbarch = get_frame_arch (frame);
+  CORE_ADDR alt_entry_point = sal.pc;
+  CORE_ADDR entry_point = alt_entry_point;
+  frame_info_ptr frame = get_selected_frame (nullptr);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
 
-      /* Set a step-resume at the function's entry point.  Once that's
-	 hit, we'll do one more step backwards.  */
-      symtab_and_line sr_sal;
-      sr_sal.pc = sal.pc;
-      sr_sal.pspace = get_frame_program_space (frame);
-      insert_step_resume_breakpoint_at_sal (gdbarch,
-					    sr_sal, null_frame_id);
+  if (gdbarch_skip_entrypoint_p (gdbarch))
+    /* Some architectures, like PowerPC use local and global entry points.
+       There is only one Entry Point (GEP = LEP) for other architectures.
+       The GEP is an alternate entry point.  The LEP is the normal entry point.
+       The value of entry_point was initialized to the alternate entry point
+       (GEP).  It will be adjusted to the normal entry point if the function
+       has two entry points.  */
+    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
+
+  if  ((pc >= alt_entry_point) && (pc <= entry_point))
+    /* We are either at one of the entry points or between the entry points.
+       If we are not at the alt_entry point, go back to the alt_entry_point
+       If we at the normal entry point step back one instruction, when we
+       stop we will determine if we entered via the entry point or the
+       alternate entry point.  If we are at the alternate entry point,
+       single step back to the function call.  */
+    tp->control.step_range_start = tp->control.step_range_end = 1;
 
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
-    }
   else
     {
-      /* We're almost there -- we just need to back up by one more
-	 single-step.  */
-      tp->control.step_range_start = tp->control.step_range_end = 1;
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
+      /* We are in the body of the function.  Set a breakpoint to backup to
+	 the normal entry point.  */
+      symtab_and_line sr_sal;
+      sr_sal.pc = entry_point;
+      sr_sal.pspace = get_frame_program_space (frame);
+      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
+					    null_frame_id);
     }
+
+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
 /* finish_forward -- helper function for finish_command.  FRAME is the
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 87ab73c47a4..f0bd13fc219 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1868,6 +1868,7 @@ struct execution_control_state
 
   struct target_waitstatus ws;
   int stop_func_filled_in = 0;
+  CORE_ADDR stop_func_alt_start = 0;
   CORE_ADDR stop_func_start = 0;
   CORE_ADDR stop_func_end = 0;
   const char *stop_func_name = nullptr;
@@ -4680,6 +4681,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 	  ecs->stop_func_start
 	    += gdbarch_deprecated_function_start_offset (gdbarch);
 
+	  /* PowerPC functions have a Local Entry Point (LEP) and a Global
+	     Entry Point (GEP).  There is only one Entry Point (GEP = LEP) for
+	     other architectures.  */
+	  ecs->stop_func_alt_start = ecs->stop_func_start;
+
 	  if (gdbarch_skip_entrypoint_p (gdbarch))
 	    ecs->stop_func_start
 	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
@@ -7269,6 +7275,26 @@ process_event_stop_test (struct execution_control_state *ecs)
 	}
     }
 
+  if (execution_direction == EXEC_REVERSE
+      && ecs->event_thread->control.proceed_to_finish)
+    {
+      /* We are executing the reverse-finish command.  */
+      if (ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
+	  && ecs->event_thread->stop_pc () < ecs->stop_func_start
+	  && ecs->stop_func_alt_start != ecs->stop_func_start)
+	/* If the system supports multiple entry points and we are finishing a
+	   function in reverse.   If we are between the entry points singe-step
+	   back to the alternate entry point.  If we are at the alternate entry
+	   point -- just   need to back up by one more single-step, which
+	   should take us back to the function call.  */
+	{
+	  ecs->event_thread->control.step_range_start
+	    = ecs->event_thread->control.step_range_end = 1;
+	  keep_going (ecs);
+	  return;
+	}
+    }
+
   if (ecs->event_thread->control.step_range_end == 1)
     {
       /* It is stepi or nexti.  We always want to stop stepping after
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
new file mode 100644
index 00000000000..e95ee8e33a6
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -0,0 +1,91 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The reverse finish command should return from a function and stop on
+   the first instruction of the source line where the function call is made.
+   Specifically, the behavior should match doing a reverse next from the
+   first instruction in the function.  GDB should only require one reverse
+   step or next statement to reach the previous source code line.
+
+   This test verifies the fix for gdb bugzilla:
+
+   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+   PowerPC supports two entry points to a function.  The normal entry point
+   is called the local entry point (LEP).  The alternate entry point is called
+   the global entry point (GEP).  The GEP is only used if the table of
+   contents (TOC) value stored in register r2 needs to be setup prior to
+   execution starting at the LEP.  A function call via a function pointer
+   will entry via the GEP.  A normal function call will enter via the LEP.
+
+   This test has been expanded to include tests to verify the reverse-finish
+   command works properly if the function is called via the GEP.  The original
+   test only verified the reverse-finish command for a normal call that used
+   the LEP.  */
+
+int
+function2 (int a, int b)
+{
+  int ret = 0;
+  ret = ret + a + b;
+  return ret;
+}
+
+int
+function1 (int a, int b)   // FUNCTION1
+{
+  int ret = 0;
+  int (*funp) (int, int) = &function2;
+  /* The assembly code for this function when compiled for PowerPC is as
+     follows:
+
+     0000000010000758 <function1>:
+     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
+     1000075c:	00 7f 42 38 	addi    r2,r2,32512
+     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
+     10000764:	10 00 01 f8 	std     r0,16(r1)
+     ....
+
+     When the function is called on PowerPC with function1 (a, b) the call
+     enters at the Local Entry Point (LEP).  When the function is called via
+     a function pointer, the Global Entry Point (GEP) for function1 is used.
+     The GEP sets up register 2 before reaching the LEP.
+  */
+  ret = funp (a + 1, b + 2);
+  return ret;
+}
+
+int
+main(int argc, char* argv[])
+{
+  int a, b;
+  int (*funp) (int, int) = &function1;
+
+  /* Call function via Local Entry Point (LEP).  */
+
+  a = 1;
+  b = 5;
+
+  function1 (a, b);   // CALL VIA LEP
+
+  /* Call function via Global Entry Point (GEP).  */
+  a = 10;
+  b = 50;
+
+  funp (a, b);        // CALL VIA GEP
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
new file mode 100644
index 00000000000..6e08530c970
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -0,0 +1,224 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+# PowerPC supports two entry points to a function.  The normal entry point
+# is called the local entry point (LEP).  The alternate entry point is called
+# the global entry point (GEP).  A function call via a function pointer
+# will entry via the GEP.  A normal function call will enter via the LEP.
+#
+# This test has been expanded to include tests to verify the reverse-finish
+# command works properly if the function is called via the GEP.  The original
+# test only verified the reverse-finish command for a normal call that used
+# the LEP.
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+### TEST 1: reverse finish from the entry point instruction (LEP) in
+### function1 when called using the normal entry point (LEP).
+
+# Set breakpoint at call to function1 in main.
+set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function1
+repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from LEP "
+gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
+    "reverse next 1 LEP entry point function call from LEP"
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call from LEP"
+
+
+gdb_test "reverse-continue" ".*" "setup for test 2"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+### TEST 2: reverse finish from the body of function1.
+
+# Set breakpoint at call to function1 in main.
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+# do a step instruction to get to the body of the function
+gdb_test "step" ".*int ret = 0;.*" "step test 1"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from function body"
+gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse next 1 LEP from function body"
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse next 2 at b = 5, from function body"
+
+gdb_test "reverse-continue" ".*" "setup for test 3"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test2"
+gdb_test_no_output "record" "turn on process record for test3"
+
+
+### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP"
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP entry point function call from GEP"
+gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, call from GEP"
+
+gdb_test "reverse-continue" ".*" "setup for test 4"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test3"
+gdb_test_no_output "record" "turn on process record for test4"
+
+### TEST 4: reverse finish from between the GEP and LEP in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp again" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call again"
+
+# do one more stepi so we are between the GEP and LEP.
+gdb_test "stepi" "{" "stepi to between GEP and LEP"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP again"
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP entry point function call from GEP again"
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next 2 at b = 50, call from GEP again"
+
+gdb_test "reverse-continue" ".*" "setup for test 5"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test4"
+gdb_test_no_output "record" "turn on process record for test5"
+
+
+### TEST 5: reverse finish from the body of function 1 when calling using the
+### alternate entrypoint (GEP).
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of funp call" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# Step into body of funp, called via GEP.
+gdb_test "step" ".*int ret = 0;.*" "step test 2"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "reverse-finish function1 GEP call, from function body  "
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP call from function body"
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next 2 at b = 50 from function body"
diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index 94292d5eb9b..dc5cf097511 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -36,39 +36,6 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
-proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
-}
-
 gdb_test_no_output "record"
 gdb_test "next" ".*" "record trace"
 
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index faa0ac05a9a..c156982a674 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9295,6 +9295,39 @@ proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
     }
 }
 
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND is a stepping command
+#  CURRENT is a string matching the current location
+#  TARGET  is a string matching the target location
+#  TEST    is the test name
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of 100 steps.
+#
+# TEST passes if the resulting location matches TARGET and fails
+# otherwise.
+#
+proc repeat_cmd_until { command current target test } {
+    global gdb_prompt
+
+    set count 0
+    gdb_test_multiple "$command" "$test" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < 100 } {
+		send_gdb "$command\n"
+		exp_continue
+	    } else {
+		fail "$test"
+	    }
+	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+}
+
 # Check if the compiler emits epilogue information associated
 # with the closing brace or with the last statement line.
 #
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-10 20:55                                                                               ` [PATCH ] PowerPC: " Carl Love
@ 2023-02-17 12:24                                                                                 ` Ulrich Weigand
  2023-02-20 16:34                                                                                   ` Carl Love
  2023-02-20 20:24                                                                                   ` Carl Love
  0 siblings, 2 replies; 105+ messages in thread
From: Ulrich Weigand @ 2023-02-17 12:24 UTC (permalink / raw)
  To: gdb-patches, Bruno Larsen, tdevries, cel, pedro

Carl Love <cel@us.ibm.com> wrote:

This looks generally OK to me, except for two minor issues
in the code base, and one problem in the test suite:


>diff --git a/gdb/infcmd.c b/gdb/infcmd.c
>index 77206fcbfe8..a65cc700fc9 100644
>--- a/gdb/infcmd.c
>+++ b/gdb/infcmd.c
>@@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm *sm)
>      no way that a function up the stack can have a return address
>      that's equal to its entry point.  */
> 
>-  if (sal.pc != pc)
>-    {
>-      frame_info_ptr frame = get_selected_frame (nullptr);
>-      struct gdbarch *gdbarch = get_frame_arch (frame);
>+  CORE_ADDR alt_entry_point = sal.pc;
>+  CORE_ADDR entry_point = alt_entry_point;
>+  frame_info_ptr frame = get_selected_frame (nullptr);
>+  struct gdbarch *gdbarch = get_frame_arch (frame);
> 
>-      /* Set a step-resume at the function's entry point.  Once that's
>-	 hit, we'll do one more step backwards.  */
>-      symtab_and_line sr_sal;
>-      sr_sal.pc = sal.pc;
>-      sr_sal.pspace = get_frame_program_space (frame);
>-      insert_step_resume_breakpoint_at_sal (gdbarch,
>-					    sr_sal, null_frame_id);
>+  if (gdbarch_skip_entrypoint_p (gdbarch))
>+    /* Some architectures, like PowerPC use local and global entry points.
>+       There is only one Entry Point (GEP = LEP) for other architectures.
>+       The GEP is an alternate entry point.  The LEP is the normal entry point.
>+       The value of entry_point was initialized to the alternate entry point
>+       (GEP).  It will be adjusted to the normal entry point if the function
>+       has two entry points.  */
>+    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
>+
>+  if  ((pc >= alt_entry_point) && (pc <= entry_point))
>+    /* We are either at one of the entry points or between the entry points.
>+       If we are not at the alt_entry point, go back to the alt_entry_point
>+       If we at the normal entry point step back one instruction, when we
>+       stop we will determine if we entered via the entry point or the
>+       alternate entry point.  If we are at the alternate entry point,
>+       single step back to the function call.  */
>+    tp->control.step_range_start = tp->control.step_range_end = 1;
> 
>-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>-    }
>   else
>     {
>-      /* We're almost there -- we just need to back up by one more
>-	 single-step.  */
>-      tp->control.step_range_start = tp->control.step_range_end = 1;
>-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>+      /* We are in the body of the function.  Set a breakpoint to backup to
>+	 the normal entry point.  */
>+      symtab_and_line sr_sal;
>+      sr_sal.pc = entry_point;
>+      sr_sal.pspace = get_frame_program_space (frame);
>+      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
>+					    null_frame_id);
>     }
>+
>+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> }

This change looks much larger than it actually is, because you've
swapped the order of the if vs. else blocks (the orignal code sets
the breakpoint in the if path and the single-step range in the
else path, while you've swapped this).  Can you swap this back to
shorten the diff?

>+  if (execution_direction == EXEC_REVERSE
>+      && ecs->event_thread->control.proceed_to_finish)
>+    {
>+      /* We are executing the reverse-finish command.  */
>+      if (ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
>+	  && ecs->event_thread->stop_pc () < ecs->stop_func_start
>+	  && ecs->stop_func_alt_start != ecs->stop_func_start)

This third condition seems redundant: if stop_pc is >= func_alt_start
*and* < func_start, then func_alt_start cannot be equal func_start.


>diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
>index 94292d5eb9b..dc5cf097511 100644
>--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
>+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
>@@ -36,39 +36,6 @@ if { ![runto_main] } {
>     return -1
> }
> 
>-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
>-#
>-#  COMMAND is a stepping command
>-#  CURRENT is a string matching the current location
>-#  TARGET  is a string matching the target location
>-#  TEST    is the test name
>-#
>-# The function issues repeated COMMANDs as long as the location matches
>-# CURRENT up to a maximum of 100 steps.
>-#
>-# TEST passes if the resulting location matches TARGET and fails
>-# otherwise.
>-#
>-proc step_until { command current target test } {
>-    global gdb_prompt
>-
>-    set count 0
>-    gdb_test_multiple "$command" "$test" {
>-        -re "$current.*$gdb_prompt $" {
>-            incr count
>-            if { $count < 100 } {
>-                send_gdb "$command\n"
>-                exp_continue
>-            } else {
>-                fail "$test"
>-            }
>-        }
>-        -re "$target.*$gdb_prompt $" {
>-            pass "$test"
>-        }
>-    }
>-}
>-
> gdb_test_no_output "record"
> gdb_test "next" ".*" "record trace"


How is it OK to just remove this procedure?  This is still used
in the rest of the step-indirect-call-thunk.exp test case ...

I get why you may want to reduce duplication, but then you'd
have to update current users of "step_until" as well.

Also, talking about duplication, should the (already separate)
gdb_step_until command in lib/gdb.exp now just be a variant
of the new repeat_cmd_until ?


Bye,
Ulrich


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-17 12:24                                                                                 ` Ulrich Weigand
@ 2023-02-20 16:34                                                                                   ` Carl Love
  2023-02-20 16:48                                                                                     ` Bruno Larsen
  2023-02-20 20:24                                                                                   ` Carl Love
  1 sibling, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-02-20 16:34 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches, Bruno Larsen, tdevries, pedro; +Cc: cel

On Fri, 2023-02-17 at 12:24 +0000, Ulrich Weigand wrote:
> Carl Love <cel@us.ibm.com> wrote:
> 
> This looks generally OK to me, except for two minor issues
> in the code base, and one problem in the test suite:
> 
> 
> > diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> > index 77206fcbfe8..a65cc700fc9 100644
> > --- a/gdb/infcmd.c
> > +++ b/gdb/infcmd.c
> > @@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm
> > *sm)
> >      no way that a function up the stack can have a return address
> >      that's equal to its entry point.  */
> > 
> > -  if (sal.pc != pc)
> > -    {
> > -      frame_info_ptr frame = get_selected_frame (nullptr);
> > -      struct gdbarch *gdbarch = get_frame_arch (frame);
> > +  CORE_ADDR alt_entry_point = sal.pc;
> > +  CORE_ADDR entry_point = alt_entry_point;
> > +  frame_info_ptr frame = get_selected_frame (nullptr);
> > +  struct gdbarch *gdbarch = get_frame_arch (frame);
> > 
> > -      /* Set a step-resume at the function's entry point.  Once
> > that's
> > -	 hit, we'll do one more step backwards.  */
> > -      symtab_and_line sr_sal;
> > -      sr_sal.pc = sal.pc;
> > -      sr_sal.pspace = get_frame_program_space (frame);
> > -      insert_step_resume_breakpoint_at_sal (gdbarch,
> > -					    sr_sal, null_frame_id);
> > +  if (gdbarch_skip_entrypoint_p (gdbarch))
> > +    /* Some architectures, like PowerPC use local and global entry
> > points.
> > +       There is only one Entry Point (GEP = LEP) for other
> > architectures.
> > +       The GEP is an alternate entry point.  The LEP is the normal
> > entry point.
> > +       The value of entry_point was initialized to the alternate
> > entry point
> > +       (GEP).  It will be adjusted to the normal entry point if
> > the function
> > +       has two entry points.  */
> > +    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
> > +
> > +  if  ((pc >= alt_entry_point) && (pc <= entry_point))
> > +    /* We are either at one of the entry points or between the
> > entry points.
> > +       If we are not at the alt_entry point, go back to the
> > alt_entry_point
> > +       If we at the normal entry point step back one instruction,
> > when we
> > +       stop we will determine if we entered via the entry point or
> > the
> > +       alternate entry point.  If we are at the alternate entry
> > point,
> > +       single step back to the function call.  */
> > +    tp->control.step_range_start = tp->control.step_range_end = 1;
> > 
> > -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> > -    }
> >   else
> >     {
> > -      /* We're almost there -- we just need to back up by one more
> > -	 single-step.  */
> > -      tp->control.step_range_start = tp->control.step_range_end =
> > 1;
> > -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> > +      /* We are in the body of the function.  Set a breakpoint to
> > backup to
> > +	 the normal entry point.  */
> > +      symtab_and_line sr_sal;
> > +      sr_sal.pc = entry_point;
> > +      sr_sal.pspace = get_frame_program_space (frame);
> > +      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
> > +					    null_frame_id);
> >     }
> > +
> > +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> > }
> 
> This change looks much larger than it actually is, because you've
> swapped the order of the if vs. else blocks (the orignal code sets
> the breakpoint in the if path and the single-step range in the
> else path, while you've swapped this).  Can you swap this back to
> shorten the diff?

OK, swapped them.

> 
> > +  if (execution_direction == EXEC_REVERSE
> > +      && ecs->event_thread->control.proceed_to_finish)
> > +    {
> > +      /* We are executing the reverse-finish command.  */
> > +      if (ecs->event_thread->stop_pc () >= ecs-
> > >stop_func_alt_start
> > +	  && ecs->event_thread->stop_pc () < ecs->stop_func_start
> > +	  && ecs->stop_func_alt_start != ecs->stop_func_start)
> 
> This third condition seems redundant: if stop_pc is >= func_alt_start
> *and* < func_start, then func_alt_start cannot be equal func_start.

Yes, on Powerpc the third condition is redundant.  However, on other
platforms, specifically X86, the third condition is always false which
ensures the if statement is false.  This is important on the tests
gdb.btrace/tailcall-only.exp and gdb.btrace/tailcall.exp which only run
on X86.  The tests call the up command which will satisfy conditions 1
and 2 and thus do an "extra" step command resulting in a test failure. 
The third condition ensures that we never execute an additional
reverse-step unless the platform supports multiple entry points and we
are at the alternate entry point.  I can see where this is not obvious
at first glance.  I added a comment to the if statement explaining the
need for the apparent redundancy.

Also, the if statement is nested inside of the if reverse if statement.
I combined the two if statements into a single if statement.

> > diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp 
> > b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> > index 94292d5eb9b..dc5cf097511 100644
> > --- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> > +++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> > @@ -36,39 +36,6 @@ if { ![runto_main] } {
> >     return -1
> > }
> > 
> > -# Do repeated stepping COMMANDs in order to reach TARGET from
> > CURRENT
> > -#
> > -#  COMMAND is a stepping command
> > -#  CURRENT is a string matching the current location
> > -#  TARGET  is a string matching the target location
> > -#  TEST    is the test name
> > -#
> > -# The function issues repeated COMMANDs as long as the location
> > matches
> > -# CURRENT up to a maximum of 100 steps.
> > -#
> > -# TEST passes if the resulting location matches TARGET and fails
> > -# otherwise.
> > -#
> > -proc step_until { command current target test } {
> > -    global gdb_prompt
> > -
> > -    set count 0
> > -    gdb_test_multiple "$command" "$test" {
> > -        -re "$current.*$gdb_prompt $" {
> > -            incr count
> > -            if { $count < 100 } {
> > -                send_gdb "$command\n"
> > -                exp_continue
> > -            } else {
> > -                fail "$test"
> > -            }
> > -        }
> > -        -re "$target.*$gdb_prompt $" {
> > -            pass "$test"
> > -        }
> > -    }
> > -}
> > -
> > gdb_test_no_output "record"
> > gdb_test "next" ".*" "record trace"
> 
> How is it OK to just remove this procedure?  This is still used
> in the rest of the step-indirect-call-thunk.exp test case ...

Yes, looks like my fix up of the call to step_until in step-indirect-
call-thunk.exp got lost somewhere along the line.  I remember making
the change.

I went back to see why the regression testing didn't catch the error. 
On PowerPC, the test doesn't run as the compile options "-mindirect-
branch=thunk" and "-mfunction-return=thunk" are not supported on
PowerPC, so the test fails anyways.  It looks like the test didn't run
on my X86 either due to the regression test failing before getting to
the gdb tests.  Looks like I need to run the regression test in
subdirectory gdb to make sure all of the gdb tests get run.  

I have run the updated patch, on X86, manually and in the regression
test to make sure there are no regressions with this test.  I checked
out the base and regression runs on X86 to make sure the regression
tests are all be run.

> 
> I get why you may want to reduce duplication, but then you'd
> have to update current users of "step_until" as well.

Yes, those updates got lost rebasing the patch at some point.  Fixed.

> 
> Also, talking about duplication, should the (already separate)
> gdb_step_until command in lib/gdb.exp now just be a variant
> of the new repeat_cmd_until ?

OK, I extended the new repeat_cmd_until proceedure to take the
additional input max_steps.  I created a new version of gdb_step_until
that calls repeat_cmd_until.  I added an optional argument, current, to
gdb_step_until proceedure for the current line.  By default, current is
set to "\}" which is needed by the call to repeat_cmd_until proceedure.
The new gdb_step_until proceedure works in the existing regression
tests without changing the gdb_step_until call in the existing tests. 

Thanks for reviewing the patch.  I will post an updated patch shortly.

                         Carl 



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-20 16:34                                                                                   ` Carl Love
@ 2023-02-20 16:48                                                                                     ` Bruno Larsen
  0 siblings, 0 replies; 105+ messages in thread
From: Bruno Larsen @ 2023-02-20 16:48 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, gdb-patches, tdevries, pedro

On 20/02/2023 17:34, Carl Love wrote:
>>> +  if (execution_direction == EXEC_REVERSE
>>> +      && ecs->event_thread->control.proceed_to_finish)
>>> +    {
>>> +      /* We are executing the reverse-finish command.  */
>>> +      if (ecs->event_thread->stop_pc () >= ecs-
>>>> stop_func_alt_start
>>> +	  && ecs->event_thread->stop_pc () < ecs->stop_func_start
>>> +	  && ecs->stop_func_alt_start != ecs->stop_func_start)
>> This third condition seems redundant: if stop_pc is >= func_alt_start
>> *and*  < func_start, then func_alt_start cannot be equal func_start.
> Yes, on Powerpc the third condition is redundant.  However, on other
> platforms, specifically X86, the third condition is always false which
> ensures the if statement is false.  This is important on the tests
> gdb.btrace/tailcall-only.exp and gdb.btrace/tailcall.exp which only run
> on X86.  The tests call the up command which will satisfy conditions 1
> and 2 and thus do an "extra" step command resulting in a test failure.
> The third condition ensures that we never execute an additional
> reverse-step unless the platform supports multiple entry points and we
> are at the alternate entry point.  I can see where this is not obvious
> at first glance.  I added a comment to the if statement explaining the
> need for the apparent redundancy.
But it is always redundant, even on x86. If the stop_func_start is A, 
there is no way the stop_pc can be simultaneously larger or equal to A, 
and strictly smaller than A. The only way the third condition would make 
a difference is if the second condition was `ecs->event_thread->stop_pc 
() <= ecs->stop_func_start`

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-17 12:24                                                                                 ` Ulrich Weigand
  2023-02-20 16:34                                                                                   ` Carl Love
@ 2023-02-20 20:24                                                                                   ` Carl Love
  2023-02-27 16:09                                                                                     ` [PING] " Carl Love
                                                                                                       ` (4 more replies)
  1 sibling, 5 replies; 105+ messages in thread
From: Carl Love @ 2023-02-20 20:24 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches, Bruno Larsen, tdevries, pedro; +Cc: cel

Ulrich, Bruno, GDB maintainers:

Per the comments from Ulrich, I have updated the patch to address the
comments about the source code and the testcase. I updated the new
library procedure so it can be called from gdb_step_until.  So
gdb_step_until is now just a variant of the new repeat_cmd_until
proceedure.

The redundant if test has been removed.  It was added to fix a
regression testing failure I saw on the gdb.btrace/tailcall.exp on X86.
I went back and redid the testing, rebuilding everything from scratch. 
I am not able to reproduce the test failure without the redundant
check.  Not sure why I initially saw the regression failure at this
point?  Perhaps I hadn't re-enabled the
/proc/sys/kernel/perf_event_paranoid value?  It must be 2 or lower for
the test to run.  Otherwise the test fails.  Anyway, the regression
tests on X86 run without the redundant check are passing on my laptop. 

I resolved the issues with the testing on X86 to make sure it isn't
missing failures when testing gdb.reverse/step-indirect-call-thunk.exp. 
As mentioned in the previous email, the test does not run on PowerPC
since the gcc command line options "-mindirect-branch=thunk" and "-
mfunction-return=thunk" are not supported on PowerPC.  I disabled the
test on PowerPC in the updated patch.

Retested on X86 generation 5 and PowerPC with no regressions found. 

Hopefully this version of the patch is acceptable. 

                          Carl 

  -----------------------------------------------------

PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp

PPC64 multiple entry points.  When executing in reverse the function
finish_backward sets the break point at the alternate entry point, known
as the global entry point (GEP) in PowerPC.  However if the forward
execution enters via the normal entry point, known as the local entry
point (LEP) on PowerPC, reverse execution never sees the break point at the
alternate entry point of the function.  Reverse execution continues until
the next break point is encountered thus stopping at the wrong place.

This patch adds a new address to struct execution_control_state to hold the
address of the alternate entry point (GEP).  The finish_backwards function
is updated, if the stopping point is between the normal entry point (LEP)
and the end of the function, a breakpoint is set at the normal entry point.
If the stopping point is between the entry points, a breakpoint is set to
the alternate entry point.

The patch fixes the behavior of the reverse-finish command on PowerPC to
match the behavior of the command on other platforms, specifically X86.
The patch does not change the behavior of the command on X86.

A new test is added to verify the reverse-finish command on PowerPC
correctly stops at the instruction where the function call is made.  A new
test, finish-reverse-next.exp, is added to verify the correct functionality
of the reverse-finish command.  The reverse-finish comand is expected to
stop on the instruction that jumps to the function.  Procedure
proc_step_until from test gdb.reverse/step-indirect-call-thunk.exp is moved
to lib/gdb.exp and renamed repeat_cmd_until.

The patch fixes 11 regression errors in test gdb.reverse/finish-precsave.exp
and 11 regression errors in test gdb.reverse/finish-reverse.exp.

The patch has been tested on Power 10 and X86 processor with no new
regression failures.
---
 gdb/infcmd.c                                  |  47 ++--
 gdb/infrun.c                                  |  24 ++
 .../gdb.reverse/finish-reverse-next.c         |  91 +++++++
 .../gdb.reverse/finish-reverse-next.exp       | 224 ++++++++++++++++++
 .../gdb.reverse/step-indirect-call-thunk.exp  |  55 ++---
 gdb/testsuite/lib/gdb.exp                     |  49 +++-
 6 files changed, 421 insertions(+), 69 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 77206fcbfe8..0fa5719d38b 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm *sm)
      no way that a function up the stack can have a return address
      that's equal to its entry point.  */
 
-  if (sal.pc != pc)
-    {
-      frame_info_ptr frame = get_selected_frame (nullptr);
-      struct gdbarch *gdbarch = get_frame_arch (frame);
+  CORE_ADDR alt_entry_point = sal.pc;
+  CORE_ADDR entry_point = alt_entry_point;
+  frame_info_ptr frame = get_selected_frame (nullptr);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  if (gdbarch_skip_entrypoint_p (gdbarch))
+    /* Some architectures, like PowerPC use local and global entry points.
+       There is only one Entry Point (GEP = LEP) for other architectures.
+       The GEP is an alternate entry point.  The LEP is the normal entry point.
+       The value of entry_point was initialized to the alternate entry point
+       (GEP).  It will be adjusted to the normal entry point if the function
+       has two entry points.  */
+    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
 
-      /* Set a step-resume at the function's entry point.  Once that's
-	 hit, we'll do one more step backwards.  */
+  if  ((pc < alt_entry_point) || (pc > entry_point))
+    {
+      /* We are in the body of the function.  Set a breakpoint to backup to
+	 the normal entry point.  */
       symtab_and_line sr_sal;
-      sr_sal.pc = sal.pc;
+      sr_sal.pc = entry_point;
       sr_sal.pspace = get_frame_program_space (frame);
-      insert_step_resume_breakpoint_at_sal (gdbarch,
-					    sr_sal, null_frame_id);
-
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
+      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
+					    null_frame_id);
     }
+
   else
-    {
-      /* We're almost there -- we just need to back up by one more
-	 single-step.  */
-      tp->control.step_range_start = tp->control.step_range_end = 1;
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
-    }
+    /* We are either at one of the entry points or between the entry points.
+       If we are not at the alt_entry point, go back to the alt_entry_point
+       If we at the normal entry point step back one instruction, when we
+       stop we will determine if we entered via the entry point or the
+       alternate entry point.  If we are at the alternate entry point,
+       single step back to the function call.  */
+    tp->control.step_range_start = tp->control.step_range_end = 1;
+
+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
 /* finish_forward -- helper function for finish_command.  FRAME is the
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 87ab73c47a4..987dbd16ea4 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1868,6 +1868,7 @@ struct execution_control_state
 
   struct target_waitstatus ws;
   int stop_func_filled_in = 0;
+  CORE_ADDR stop_func_alt_start = 0;
   CORE_ADDR stop_func_start = 0;
   CORE_ADDR stop_func_end = 0;
   const char *stop_func_name = nullptr;
@@ -4680,6 +4681,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 	  ecs->stop_func_start
 	    += gdbarch_deprecated_function_start_offset (gdbarch);
 
+	  /* PowerPC functions have a Local Entry Point (LEP) and a Global
+	     Entry Point (GEP).  There is only one Entry Point (GEP = LEP) for
+	     other architectures.  */
+	  ecs->stop_func_alt_start = ecs->stop_func_start;
+
 	  if (gdbarch_skip_entrypoint_p (gdbarch))
 	    ecs->stop_func_start
 	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
@@ -7269,6 +7275,24 @@ process_event_stop_test (struct execution_control_state *ecs)
 	}
     }
 
+  if (execution_direction == EXEC_REVERSE
+      && ecs->event_thread->control.proceed_to_finish
+      && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
+      && ecs->event_thread->stop_pc () < ecs->stop_func_start)
+    {
+      /* We are executing the reverse-finish command.
+	 If the system supports multiple entry points and we are finishing a
+	 function in reverse.   If we are between the entry points singe-step
+	 back to the alternate entry point.  If we are at the alternate entry
+	 point -- just   need to back up by one more single-step, which
+	 should take us back to the function call.  */
+      ecs->event_thread->control.step_range_start
+	= ecs->event_thread->control.step_range_end = 1;
+      keep_going (ecs);
+      return;
+
+    }
+
   if (ecs->event_thread->control.step_range_end == 1)
     {
       /* It is stepi or nexti.  We always want to stop stepping after
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
new file mode 100644
index 00000000000..e95ee8e33a6
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -0,0 +1,91 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The reverse finish command should return from a function and stop on
+   the first instruction of the source line where the function call is made.
+   Specifically, the behavior should match doing a reverse next from the
+   first instruction in the function.  GDB should only require one reverse
+   step or next statement to reach the previous source code line.
+
+   This test verifies the fix for gdb bugzilla:
+
+   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+   PowerPC supports two entry points to a function.  The normal entry point
+   is called the local entry point (LEP).  The alternate entry point is called
+   the global entry point (GEP).  The GEP is only used if the table of
+   contents (TOC) value stored in register r2 needs to be setup prior to
+   execution starting at the LEP.  A function call via a function pointer
+   will entry via the GEP.  A normal function call will enter via the LEP.
+
+   This test has been expanded to include tests to verify the reverse-finish
+   command works properly if the function is called via the GEP.  The original
+   test only verified the reverse-finish command for a normal call that used
+   the LEP.  */
+
+int
+function2 (int a, int b)
+{
+  int ret = 0;
+  ret = ret + a + b;
+  return ret;
+}
+
+int
+function1 (int a, int b)   // FUNCTION1
+{
+  int ret = 0;
+  int (*funp) (int, int) = &function2;
+  /* The assembly code for this function when compiled for PowerPC is as
+     follows:
+
+     0000000010000758 <function1>:
+     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
+     1000075c:	00 7f 42 38 	addi    r2,r2,32512
+     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
+     10000764:	10 00 01 f8 	std     r0,16(r1)
+     ....
+
+     When the function is called on PowerPC with function1 (a, b) the call
+     enters at the Local Entry Point (LEP).  When the function is called via
+     a function pointer, the Global Entry Point (GEP) for function1 is used.
+     The GEP sets up register 2 before reaching the LEP.
+  */
+  ret = funp (a + 1, b + 2);
+  return ret;
+}
+
+int
+main(int argc, char* argv[])
+{
+  int a, b;
+  int (*funp) (int, int) = &function1;
+
+  /* Call function via Local Entry Point (LEP).  */
+
+  a = 1;
+  b = 5;
+
+  function1 (a, b);   // CALL VIA LEP
+
+  /* Call function via Global Entry Point (GEP).  */
+  a = 10;
+  b = 50;
+
+  funp (a, b);        // CALL VIA GEP
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
new file mode 100644
index 00000000000..1f53b649a7d
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -0,0 +1,224 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+# PowerPC supports two entry points to a function.  The normal entry point
+# is called the local entry point (LEP).  The alternate entry point is called
+# the global entry point (GEP).  A function call via a function pointer
+# will entry via the GEP.  A normal function call will enter via the LEP.
+#
+# This test has been expanded to include tests to verify the reverse-finish
+# command works properly if the function is called via the GEP.  The original
+# test only verified the reverse-finish command for a normal call that used
+# the LEP.
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+### TEST 1: reverse finish from the entry point instruction (LEP) in
+### function1 when called using the normal entry point (LEP).
+
+# Set breakpoint at call to function1 in main.
+set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function1
+repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call" "100"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from LEP "
+gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
+    "reverse next 1 LEP entry point function call from LEP"
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call from LEP"
+
+
+gdb_test "reverse-continue" ".*" "setup for test 2"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+### TEST 2: reverse finish from the body of function1.
+
+# Set breakpoint at call to function1 in main.
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+# do a step instruction to get to the body of the function
+gdb_test "step" ".*int ret = 0;.*" "step test 1"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from function body"
+gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse next 1 LEP from function body"
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse next 2 at b = 5, from function body"
+
+gdb_test "reverse-continue" ".*" "setup for test 3"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test2"
+gdb_test_no_output "record" "turn on process record for test3"
+
+
+### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP"
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP entry point function call from GEP"
+gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, call from GEP"
+
+gdb_test "reverse-continue" ".*" "setup for test 4"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test3"
+gdb_test_no_output "record" "turn on process record for test4"
+
+### TEST 4: reverse finish from between the GEP and LEP in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp again" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call again"
+
+# do one more stepi so we are between the GEP and LEP.
+gdb_test "stepi" "{" "stepi to between GEP and LEP"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP again"
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP entry point function call from GEP again"
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next 2 at b = 50, call from GEP again"
+
+gdb_test "reverse-continue" ".*" "setup for test 5"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test4"
+gdb_test_no_output "record" "turn on process record for test5"
+
+
+### TEST 5: reverse finish from the body of function 1 when calling using the
+### alternate entrypoint (GEP).
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of funp call" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# Step into body of funp, called via GEP.
+gdb_test "step" ".*int ret = 0;.*" "step test 2"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "reverse-finish function1 GEP call, from function body  "
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP call from function body"
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next 2 at b = 50 from function body"
diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index 94292d5eb9b..61fb4974b8e 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -17,6 +17,12 @@ require supports_reverse
 
 standard_testfile
 
+if { [istarget "powerpc*-*-linux*"] } {
+    # GCC for PowerPC on linux does not support the -mindirect-branch and
+    # -mfunction-return command line options.
+    return 0
+}
+
 set cflags {}
 lappend cflags debug
 lappend cflags additional_flags=-mindirect-branch=thunk
@@ -36,39 +42,6 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
-proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
-}
-
 gdb_test_no_output "record"
 gdb_test "next" ".*" "record trace"
 
@@ -88,20 +61,20 @@ gdb_test "reverse-next" "apply\.2.*" \
     "reverse-step through thunks and over inc"
 
 # We can use instruction stepping to step into thunks.
-step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
-step_until "stepi" "indirect_thunk" "inc" \
+repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
+repeat_cmd_until "stepi" "indirect_thunk" "inc" \
     "stepi out of call thunk into inc"
 set alphanum_re "\[a-zA-Z0-9\]"
 set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
-step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
-step_until "stepi" "return_thunk" "apply" \
+repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
+repeat_cmd_until "stepi" "return_thunk" "apply" \
     "stepi out of return thunk back into apply"
 
-step_until "reverse-stepi" "apply" "return_thunk" \
+repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
     "reverse-stepi into return thunk"
-step_until "reverse-stepi" "return_thunk" "inc" \
+repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
     "reverse-stepi out of return thunk into inc"
-step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
+repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
     "reverse-stepi into call thunk"
-step_until "reverse-stepi" "indirect_thunk" "apply" \
+repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
     "reverse-stepi out of call thunk into apply"
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index faa0ac05a9a..b10555fe5fb 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9267,31 +9267,58 @@ gdb_caching_proc arm_cc_for_target {
 
 # Step until the pattern REGEXP is found.  Step at most
 # MAX_STEPS times, but stop stepping once REGEXP is found.
-#
+# START matches current location
 # If REGEXP is found then a single pass is emitted, otherwise, after
 # MAX_STEPS steps, a single fail is emitted.
 #
 # TEST_NAME is the name used in the pass/fail calls.
 
-proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
+proc gdb_step_until { regexp {test_name ""} {current ""} \
+			  { max_steps 10 } } {
+    if { $current == "" } {
+	set current "\}"
+    }
+    if { $test_name == "" } {
+	set test_name "stepping until regexp"
+    }
+
+    repeat_cmd_until "step" $current  $regexp  $test_name "10"
+}
+
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND is a stepping command
+#  CURRENT is a string matching the current location
+#  TARGET  is a string matching the target location
+#  TEST    is the test name
+#  MAX_STEPS is number of steps attempted before fail is emitted
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of 100 steps.
+#
+# TEST passes if the resulting location matches TARGET and fails
+# otherwise.
+#
+proc repeat_cmd_until { command current target test_name {max_steps 100} } {
+    global gdb_prompt
     if { $test_name == "" } {
 	set test_name "stepping until regexp"
     }
 
     set count 0
-    gdb_test_multiple "step" "$test_name" {
-	-re "$regexp\r\n$::gdb_prompt $" {
-	    pass $test_name
-	}
-	-re ".*$::gdb_prompt $" {
-	    if {$count < $max_steps} {
-		incr count
-		send_gdb "step\n"
+    gdb_test_multiple "$command" "$test_name" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < $max_steps } {
+		send_gdb "$command\n"
 		exp_continue
 	    } else {
-		fail $test_name
+		fail "$test_name"
 	    }
 	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test_name"
+	}
     }
 }
 
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PING] Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-20 20:24                                                                                   ` Carl Love
@ 2023-02-27 16:09                                                                                     ` Carl Love
  2023-02-28 13:39                                                                                     ` Bruno Larsen
                                                                                                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-02-27 16:09 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches, Bruno Larsen, tdevries, pedro; +Cc: cel

Ulrich, Bruno, Tom, Pedro, GDB maintainers:

Wondering if anyone has had a chance to review and test this patch? 
Would really like to make sure some can test it on an Intel Generation
5 or newer processor to make sure there are no issues with the tests
gdb.btrace/rn-dl-bind.exp and gdb.btrace/tailcall.exp: reverse-next.

Thanks for the time and effort looking at this patch.

               Carl

-------------------------------------------------

On Mon, 2023-02-20 at 12:24 -0800, Carl Love wrote:
> Ulrich, Bruno, GDB maintainers:
> 
> Per the comments from Ulrich, I have updated the patch to address the
> comments about the source code and the testcase. I updated the new
> library procedure so it can be called from gdb_step_until.  So
> gdb_step_until is now just a variant of the new repeat_cmd_until
> proceedure.
> 
> The redundant if test has been removed.  It was added to fix a
> regression testing failure I saw on the gdb.btrace/tailcall.exp on
> X86.
> I went back and redid the testing, rebuilding everything from
> scratch. 
> I am not able to reproduce the test failure without the redundant
> check.  Not sure why I initially saw the regression failure at this
> point?  Perhaps I hadn't re-enabled the
> /proc/sys/kernel/perf_event_paranoid value?  It must be 2 or lower
> for
> the test to run.  Otherwise the test fails.  Anyway, the regression
> tests on X86 run without the redundant check are passing on my
> laptop. 
> 
> I resolved the issues with the testing on X86 to make sure it isn't
> missing failures when testing gdb.reverse/step-indirect-call-
> thunk.exp. 
> As mentioned in the previous email, the test does not run on PowerPC
> since the gcc command line options "-mindirect-branch=thunk" and "-
> mfunction-return=thunk" are not supported on PowerPC.  I disabled the
> test on PowerPC in the updated patch.
> 
> Retested on X86 generation 5 and PowerPC with no regressions found. 
> 
> Hopefully this version of the patch is acceptable. 
> 
>                           Carl 
> 
>   -----------------------------------------------------
> 
> PowerPC: fix for gdb.reverse/finish-precsave.exp and
> gdb.reverse/finish-reverse.exp
> 
> PPC64 multiple entry points.  When executing in reverse the function
> finish_backward sets the break point at the alternate entry point,
> known
> as the global entry point (GEP) in PowerPC.  However if the forward
> execution enters via the normal entry point, known as the local entry
> point (LEP) on PowerPC, reverse execution never sees the break point
> at the
> alternate entry point of the function.  Reverse execution continues
> until
> the next break point is encountered thus stopping at the wrong place.
> 
> This patch adds a new address to struct execution_control_state to
> hold the
> address of the alternate entry point (GEP).  The finish_backwards
> function
> is updated, if the stopping point is between the normal entry point
> (LEP)
> and the end of the function, a breakpoint is set at the normal entry
> point.
> If the stopping point is between the entry points, a breakpoint is
> set to
> the alternate entry point.
> 
> The patch fixes the behavior of the reverse-finish command on PowerPC
> to
> match the behavior of the command on other platforms, specifically
> X86.
> The patch does not change the behavior of the command on X86.
> 
> A new test is added to verify the reverse-finish command on PowerPC
> correctly stops at the instruction where the function call is
> made.  A new
> test, finish-reverse-next.exp, is added to verify the correct
> functionality
> of the reverse-finish command.  The reverse-finish comand is expected
> to
> stop on the instruction that jumps to the function.  Procedure
> proc_step_until from test gdb.reverse/step-indirect-call-thunk.exp is
> moved
> to lib/gdb.exp and renamed repeat_cmd_until.
> 
> The patch fixes 11 regression errors in test gdb.reverse/finish-
> precsave.exp
> and 11 regression errors in test gdb.reverse/finish-reverse.exp.
> 
> The patch has been tested on Power 10 and X86 processor with no new
> regression failures.
> ---
>  gdb/infcmd.c                                  |  47 ++--
>  gdb/infrun.c                                  |  24 ++
>  .../gdb.reverse/finish-reverse-next.c         |  91 +++++++
>  .../gdb.reverse/finish-reverse-next.exp       | 224
> ++++++++++++++++++
>  .../gdb.reverse/step-indirect-call-thunk.exp  |  55 ++---
>  gdb/testsuite/lib/gdb.exp                     |  49 +++-
>  6 files changed, 421 insertions(+), 69 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
>  create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> 
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 77206fcbfe8..0fa5719d38b 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm
> *sm)
>       no way that a function up the stack can have a return address
>       that's equal to its entry point.  */
> 
> -  if (sal.pc != pc)
> -    {
> -      frame_info_ptr frame = get_selected_frame (nullptr);
> -      struct gdbarch *gdbarch = get_frame_arch (frame);
> +  CORE_ADDR alt_entry_point = sal.pc;
> +  CORE_ADDR entry_point = alt_entry_point;
> +  frame_info_ptr frame = get_selected_frame (nullptr);
> +  struct gdbarch *gdbarch = get_frame_arch (frame);
> +
> +  if (gdbarch_skip_entrypoint_p (gdbarch))
> +    /* Some architectures, like PowerPC use local and global entry
> points.
> +       There is only one Entry Point (GEP = LEP) for other
> architectures.
> +       The GEP is an alternate entry point.  The LEP is the normal
> entry point.
> +       The value of entry_point was initialized to the alternate
> entry point
> +       (GEP).  It will be adjusted to the normal entry point if the
> function
> +       has two entry points.  */
> +    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
> 
> -      /* Set a step-resume at the function's entry point.  Once
> that's
> -	 hit, we'll do one more step backwards.  */
> +  if  ((pc < alt_entry_point) || (pc > entry_point))
> +    {
> +      /* We are in the body of the function.  Set a breakpoint to
> backup to
> +	 the normal entry point.  */
>        symtab_and_line sr_sal;
> -      sr_sal.pc = sal.pc;
> +      sr_sal.pc = entry_point;
>        sr_sal.pspace = get_frame_program_space (frame);
> -      insert_step_resume_breakpoint_at_sal (gdbarch,
> -					    sr_sal, null_frame_id);
> -
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> +      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
> +					    null_frame_id);
>      }
> +
>    else
> -    {
> -      /* We're almost there -- we just need to back up by one more
> -	 single-step.  */
> -      tp->control.step_range_start = tp->control.step_range_end = 1;
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> -    }
> +    /* We are either at one of the entry points or between the entry
> points.
> +       If we are not at the alt_entry point, go back to the
> alt_entry_point
> +       If we at the normal entry point step back one instruction,
> when we
> +       stop we will determine if we entered via the entry point or
> the
> +       alternate entry point.  If we are at the alternate entry
> point,
> +       single step back to the function call.  */
> +    tp->control.step_range_start = tp->control.step_range_end = 1;
> +
> +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>  }
> 
>  /* finish_forward -- helper function for finish_command.  FRAME is
> the
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 87ab73c47a4..987dbd16ea4 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -1868,6 +1868,7 @@ struct execution_control_state
> 
>    struct target_waitstatus ws;
>    int stop_func_filled_in = 0;
> +  CORE_ADDR stop_func_alt_start = 0;
>    CORE_ADDR stop_func_start = 0;
>    CORE_ADDR stop_func_end = 0;
>    const char *stop_func_name = nullptr;
> @@ -4680,6 +4681,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
>  	  ecs->stop_func_start
>  	    += gdbarch_deprecated_function_start_offset (gdbarch);
> 
> +	  /* PowerPC functions have a Local Entry Point (LEP) and a
> Global
> +	     Entry Point (GEP).  There is only one Entry Point (GEP =
> LEP) for
> +	     other architectures.  */
> +	  ecs->stop_func_alt_start = ecs->stop_func_start;
> +
>  	  if (gdbarch_skip_entrypoint_p (gdbarch))
>  	    ecs->stop_func_start
>  	      = gdbarch_skip_entrypoint (gdbarch, ecs-
> >stop_func_start);
> @@ -7269,6 +7275,24 @@ process_event_stop_test (struct
> execution_control_state *ecs)
>  	}
>      }
> 
> +  if (execution_direction == EXEC_REVERSE
> +      && ecs->event_thread->control.proceed_to_finish
> +      && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
> +      && ecs->event_thread->stop_pc () < ecs->stop_func_start)
> +    {
> +      /* We are executing the reverse-finish command.
> +	 If the system supports multiple entry points and we are
> finishing a
> +	 function in reverse.   If we are between the entry points
> singe-step
> +	 back to the alternate entry point.  If we are at the alternate
> entry
> +	 point -- just   need to back up by one more single-step, which
> +	 should take us back to the function call.  */
> +      ecs->event_thread->control.step_range_start
> +	= ecs->event_thread->control.step_range_end = 1;
> +      keep_going (ecs);
> +      return;
> +
> +    }
> +
>    if (ecs->event_thread->control.step_range_end == 1)
>      {
>        /* It is stepi or nexti.  We always want to stop stepping
> after
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> new file mode 100644
> index 00000000000..e95ee8e33a6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> @@ -0,0 +1,91 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2012-2023 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or
> modify
> +   it under the terms of the GNU General Public License as published
> by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <
> http://www.gnu.org/licenses/>.  */
> +
> +/* The reverse finish command should return from a function and stop
> on
> +   the first instruction of the source line where the function call
> is made.
> +   Specifically, the behavior should match doing a reverse next from
> the
> +   first instruction in the function.  GDB should only require one
> reverse
> +   step or next statement to reach the previous source code line.
> +
> +   This test verifies the fix for gdb bugzilla:
> +
> +   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +   PowerPC supports two entry points to a function.  The normal
> entry point
> +   is called the local entry point (LEP).  The alternate entry point
> is called
> +   the global entry point (GEP).  The GEP is only used if the table
> of
> +   contents (TOC) value stored in register r2 needs to be setup
> prior to
> +   execution starting at the LEP.  A function call via a function
> pointer
> +   will entry via the GEP.  A normal function call will enter via
> the LEP.
> +
> +   This test has been expanded to include tests to verify the
> reverse-finish
> +   command works properly if the function is called via the
> GEP.  The original
> +   test only verified the reverse-finish command for a normal call
> that used
> +   the LEP.  */
> +
> +int
> +function2 (int a, int b)
> +{
> +  int ret = 0;
> +  ret = ret + a + b;
> +  return ret;
> +}
> +
> +int
> +function1 (int a, int b)   // FUNCTION1
> +{
> +  int ret = 0;
> +  int (*funp) (int, int) = &function2;
> +  /* The assembly code for this function when compiled for PowerPC
> is as
> +     follows:
> +
> +     0000000010000758 <function1>:
> +     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
> +     1000075c:	00 7f 42 38 	addi    r2,r2,32512
> +     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
> +     10000764:	10 00 01 f8 	std     r0,16(r1)
> +     ....
> +
> +     When the function is called on PowerPC with function1 (a, b)
> the call
> +     enters at the Local Entry Point (LEP).  When the function is
> called via
> +     a function pointer, the Global Entry Point (GEP) for function1
> is used.
> +     The GEP sets up register 2 before reaching the LEP.
> +  */
> +  ret = funp (a + 1, b + 2);
> +  return ret;
> +}
> +
> +int
> +main(int argc, char* argv[])
> +{
> +  int a, b;
> +  int (*funp) (int, int) = &function1;
> +
> +  /* Call function via Local Entry Point (LEP).  */
> +
> +  a = 1;
> +  b = 5;
> +
> +  function1 (a, b);   // CALL VIA LEP
> +
> +  /* Call function via Global Entry Point (GEP).  */
> +  a = 10;
> +  b = 50;
> +
> +  funp (a, b);        // CALL VIA GEP
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> new file mode 100644
> index 00000000000..1f53b649a7d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> @@ -0,0 +1,224 @@
> +# Copyright 2008-2023 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or
> modify
> +# it under the terms of the GNU General Public License as published
> by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <
> http://www.gnu.org/licenses/>.  */
> +
> +# This file is part of the GDB testsuite.  It tests reverse
> stepping.
> +# Lots of code borrowed from "step-test.exp".
> +
> +# The reverse finish command should return from a function and stop
> on
> +# the first instruction of the source line where the function call
> is made.
> +# Specifically, the behavior should match doing a reverse next from
> the
> +# first instruction in the function.  GDB should only take one
> reverse step
> +# or next statement to reach the previous source code line.
> +
> +# This testcase verifies the reverse-finish command stops at the
> first
> +# instruction in the source code line where the function was
> called.  There
> +# are two scenarios that must be checked:
> +#   1) gdb is at the entry point instruction for the function
> +#   2) gdb is in the body of the function.
> +
> +# This test verifies the fix for gdb bugzilla:
> +#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +# PowerPC supports two entry points to a function.  The normal entry
> point
> +# is called the local entry point (LEP).  The alternate entry point
> is called
> +# the global entry point (GEP).  A function call via a function
> pointer
> +# will entry via the GEP.  A normal function call will enter via the
> LEP.
> +#
> +# This test has been expanded to include tests to verify the
> reverse-finish
> +# command works properly if the function is called via the GEP.  The
> original
> +# test only verified the reverse-finish command for a normal call
> that used
> +# the LEP.
> +
> +if ![supports_reverse] {
> +    return
> +}
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] }
> {
> +    return -1
> +}
> +
> +runto_main
> +set target_remote [gdb_is_target_remote]
> +
> +if [supports_process_record] {
> +    # Activate process record/replay.
> +    gdb_test_no_output "record" "turn on process record for test1"
> +}
> +
> +
> +### TEST 1: reverse finish from the entry point instruction (LEP) in
> +### function1 when called using the normal entry point (LEP).
> +
> +# Set breakpoint at call to function1 in main.
> +set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into
> function" \
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function1
> +repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1
> call" "100"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA
> LEP.*" \
> +    "reverse-finish function1 LEP call from LEP "
> +gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP"
> \
> +    "reverse next 1 LEP entry point function call from LEP"
> +gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call
> from LEP"
> +
> +
> +gdb_test "reverse-continue" ".*" "setup for test 2"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test1"
> +gdb_test_no_output "record" "turn on process record for test2"
> +
> +
> +### TEST 2: reverse finish from the body of function1.
> +
> +# Set breakpoint at call to function1 in main.
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "at function1 entry point instruction to step to body of
> function" \
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
> +
> +# do a step instruction to get to the body of the function
> +gdb_test "step" ".*int ret = 0;.*" "step test 1"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA
> LEP.*" \
> +    "reverse-finish function1 LEP call from function body"
> +gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA
> LEP.*" \
> +    "reverse next 1 LEP from function body"
> +gdb_test "reverse-next" ".*b = 5;.*" \
> +    "reverse next 2 at b = 5, from function body"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 3"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test2"
> +gdb_test_no_output "record" "turn on process record for test3"
> +
> +
> +### TEST 3: reverse finish from the alternate entry point
> instruction (GEP) in
> +### function1 when called using the alternate entry point (GEP).
> +
> +# Set breakpoint at call to funp in main.
> +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into
> funp" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function.
> +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "function1 GEP call call from GEP"
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP entry point function call from GEP"
> +gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50,
> call from GEP"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 4"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test3"
> +gdb_test_no_output "record" "turn on process record for test4"
> +
> +### TEST 4: reverse finish from between the GEP and LEP in
> +### function1 when called using the alternate entry point (GEP).
> +
> +# Set breakpoint at call to funp in main.
> +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into funp
> again" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function.
> +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call
> again"
> +
> +# do one more stepi so we are between the GEP and LEP.
> +gdb_test "stepi" "{" "stepi to between GEP and LEP"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "function1 GEP call call from GEP again"
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP entry point function call from GEP again"
> +gdb_test "reverse-next" ".*b = 50;.*" \
> +    "reverse next 2 at b = 50, call from GEP again"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 5"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test4"
> +gdb_test_no_output "record" "turn on process record for test5"
> +
> +
> +### TEST 5: reverse finish from the body of function 1 when calling
> using the
> +### alternate entrypoint (GEP).
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call.
> +gdb_continue_to_breakpoint \
> +    "at function1 entry point instruction to step to body of funp
> call" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# Step into body of funp, called via GEP.
> +gdb_test "step" ".*int ret = 0;.*" "step test 2"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "reverse-finish function1 GEP call, from function body  "
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP call from function body"
> +gdb_test "reverse-next" ".*b = 50;.*" \
> +    "reverse next 2 at b = 50 from function body"
> diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> index 94292d5eb9b..61fb4974b8e 100644
> --- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> +++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> @@ -17,6 +17,12 @@ require supports_reverse
> 
>  standard_testfile
> 
> +if { [istarget "powerpc*-*-linux*"] } {
> +    # GCC for PowerPC on linux does not support the -mindirect-
> branch and
> +    # -mfunction-return command line options.
> +    return 0
> +}
> +
>  set cflags {}
>  lappend cflags debug
>  lappend cflags additional_flags=-mindirect-branch=thunk
> @@ -36,39 +42,6 @@ if { ![runto_main] } {
>      return -1
>  }
> 
> -# Do repeated stepping COMMANDs in order to reach TARGET from
> CURRENT
> -#
> -#  COMMAND is a stepping command
> -#  CURRENT is a string matching the current location
> -#  TARGET  is a string matching the target location
> -#  TEST    is the test name
> -#
> -# The function issues repeated COMMANDs as long as the location
> matches
> -# CURRENT up to a maximum of 100 steps.
> -#
> -# TEST passes if the resulting location matches TARGET and fails
> -# otherwise.
> -#
> -proc step_until { command current target test } {
> -    global gdb_prompt
> -
> -    set count 0
> -    gdb_test_multiple "$command" "$test" {
> -        -re "$current.*$gdb_prompt $" {
> -            incr count
> -            if { $count < 100 } {
> -                send_gdb "$command\n"
> -                exp_continue
> -            } else {
> -                fail "$test"
> -            }
> -        }
> -        -re "$target.*$gdb_prompt $" {
> -            pass "$test"
> -        }
> -    }
> -}
> -
>  gdb_test_no_output "record"
>  gdb_test "next" ".*" "record trace"
> 
> @@ -88,20 +61,20 @@ gdb_test "reverse-next" "apply\.2.*" \
>      "reverse-step through thunks and over inc"
> 
>  # We can use instruction stepping to step into thunks.
> -step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call
> thunk"
> -step_until "stepi" "indirect_thunk" "inc" \
> +repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into
> call thunk"
> +repeat_cmd_until "stepi" "indirect_thunk" "inc" \
>      "stepi out of call thunk into inc"
>  set alphanum_re "\[a-zA-Z0-9\]"
>  set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re*
> \\(\\)"
> -step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into
> return thunk"
> -step_until "stepi" "return_thunk" "apply" \
> +repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi
> into return thunk"
> +repeat_cmd_until "stepi" "return_thunk" "apply" \
>      "stepi out of return thunk back into apply"
> 
> -step_until "reverse-stepi" "apply" "return_thunk" \
> +repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
>      "reverse-stepi into return thunk"
> -step_until "reverse-stepi" "return_thunk" "inc" \
> +repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
>      "reverse-stepi out of return thunk into inc"
> -step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
> +repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)"
> "indirect_thunk" \
>      "reverse-stepi into call thunk"
> -step_until "reverse-stepi" "indirect_thunk" "apply" \
> +repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
>      "reverse-stepi out of call thunk into apply"
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index faa0ac05a9a..b10555fe5fb 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -9267,31 +9267,58 @@ gdb_caching_proc arm_cc_for_target {
> 
>  # Step until the pattern REGEXP is found.  Step at most
>  # MAX_STEPS times, but stop stepping once REGEXP is found.
> -#
> +# START matches current location
>  # If REGEXP is found then a single pass is emitted, otherwise, after
>  # MAX_STEPS steps, a single fail is emitted.
>  #
>  # TEST_NAME is the name used in the pass/fail calls.
> 
> -proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
> +proc gdb_step_until { regexp {test_name ""} {current ""} \
> +			  { max_steps 10 } } {
> +    if { $current == "" } {
> +	set current "\}"
> +    }
> +    if { $test_name == "" } {
> +	set test_name "stepping until regexp"
> +    }
> +
> +    repeat_cmd_until "step" $current  $regexp  $test_name "10"
> +}
> +
> +# Do repeated stepping COMMANDs in order to reach TARGET from
> CURRENT
> +#
> +#  COMMAND is a stepping command
> +#  CURRENT is a string matching the current location
> +#  TARGET  is a string matching the target location
> +#  TEST    is the test name
> +#  MAX_STEPS is number of steps attempted before fail is emitted
> +#
> +# The function issues repeated COMMANDs as long as the location
> matches
> +# CURRENT up to a maximum of 100 steps.
> +#
> +# TEST passes if the resulting location matches TARGET and fails
> +# otherwise.
> +#
> +proc repeat_cmd_until { command current target test_name {max_steps
> 100} } {
> +    global gdb_prompt
>      if { $test_name == "" } {
>  	set test_name "stepping until regexp"
>      }
> 
>      set count 0
> -    gdb_test_multiple "step" "$test_name" {
> -	-re "$regexp\r\n$::gdb_prompt $" {
> -	    pass $test_name
> -	}
> -	-re ".*$::gdb_prompt $" {
> -	    if {$count < $max_steps} {
> -		incr count
> -		send_gdb "step\n"
> +    gdb_test_multiple "$command" "$test_name" {
> +	-re "$current.*$gdb_prompt $" {
> +	    incr count
> +	    if { $count < $max_steps } {
> +		send_gdb "$command\n"
>  		exp_continue
>  	    } else {
> -		fail $test_name
> +		fail "$test_name"
>  	    }
>  	}
> +	-re "$target.*$gdb_prompt $" {
> +	    pass "$test_name"
> +	}
>      }
>  }
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-20 20:24                                                                                   ` Carl Love
  2023-02-27 16:09                                                                                     ` [PING] " Carl Love
@ 2023-02-28 13:39                                                                                     ` Bruno Larsen
  2023-02-28 16:19                                                                                       ` Carl Love
  2023-03-01 13:43                                                                                     ` Tom de Vries
                                                                                                       ` (2 subsequent siblings)
  4 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-02-28 13:39 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, gdb-patches, tdevries, pedro

On 20/02/2023 21:24, Carl Love wrote:
> Ulrich, Bruno, GDB maintainers:
>
> Per the comments from Ulrich, I have updated the patch to address the
> comments about the source code and the testcase. I updated the new
> library procedure so it can be called from gdb_step_until.  So
> gdb_step_until is now just a variant of the new repeat_cmd_until
> proceedure.
>
> The redundant if test has been removed.  It was added to fix a
> regression testing failure I saw on the gdb.btrace/tailcall.exp on X86.
> I went back and redid the testing, rebuilding everything from scratch.
> I am not able to reproduce the test failure without the redundant
> check.  Not sure why I initially saw the regression failure at this
> point?  Perhaps I hadn't re-enabled the
> /proc/sys/kernel/perf_event_paranoid value?  It must be 2 or lower for
> the test to run.  Otherwise the test fails.  Anyway, the regression
> tests on X86 run without the redundant check are passing on my laptop.
>
> I resolved the issues with the testing on X86 to make sure it isn't
> missing failures when testing gdb.reverse/step-indirect-call-thunk.exp.
> As mentioned in the previous email, the test does not run on PowerPC
> since the gcc command line options "-mindirect-branch=thunk" and "-
> mfunction-return=thunk" are not supported on PowerPC.  I disabled the
> test on PowerPC in the updated patch.
>
> Retested on X86 generation 5 and PowerPC with no regressions found.
>
> Hopefully this version of the patch is acceptable.
>
>                            Carl

Hi Carl,

Sorry about the delay. I've tested the series and see no regressions. In 
particular, the tests you called out all passed on my machine. I have a 
minor wording nit in one comment, but regardless, you can add to the tag:

Reviewed-By: Bruno Larsen <blarsen@redhat.com>

>    -----------------------------------------------------
>
> PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
>
> PPC64 multiple entry points.  When executing in reverse the function
> finish_backward sets the break point at the alternate entry point, known
> as the global entry point (GEP) in PowerPC.  However if the forward
> execution enters via the normal entry point, known as the local entry
> point (LEP) on PowerPC, reverse execution never sees the break point at the
> alternate entry point of the function.  Reverse execution continues until
> the next break point is encountered thus stopping at the wrong place.
>
> This patch adds a new address to struct execution_control_state to hold the
> address of the alternate entry point (GEP).  The finish_backwards function
> is updated, if the stopping point is between the normal entry point (LEP)
> and the end of the function, a breakpoint is set at the normal entry point.
> If the stopping point is between the entry points, a breakpoint is set to
> the alternate entry point.
>
> The patch fixes the behavior of the reverse-finish command on PowerPC to
> match the behavior of the command on other platforms, specifically X86.
> The patch does not change the behavior of the command on X86.
>
> A new test is added to verify the reverse-finish command on PowerPC
> correctly stops at the instruction where the function call is made.  A new
> test, finish-reverse-next.exp, is added to verify the correct functionality
> of the reverse-finish command.  The reverse-finish comand is expected to
> stop on the instruction that jumps to the function.  Procedure
> proc_step_until from test gdb.reverse/step-indirect-call-thunk.exp is moved
> to lib/gdb.exp and renamed repeat_cmd_until.
>
> The patch fixes 11 regression errors in test gdb.reverse/finish-precsave.exp
> and 11 regression errors in test gdb.reverse/finish-reverse.exp.
>
> The patch has been tested on Power 10 and X86 processor with no new
> regression failures.
> ---
>   gdb/infcmd.c                                  |  47 ++--
>   gdb/infrun.c                                  |  24 ++
>   .../gdb.reverse/finish-reverse-next.c         |  91 +++++++
>   .../gdb.reverse/finish-reverse-next.exp       | 224 ++++++++++++++++++
>   .../gdb.reverse/step-indirect-call-thunk.exp  |  55 ++---
>   gdb/testsuite/lib/gdb.exp                     |  49 +++-
>   6 files changed, 421 insertions(+), 69 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
>   create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp
>
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 77206fcbfe8..0fa5719d38b 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm *sm)
>        no way that a function up the stack can have a return address
>        that's equal to its entry point.  */
>   
> -  if (sal.pc != pc)
> -    {
> -      frame_info_ptr frame = get_selected_frame (nullptr);
> -      struct gdbarch *gdbarch = get_frame_arch (frame);
> +  CORE_ADDR alt_entry_point = sal.pc;
> +  CORE_ADDR entry_point = alt_entry_point;
> +  frame_info_ptr frame = get_selected_frame (nullptr);
> +  struct gdbarch *gdbarch = get_frame_arch (frame);
> +
> +  if (gdbarch_skip_entrypoint_p (gdbarch))
> +    /* Some architectures, like PowerPC use local and global entry points.
> +       There is only one Entry Point (GEP = LEP) for other architectures.
> +       The GEP is an alternate entry point.  The LEP is the normal entry point.
> +       The value of entry_point was initialized to the alternate entry point
> +       (GEP).  It will be adjusted to the normal entry point if the function
> +       has two entry points.  */
> +    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
>   
> -      /* Set a step-resume at the function's entry point.  Once that's
> -	 hit, we'll do one more step backwards.  */
> +  if  ((pc < alt_entry_point) || (pc > entry_point))
> +    {
> +      /* We are in the body of the function.  Set a breakpoint to backup to

I would change backup for "return", or separate it to "back up", 
otherwise I personally think of data backups.


-- 
Cheers,
Bruno

> +	 the normal entry point.  */
>         symtab_and_line sr_sal;
> -      sr_sal.pc = sal.pc;
> +      sr_sal.pc = entry_point;
>         sr_sal.pspace = get_frame_program_space (frame);
> -      insert_step_resume_breakpoint_at_sal (gdbarch,
> -					    sr_sal, null_frame_id);
> -
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> +      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
> +					    null_frame_id);
>       }
> +
>     else
> -    {
> -      /* We're almost there -- we just need to back up by one more
> -	 single-step.  */
> -      tp->control.step_range_start = tp->control.step_range_end = 1;
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> -    }
> +    /* We are either at one of the entry points or between the entry points.
> +       If we are not at the alt_entry point, go back to the alt_entry_point
> +       If we at the normal entry point step back one instruction, when we
> +       stop we will determine if we entered via the entry point or the
> +       alternate entry point.  If we are at the alternate entry point,
> +       single step back to the function call.  */
> +    tp->control.step_range_start = tp->control.step_range_end = 1;
> +
> +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>   }
>   
>   /* finish_forward -- helper function for finish_command.  FRAME is the
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 87ab73c47a4..987dbd16ea4 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -1868,6 +1868,7 @@ struct execution_control_state
>   
>     struct target_waitstatus ws;
>     int stop_func_filled_in = 0;
> +  CORE_ADDR stop_func_alt_start = 0;
>     CORE_ADDR stop_func_start = 0;
>     CORE_ADDR stop_func_end = 0;
>     const char *stop_func_name = nullptr;
> @@ -4680,6 +4681,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
>   	  ecs->stop_func_start
>   	    += gdbarch_deprecated_function_start_offset (gdbarch);
>   
> +	  /* PowerPC functions have a Local Entry Point (LEP) and a Global
> +	     Entry Point (GEP).  There is only one Entry Point (GEP = LEP) for
> +	     other architectures.  */
> +	  ecs->stop_func_alt_start = ecs->stop_func_start;
> +
>   	  if (gdbarch_skip_entrypoint_p (gdbarch))
>   	    ecs->stop_func_start
>   	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
> @@ -7269,6 +7275,24 @@ process_event_stop_test (struct execution_control_state *ecs)
>   	}
>       }
>   
> +  if (execution_direction == EXEC_REVERSE
> +      && ecs->event_thread->control.proceed_to_finish
> +      && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
> +      && ecs->event_thread->stop_pc () < ecs->stop_func_start)
> +    {
> +      /* We are executing the reverse-finish command.
> +	 If the system supports multiple entry points and we are finishing a
> +	 function in reverse.   If we are between the entry points singe-step
> +	 back to the alternate entry point.  If we are at the alternate entry
> +	 point -- just   need to back up by one more single-step, which
> +	 should take us back to the function call.  */
> +      ecs->event_thread->control.step_range_start
> +	= ecs->event_thread->control.step_range_end = 1;
> +      keep_going (ecs);
> +      return;
> +
> +    }
> +
>     if (ecs->event_thread->control.step_range_end == 1)
>       {
>         /* It is stepi or nexti.  We always want to stop stepping after
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> new file mode 100644
> index 00000000000..e95ee8e33a6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> @@ -0,0 +1,91 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2012-2023 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +/* The reverse finish command should return from a function and stop on
> +   the first instruction of the source line where the function call is made.
> +   Specifically, the behavior should match doing a reverse next from the
> +   first instruction in the function.  GDB should only require one reverse
> +   step or next statement to reach the previous source code line.
> +
> +   This test verifies the fix for gdb bugzilla:
> +
> +   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +   PowerPC supports two entry points to a function.  The normal entry point
> +   is called the local entry point (LEP).  The alternate entry point is called
> +   the global entry point (GEP).  The GEP is only used if the table of
> +   contents (TOC) value stored in register r2 needs to be setup prior to
> +   execution starting at the LEP.  A function call via a function pointer
> +   will entry via the GEP.  A normal function call will enter via the LEP.
> +
> +   This test has been expanded to include tests to verify the reverse-finish
> +   command works properly if the function is called via the GEP.  The original
> +   test only verified the reverse-finish command for a normal call that used
> +   the LEP.  */
> +
> +int
> +function2 (int a, int b)
> +{
> +  int ret = 0;
> +  ret = ret + a + b;
> +  return ret;
> +}
> +
> +int
> +function1 (int a, int b)   // FUNCTION1
> +{
> +  int ret = 0;
> +  int (*funp) (int, int) = &function2;
> +  /* The assembly code for this function when compiled for PowerPC is as
> +     follows:
> +
> +     0000000010000758 <function1>:
> +     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
> +     1000075c:	00 7f 42 38 	addi    r2,r2,32512
> +     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
> +     10000764:	10 00 01 f8 	std     r0,16(r1)
> +     ....
> +
> +     When the function is called on PowerPC with function1 (a, b) the call
> +     enters at the Local Entry Point (LEP).  When the function is called via
> +     a function pointer, the Global Entry Point (GEP) for function1 is used.
> +     The GEP sets up register 2 before reaching the LEP.
> +  */
> +  ret = funp (a + 1, b + 2);
> +  return ret;
> +}
> +
> +int
> +main(int argc, char* argv[])
> +{
> +  int a, b;
> +  int (*funp) (int, int) = &function1;
> +
> +  /* Call function via Local Entry Point (LEP).  */
> +
> +  a = 1;
> +  b = 5;
> +
> +  function1 (a, b);   // CALL VIA LEP
> +
> +  /* Call function via Global Entry Point (GEP).  */
> +  a = 10;
> +  b = 50;
> +
> +  funp (a, b);        // CALL VIA GEP
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> new file mode 100644
> index 00000000000..1f53b649a7d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> @@ -0,0 +1,224 @@
> +# Copyright 2008-2023 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +# This file is part of the GDB testsuite.  It tests reverse stepping.
> +# Lots of code borrowed from "step-test.exp".
> +
> +# The reverse finish command should return from a function and stop on
> +# the first instruction of the source line where the function call is made.
> +# Specifically, the behavior should match doing a reverse next from the
> +# first instruction in the function.  GDB should only take one reverse step
> +# or next statement to reach the previous source code line.
> +
> +# This testcase verifies the reverse-finish command stops at the first
> +# instruction in the source code line where the function was called.  There
> +# are two scenarios that must be checked:
> +#   1) gdb is at the entry point instruction for the function
> +#   2) gdb is in the body of the function.
> +
> +# This test verifies the fix for gdb bugzilla:
> +#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +# PowerPC supports two entry points to a function.  The normal entry point
> +# is called the local entry point (LEP).  The alternate entry point is called
> +# the global entry point (GEP).  A function call via a function pointer
> +# will entry via the GEP.  A normal function call will enter via the LEP.
> +#
> +# This test has been expanded to include tests to verify the reverse-finish
> +# command works properly if the function is called via the GEP.  The original
> +# test only verified the reverse-finish command for a normal call that used
> +# the LEP.
> +
> +if ![supports_reverse] {
> +    return
> +}
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
> +    return -1
> +}
> +
> +runto_main
> +set target_remote [gdb_is_target_remote]
> +
> +if [supports_process_record] {
> +    # Activate process record/replay.
> +    gdb_test_no_output "record" "turn on process record for test1"
> +}
> +
> +
> +### TEST 1: reverse finish from the entry point instruction (LEP) in
> +### function1 when called using the normal entry point (LEP).
> +
> +# Set breakpoint at call to function1 in main.
> +set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into function" \
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function1
> +repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call" "100"
> +
> +# The reverse-finish command should stop on the function call instruction
> +# which is the last instruction in the source code line.  A reverse-next
> +# instruction should then stop at the first instruction in the same source
> +# code line.  Another revers-next instruction stops at the previous source
> +# code line.
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +    "reverse-finish function1 LEP call from LEP "
> +gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
> +    "reverse next 1 LEP entry point function call from LEP"
> +gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call from LEP"
> +
> +
> +gdb_test "reverse-continue" ".*" "setup for test 2"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test1"
> +gdb_test_no_output "record" "turn on process record for test2"
> +
> +
> +### TEST 2: reverse finish from the body of function1.
> +
> +# Set breakpoint at call to function1 in main.
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "at function1 entry point instruction to step to body of function" \
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
> +
> +# do a step instruction to get to the body of the function
> +gdb_test "step" ".*int ret = 0;.*" "step test 1"
> +
> +# The reverse-finish command should stop on the function call instruction
> +# which is the last instruction in the source code line.  A reverse-next
> +# instruction should then stop at the first instruction in the same source
> +# code line.  Another revers-next instruction stops at the previous source
> +# code line.
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +    "reverse-finish function1 LEP call from function body"
> +gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +    "reverse next 1 LEP from function body"
> +gdb_test "reverse-next" ".*b = 5;.*" \
> +    "reverse next 2 at b = 5, from function body"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 3"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test2"
> +gdb_test_no_output "record" "turn on process record for test3"
> +
> +
> +### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
> +### function1 when called using the alternate entry point (GEP).
> +
> +# Set breakpoint at call to funp in main.
> +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into funp" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function.
> +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
> +
> +# The reverse-finish command should stop on the function call instruction
> +# which is the last instruction in the source code line.  A reverse-next
> +# instruction should then stop at the first instruction in the same source
> +# code line.  Another revers-next instruction stops at the previous source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "function1 GEP call call from GEP"
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP entry point function call from GEP"
> +gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, call from GEP"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 4"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test3"
> +gdb_test_no_output "record" "turn on process record for test4"
> +
> +### TEST 4: reverse finish from between the GEP and LEP in
> +### function1 when called using the alternate entry point (GEP).
> +
> +# Set breakpoint at call to funp in main.
> +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into funp again" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function.
> +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call again"
> +
> +# do one more stepi so we are between the GEP and LEP.
> +gdb_test "stepi" "{" "stepi to between GEP and LEP"
> +
> +# The reverse-finish command should stop on the function call instruction
> +# which is the last instruction in the source code line.  A reverse-next
> +# instruction should then stop at the first instruction in the same source
> +# code line.  Another revers-next instruction stops at the previous source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "function1 GEP call call from GEP again"
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP entry point function call from GEP again"
> +gdb_test "reverse-next" ".*b = 50;.*" \
> +    "reverse next 2 at b = 50, call from GEP again"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 5"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test4"
> +gdb_test_no_output "record" "turn on process record for test5"
> +
> +
> +### TEST 5: reverse finish from the body of function 1 when calling using the
> +### alternate entrypoint (GEP).
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call.
> +gdb_continue_to_breakpoint \
> +    "at function1 entry point instruction to step to body of funp call" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# Step into body of funp, called via GEP.
> +gdb_test "step" ".*int ret = 0;.*" "step test 2"
> +
> +# The reverse-finish command should stop on the function call instruction
> +# which is the last instruction in the source code line.  A reverse-next
> +# instruction should then stop at the first instruction in the same source
> +# code line.  Another revers-next instruction stops at the previous source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "reverse-finish function1 GEP call, from function body  "
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP call from function body"
> +gdb_test "reverse-next" ".*b = 50;.*" \
> +    "reverse next 2 at b = 50 from function body"
> diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> index 94292d5eb9b..61fb4974b8e 100644
> --- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> +++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
> @@ -17,6 +17,12 @@ require supports_reverse
>   
>   standard_testfile
>   
> +if { [istarget "powerpc*-*-linux*"] } {
> +    # GCC for PowerPC on linux does not support the -mindirect-branch and
> +    # -mfunction-return command line options.
> +    return 0
> +}
> +
>   set cflags {}
>   lappend cflags debug
>   lappend cflags additional_flags=-mindirect-branch=thunk
> @@ -36,39 +42,6 @@ if { ![runto_main] } {
>       return -1
>   }
>   
> -# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
> -#
> -#  COMMAND is a stepping command
> -#  CURRENT is a string matching the current location
> -#  TARGET  is a string matching the target location
> -#  TEST    is the test name
> -#
> -# The function issues repeated COMMANDs as long as the location matches
> -# CURRENT up to a maximum of 100 steps.
> -#
> -# TEST passes if the resulting location matches TARGET and fails
> -# otherwise.
> -#
> -proc step_until { command current target test } {
> -    global gdb_prompt
> -
> -    set count 0
> -    gdb_test_multiple "$command" "$test" {
> -        -re "$current.*$gdb_prompt $" {
> -            incr count
> -            if { $count < 100 } {
> -                send_gdb "$command\n"
> -                exp_continue
> -            } else {
> -                fail "$test"
> -            }
> -        }
> -        -re "$target.*$gdb_prompt $" {
> -            pass "$test"
> -        }
> -    }
> -}
> -
>   gdb_test_no_output "record"
>   gdb_test "next" ".*" "record trace"
>   
> @@ -88,20 +61,20 @@ gdb_test "reverse-next" "apply\.2.*" \
>       "reverse-step through thunks and over inc"
>   
>   # We can use instruction stepping to step into thunks.
> -step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
> -step_until "stepi" "indirect_thunk" "inc" \
> +repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
> +repeat_cmd_until "stepi" "indirect_thunk" "inc" \
>       "stepi out of call thunk into inc"
>   set alphanum_re "\[a-zA-Z0-9\]"
>   set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
> -step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
> -step_until "stepi" "return_thunk" "apply" \
> +repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
> +repeat_cmd_until "stepi" "return_thunk" "apply" \
>       "stepi out of return thunk back into apply"
>   
> -step_until "reverse-stepi" "apply" "return_thunk" \
> +repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
>       "reverse-stepi into return thunk"
> -step_until "reverse-stepi" "return_thunk" "inc" \
> +repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
>       "reverse-stepi out of return thunk into inc"
> -step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
> +repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
>       "reverse-stepi into call thunk"
> -step_until "reverse-stepi" "indirect_thunk" "apply" \
> +repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
>       "reverse-stepi out of call thunk into apply"
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index faa0ac05a9a..b10555fe5fb 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -9267,31 +9267,58 @@ gdb_caching_proc arm_cc_for_target {
>   
>   # Step until the pattern REGEXP is found.  Step at most
>   # MAX_STEPS times, but stop stepping once REGEXP is found.
> -#
> +# START matches current location
>   # If REGEXP is found then a single pass is emitted, otherwise, after
>   # MAX_STEPS steps, a single fail is emitted.
>   #
>   # TEST_NAME is the name used in the pass/fail calls.
>   
> -proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
> +proc gdb_step_until { regexp {test_name ""} {current ""} \
> +			  { max_steps 10 } } {
> +    if { $current == "" } {
> +	set current "\}"
> +    }
> +    if { $test_name == "" } {
> +	set test_name "stepping until regexp"
> +    }
> +
> +    repeat_cmd_until "step" $current  $regexp  $test_name "10"
> +}
> +
> +# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
> +#
> +#  COMMAND is a stepping command
> +#  CURRENT is a string matching the current location
> +#  TARGET  is a string matching the target location
> +#  TEST    is the test name
> +#  MAX_STEPS is number of steps attempted before fail is emitted
> +#
> +# The function issues repeated COMMANDs as long as the location matches
> +# CURRENT up to a maximum of 100 steps.
> +#
> +# TEST passes if the resulting location matches TARGET and fails
> +# otherwise.
> +#
> +proc repeat_cmd_until { command current target test_name {max_steps 100} } {
> +    global gdb_prompt
>       if { $test_name == "" } {
>   	set test_name "stepping until regexp"
>       }
>   
>       set count 0
> -    gdb_test_multiple "step" "$test_name" {
> -	-re "$regexp\r\n$::gdb_prompt $" {
> -	    pass $test_name
> -	}
> -	-re ".*$::gdb_prompt $" {
> -	    if {$count < $max_steps} {
> -		incr count
> -		send_gdb "step\n"
> +    gdb_test_multiple "$command" "$test_name" {
> +	-re "$current.*$gdb_prompt $" {
> +	    incr count
> +	    if { $count < $max_steps } {
> +		send_gdb "$command\n"
>   		exp_continue
>   	    } else {
> -		fail $test_name
> +		fail "$test_name"
>   	    }
>   	}
> +	-re "$target.*$gdb_prompt $" {
> +	    pass "$test_name"
> +	}
>       }
>   }
>   


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-28 13:39                                                                                     ` Bruno Larsen
@ 2023-02-28 16:19                                                                                       ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-02-28 16:19 UTC (permalink / raw)
  To: Bruno Larsen, Ulrich Weigand, gdb-patches, tdevries, pedro; +Cc: cel

Bruno:

Thanks for testing and reviewing the patch

On Tue, 2023-02-28 at 14:39 +0100, Bruno Larsen wrote:
> Hi Carl,
> 
> Sorry about the delay. I've tested the series and see no regressions.
> In 
> particular, the tests you called out all passed on my machine. I have
> a 
> minor wording nit in one comment, but regardless, you can add to the
> tag:
> 
> Reviewed-By: Bruno Larsen <blarsen@redhat.com>
> 
> >     -----------------------------------------------------
> > 
> > 
<snip>
> > -      /* Set a step-resume at the function's entry point.  Once
> > that's
> > -      hit, we'll do one more step backwards.  */
> > +  if  ((pc < alt_entry_point) || (pc > entry_point))
> > +    {
> > +      /* We are in the body of the function.  Set a breakpoint to
> > backup to
> 
> I would change backup for "return", or separate it to "back up", 
> otherwise I personally think of data backups.


OK, I changed the line as follows in my copy of the patch

    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
 
   if  ((pc < alt_entry_point) || (pc > entry_point))
     {
-      /* We are in the body of the function.  Set a breakpoint to backup to
+      /* We are in the body of the function.  Set a breakpoint to go back to
 	 the normal entry point.  */
       symtab_and_line sr_sal;

I think that addresses your concern.  It is not worth resending the
patch at this point for this change but will include it in any future
posts or commits.  Thanks for the feedback.

                             Carl 




^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-20 20:24                                                                                   ` Carl Love
  2023-02-27 16:09                                                                                     ` [PING] " Carl Love
  2023-02-28 13:39                                                                                     ` Bruno Larsen
@ 2023-03-01 13:43                                                                                     ` Tom de Vries
  2023-03-01 16:26                                                                                       ` Carl Love
  2023-03-01 14:03                                                                                     ` Tom de Vries
  2023-03-01 14:34                                                                                     ` Tom de Vries
  4 siblings, 1 reply; 105+ messages in thread
From: Tom de Vries @ 2023-03-01 13:43 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro

On 2/20/23 21:24, Carl Love wrote:
> +if { [istarget "powerpc*-*-linux*"] } {
> +    # GCC for PowerPC on linux does not support the -mindirect-branch and
> +    # -mfunction-return command line options.
> +    return 0
> +}
> +

This bit is no longer necessary.

I've committed 2ef339e38f5 ("[gdb/testsuite] Require istarget x86* in 
gdb.reverse/step-indirect-call-thunk.exp") which copied your fix from 
commit 43127ae5714 ("Fix gdb.base/step-indirect-call-thunk.exp").

Thanks,
- Tom


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-20 20:24                                                                                   ` Carl Love
                                                                                                       ` (2 preceding siblings ...)
  2023-03-01 13:43                                                                                     ` Tom de Vries
@ 2023-03-01 14:03                                                                                     ` Tom de Vries
  2023-03-01 16:43                                                                                       ` Carl Love
  2023-03-01 14:34                                                                                     ` Tom de Vries
  4 siblings, 1 reply; 105+ messages in thread
From: Tom de Vries @ 2023-03-01 14:03 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro

On 2/20/23 21:24, Carl Love wrote:
>   # Step until the pattern REGEXP is found.  Step at most
>   # MAX_STEPS times, but stop stepping once REGEXP is found.
> -#
> +# START matches current location
>   # If REGEXP is found then a single pass is emitted, otherwise, after
>   # MAX_STEPS steps, a single fail is emitted.
>   #
>   # TEST_NAME is the name used in the pass/fail calls.
>   
> -proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
> +proc gdb_step_until { regexp {test_name ""} {current ""} \
> +			  { max_steps 10 } } {

I assume you meant CURRENT instead of START.

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-02-20 20:24                                                                                   ` Carl Love
                                                                                                       ` (3 preceding siblings ...)
  2023-03-01 14:03                                                                                     ` Tom de Vries
@ 2023-03-01 14:34                                                                                     ` Tom de Vries
  2023-03-01 20:39                                                                                       ` Carl Love
  4 siblings, 1 reply; 105+ messages in thread
From: Tom de Vries @ 2023-03-01 14:34 UTC (permalink / raw)
  To: Carl Love, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro

[-- Attachment #1: Type: text/plain, Size: 459 bytes --]

On 2/20/23 21:24, Carl Love wrote:
>   .../gdb.reverse/step-indirect-call-thunk.exp  |  55 ++---
>   gdb/testsuite/lib/gdb.exp                     |  49 +++-

I think the changes in these two files are not really related to 
$subject.  The only connection is that the newly introduced test-case 
gdb.reverse/finish-reverse-next.exp uses repeat_cmd_until.

I propose to commit attached patch separately.

Carl, can you review the commit message?

Thanks,
- Tom

[-- Attachment #2: 0001-gdb-testsuite-Introduce-repeat_cmd_until.patch --]
[-- Type: text/x-patch, Size: 4457 bytes --]

From d211b4d17c4c2253d85a73a78db5581b369746bd Mon Sep 17 00:00:00 2001
From: Carl Love <cel@us.ibm.com>
Date: Wed, 1 Mar 2023 14:50:15 +0100
Subject: [PATCH] [gdb/testsuite] Introduce repeat_cmd_until

Test-case gdb.reverse/step-indirect-call-thunk.exp contains a proc step_until.

OTOH, we've got a somewhat similar proc in lib/gdb.exp: gdb_step_until.

Fix this by:
- moving step_until into lib/gdb.exp and renaming to repeat_cmd_until,
- reimplementing gdb_step_until using repeat_cmd_until, and
- reimplementing step_until as an local alias of repeat_cmd_until
  (in order to avoid polluting history with updating all the calls).

Tested on x86_64-linux.
---
 .../gdb.reverse/step-indirect-call-thunk.exp  | 32 +-----------
 gdb/testsuite/lib/gdb.exp                     | 49 ++++++++++++++-----
 2 files changed, 40 insertions(+), 41 deletions(-)

diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index f433efb11c2..d431d174f88 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -38,37 +38,9 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
+# Local alias for repeat_cmd_until.
 proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
+    repeat_cmd_until $command $current $target $test
 }
 
 gdb_test_no_output "record"
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 19c782bea46..650a44aab1e 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9270,31 +9270,58 @@ gdb_caching_proc arm_cc_for_target {
 
 # Step until the pattern REGEXP is found.  Step at most
 # MAX_STEPS times, but stop stepping once REGEXP is found.
-#
+# CURRENT matches current location.
 # If REGEXP is found then a single pass is emitted, otherwise, after
 # MAX_STEPS steps, a single fail is emitted.
 #
 # TEST_NAME is the name used in the pass/fail calls.
 
-proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
+proc gdb_step_until { regexp {test_name ""} {current ""} \
+			  { max_steps 10 } } {
+    if { $current == "" } {
+	set current "\}"
+    }
+    if { $test_name == "" } {
+	set test_name "stepping until regexp"
+    }
+
+    repeat_cmd_until "step" $current  $regexp  $test_name "10"
+}
+
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND is a stepping command
+#  CURRENT is a string matching the current location
+#  TARGET  is a string matching the target location
+#  TEST    is the test name
+#  MAX_STEPS is number of steps attempted before fail is emitted
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of 100 steps.
+#
+# TEST passes if the resulting location matches TARGET and fails
+# otherwise.
+#
+proc repeat_cmd_until { command current target test_name {max_steps 100} } {
+    global gdb_prompt
     if { $test_name == "" } {
 	set test_name "stepping until regexp"
     }
 
     set count 0
-    gdb_test_multiple "step" "$test_name" {
-	-re "$regexp\r\n$::gdb_prompt $" {
-	    pass $test_name
-	}
-	-re ".*$::gdb_prompt $" {
-	    if {$count < $max_steps} {
-		incr count
-		send_gdb "step\n"
+    gdb_test_multiple "$command" "$test_name" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < $max_steps } {
+		send_gdb "$command\n"
 		exp_continue
 	    } else {
-		fail $test_name
+		fail "$test_name"
 	    }
 	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test_name"
+	}
     }
 }
 

base-commit: 2c29b1ed19711fa2a16558015e5a6b46a09aefeb
-- 
2.35.3


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 13:43                                                                                     ` Tom de Vries
@ 2023-03-01 16:26                                                                                       ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-03-01 16:26 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro

Tom:

On Wed, 2023-03-01 at 14:43 +0100, Tom de Vries wrote:
> On 2/20/23 21:24, Carl Love wrote:
> > +if { [istarget "powerpc*-*-linux*"] } {
> > +    # GCC for PowerPC on linux does not support the -mindirect-
> > branch and
> > +    # -mfunction-return command line options.
> > +    return 0
> > +}
> > +
> 
> This bit is no longer necessary.
> 
> I've committed 2ef339e38f5 ("[gdb/testsuite] Require istarget x86*
> in 
> gdb.reverse/step-indirect-call-thunk.exp") which copied your fix
> from 
> commit 43127ae5714 ("Fix gdb.base/step-indirect-call-thunk.exp").

I update my source tree, without my patch applied, I verified the test
is not running on PowerPC.  I will drop the above change from my patch.

Thanks.

                  Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 14:03                                                                                     ` Tom de Vries
@ 2023-03-01 16:43                                                                                       ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-03-01 16:43 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro; +Cc: cel

Tom:

On Wed, 2023-03-01 at 15:03 +0100, Tom de Vries wrote:
> On 2/20/23 21:24, Carl Love wrote:
> >   # Step until the pattern REGEXP is found.  Step at most
> >   # MAX_STEPS times, but stop stepping once REGEXP is found.
> > -#
> > +# START matches current location
> >   # If REGEXP is found then a single pass is emitted, otherwise,
> > after
> >   # MAX_STEPS steps, a single fail is emitted.
> >   #
> >   # TEST_NAME is the name used in the pass/fail calls.
> >   
> > -proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
> > +proc gdb_step_until { regexp {test_name ""} {current ""} \
> > +			  { max_steps 10 } } {
> 
> I assume you meant CURRENT instead of START.


Yes, thanks for catching that.  Fixed.

                  Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 14:34                                                                                     ` Tom de Vries
@ 2023-03-01 20:39                                                                                       ` Carl Love
  2023-03-01 20:59                                                                                         ` [PATCH 0/2 " Carl Love
                                                                                                           ` (2 more replies)
  0 siblings, 3 replies; 105+ messages in thread
From: Carl Love @ 2023-03-01 20:39 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro; +Cc: cel

Tom:

On Wed, 2023-03-01 at 15:34 +0100, Tom de Vries wrote:
> On 2/20/23 21:24, Carl Love wrote:
> >   .../gdb.reverse/step-indirect-call-thunk.exp  |  55 ++---
> >   gdb/testsuite/lib/gdb.exp                     |  49 +++-
> 
> I think the changes in these two files are not really related to 
> $subject.  The only connection is that the newly introduced test-
> case 
> gdb.reverse/finish-reverse-next.exp uses repeat_cmd_until.
> 
> I propose to commit attached patch separately.

OK, I split the patch.  The first patch does the changes to the above
two files.  The second patch is the PowerPC fix that uses the new
library proceedure.

> 
> Carl, can you review the commit message?\

I reworked the commit message to make it flow better and remove the
comments about the movement of the proceedure.

I will post the two patch series.

                            Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH 0/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 20:39                                                                                       ` Carl Love
@ 2023-03-01 20:59                                                                                         ` Carl Love
  2023-03-01 20:59                                                                                         ` [PATCH 1/2] " Carl Love
  2023-03-01 20:59                                                                                         ` [PATCH 2/2 ] " Carl Love
  2 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-03-01 20:59 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro; +Cc: cel

Tom, Ulrich, Bruno, Pedro, GDB maintainers:

Per the feedback on the single patch to fix the gdb reverse-finish
command, I have split the patch into two patches.  

The first patch moves the step_until proceedure from gdb.reverse/step-
indirect-call-thunk.exp to gdb/testsuite/lib/gdb.exp and renames it
repeat_cmd_until.  The new repeat_cmd_until will be used in a new test
case for the second patch.

The second patch contains the changes to GDB to fix the behavior of the
reverse-finish command on PowerPC.

The changes to gdb.reverse/step-indirect-call-thunk.exp so the test
will not run on PowerPC were dropped per the comment from Tom stating
that commit 2ef339e38f5 ("[gdb/testsuite] Require istarget x86*
in gdb.reverse/step-indirect-call-thunk.exp") takes care of restricting
the test case to only run on X86.

The wording in file gdb/infcmd.c for the PowerPC fix was updated per
Bruno's feedback.

Thanks for all the feedback.  Please let me know if the patch series is
acceptable for mainline.

                             Carl 



^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH 1/2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 20:39                                                                                       ` Carl Love
  2023-03-01 20:59                                                                                         ` [PATCH 0/2 " Carl Love
@ 2023-03-01 20:59                                                                                         ` Carl Love
  2023-03-03 11:56                                                                                           ` Bruno Larsen
  2023-03-09 19:03                                                                                           ` Tom Tromey
  2023-03-01 20:59                                                                                         ` [PATCH 2/2 ] " Carl Love
  2 siblings, 2 replies; 105+ messages in thread
From: Carl Love @ 2023-03-01 20:59 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro; +Cc: cel

Tom, Ulrich, Bruno, Pedro, GDB maintainers:

This patch moves the step_until procedure from gdb.reverse/step-
indirect-call-thunk.exp to gdb/testsuite/lib/gdb.exp and renames it
repeat_cmd_until.  There are no functional changes as a result of this
change.

Patch tested on PowerPC and 5th generation X86 with no regression
failures.

                  Carl 

--------------------------------------------------------
Move step_until procedure

Procedure proc_step_until from test gdb.reverse/step-indirect-call-thunk.exp
is moved to lib/gdb.exp and renamed repeat_cmd_until.  The existing proceedure
gdb_step_until in lib/gdb.exp is simpler variant of the new repeat_cmd_until
proceedure.  The existing proceedure gdb_step_until is changed to just call
the new repeat_cmd_until proceedure with the command set to "step" and an
optional CURRENT string.  The default CURRENT string is set to "\}" to work
with the existing uses of proceedure gdb_step_until.
---
 .../gdb.reverse/step-indirect-call-thunk.exp  | 49 +++----------------
 gdb/testsuite/lib/gdb.exp                     | 49 ++++++++++++++-----
 2 files changed, 46 insertions(+), 52 deletions(-)

diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index f433efb11c2..e6c81b80a7b 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -38,39 +38,6 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
-proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
-}
-
 gdb_test_no_output "record"
 gdb_test "next" ".*" "record trace"
 
@@ -90,20 +57,20 @@ gdb_test "reverse-next" "apply\.2.*" \
     "reverse-step through thunks and over inc"
 
 # We can use instruction stepping to step into thunks.
-step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
-step_until "stepi" "indirect_thunk" "inc" \
+repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
+repeat_cmd_until "stepi" "indirect_thunk" "inc" \
     "stepi out of call thunk into inc"
 set alphanum_re "\[a-zA-Z0-9\]"
 set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
-step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
-step_until "stepi" "return_thunk" "apply" \
+repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
+repeat_cmd_until "stepi" "return_thunk" "apply" \
     "stepi out of return thunk back into apply"
 
-step_until "reverse-stepi" "apply" "return_thunk" \
+repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
     "reverse-stepi into return thunk"
-step_until "reverse-stepi" "return_thunk" "inc" \
+repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
     "reverse-stepi out of return thunk into inc"
-step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
+repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
     "reverse-stepi into call thunk"
-step_until "reverse-stepi" "indirect_thunk" "apply" \
+repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
     "reverse-stepi out of call thunk into apply"
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 19c782bea46..2b2a554f4c7 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9270,31 +9270,58 @@ gdb_caching_proc arm_cc_for_target {
 
 # Step until the pattern REGEXP is found.  Step at most
 # MAX_STEPS times, but stop stepping once REGEXP is found.
-#
+# CURRENT matches current location
 # If REGEXP is found then a single pass is emitted, otherwise, after
 # MAX_STEPS steps, a single fail is emitted.
 #
 # TEST_NAME is the name used in the pass/fail calls.
 
-proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
+proc gdb_step_until { regexp {test_name ""} {current ""} \
+			  { max_steps 10 } } {
+    if { $current == "" } {
+	set current "\}"
+    }
+    if { $test_name == "" } {
+	set test_name "stepping until regexp"
+    }
+
+    repeat_cmd_until "step" $current  $regexp  $test_name "10"
+}
+
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND is a stepping command
+#  CURRENT is a string matching the current location
+#  TARGET  is a string matching the target location
+#  TEST    is the test name
+#  MAX_STEPS is number of steps attempted before fail is emitted
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of 100 steps.
+#
+# TEST passes if the resulting location matches TARGET and fails
+# otherwise.
+#
+proc repeat_cmd_until { command current target test_name {max_steps 100} } {
+    global gdb_prompt
     if { $test_name == "" } {
 	set test_name "stepping until regexp"
     }
 
     set count 0
-    gdb_test_multiple "step" "$test_name" {
-	-re "$regexp\r\n$::gdb_prompt $" {
-	    pass $test_name
-	}
-	-re ".*$::gdb_prompt $" {
-	    if {$count < $max_steps} {
-		incr count
-		send_gdb "step\n"
+    gdb_test_multiple "$command" "$test_name" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < $max_steps } {
+		send_gdb "$command\n"
 		exp_continue
 	    } else {
-		fail $test_name
+		fail "$test_name"
 	    }
 	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test_name"
+	}
     }
 }
 
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 20:39                                                                                       ` Carl Love
  2023-03-01 20:59                                                                                         ` [PATCH 0/2 " Carl Love
  2023-03-01 20:59                                                                                         ` [PATCH 1/2] " Carl Love
@ 2023-03-01 20:59                                                                                         ` Carl Love
  2023-03-08 16:19                                                                                           ` [PING] " Carl Love
                                                                                                             ` (2 more replies)
  2 siblings, 3 replies; 105+ messages in thread
From: Carl Love @ 2023-03-01 20:59 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro; +Cc: cel

Tom, Ulrich, Bruno, Pedro, GDB maintainers:

This patch fixes the reverse-finish command on PowerPC.  The command
now works the same as on other architectures, specifically X86.  There
are no functional changes for other architectures.  The patch includes
a new testcase to verify the reverse-finish command works correctly
with the multiple entry points supported by PowerPC.


Patch tested on PowerPC and 5th generation X86 with no regression
failures.

                  Carl 

--------------------------------------------------------
PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp

PPC64 multiple entry points, a normal entry point and an alternate entry
point.  The alternate entry point is to setup the Table of Contents (TOC)
register before continuing at the normal entry point.  When the TOC is
already valid, the normal entry point is used, this is typically the case.
The alternate entry point is typically referred to as the global entry
point (GEP) in IBM.  The normal entry point is typically referred to as
the local entry point (LEP).

When GDB is executing the finish command in reverse, the function
finish_backward currently sets the break point at the alternate entry point.
This issue is if the function, when executing in the forward direction, entered
the function via the normal entry point, execution in the reverse direction
will never sees the break point at the alternate entry point.  In this case,
the reverse execution continues until the next break point is encountered thus
stopping at the wrong place.

This patch adds a new address to struct execution_control_state to hold the
address of the alternate entry point (GEP).  The finish_backwards function
is updated, if the stopping point is between the normal entry point (LEP)
and the end of the function, a breakpoint is set at the normal entry point.
If the stopping point is between the entry points, a breakpoint is set at
the alternate entry point.  This ensures that GDB will always stop at the
normal entry point.  If the function did enter via the alternate entry point,
GDB will detect that and continue to execute backwards in the function until
the alternate entry point is reached.

The patch fixes the behavior of the reverse-finish command on PowerPC to
match the behavior of the command on other platforms, specifically X86.
The patch does not change the behavior of the command on X86.

A new test is added to verify the reverse-finish command on PowerPC
correctly stops at the instruction where the function call is made.

The patch fixes 11 regression errors in test gdb.reverse/finish-precsave.exp
and 11 regression errors in test gdb.reverse/finish-reverse.exp.

The patch has been tested on Power 10 and X86 processor with no new
regression failures.
---
 gdb/infcmd.c                                  |  47 ++--
 gdb/infrun.c                                  |  24 ++
 .../gdb.reverse/finish-reverse-next.c         |  91 +++++++
 .../gdb.reverse/finish-reverse-next.exp       | 224 ++++++++++++++++++
 4 files changed, 369 insertions(+), 17 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index c369b795757..81c617448af 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm *sm)
      no way that a function up the stack can have a return address
      that's equal to its entry point.  */
 
-  if (sal.pc != pc)
-    {
-      frame_info_ptr frame = get_selected_frame (nullptr);
-      struct gdbarch *gdbarch = get_frame_arch (frame);
+  CORE_ADDR alt_entry_point = sal.pc;
+  CORE_ADDR entry_point = alt_entry_point;
+  frame_info_ptr frame = get_selected_frame (nullptr);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  if (gdbarch_skip_entrypoint_p (gdbarch))
+    /* Some architectures, like PowerPC use local and global entry points.
+       There is only one Entry Point (GEP = LEP) for other architectures.
+       The GEP is an alternate entry point.  The LEP is the normal entry point.
+       The value of entry_point was initialized to the alternate entry point
+       (GEP).  It will be adjusted to the normal entry point if the function
+       has two entry points.  */
+    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
 
-      /* Set a step-resume at the function's entry point.  Once that's
-	 hit, we'll do one more step backwards.  */
+  if  ((pc < alt_entry_point) || (pc > entry_point))
+    {
+      /* We are in the body of the function.  Set a breakpoint to go back to
+	 the normal entry point.  */
       symtab_and_line sr_sal;
-      sr_sal.pc = sal.pc;
+      sr_sal.pc = entry_point;
       sr_sal.pspace = get_frame_program_space (frame);
-      insert_step_resume_breakpoint_at_sal (gdbarch,
-					    sr_sal, null_frame_id);
-
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
+      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
+					    null_frame_id);
     }
+
   else
-    {
-      /* We're almost there -- we just need to back up by one more
-	 single-step.  */
-      tp->control.step_range_start = tp->control.step_range_end = 1;
-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
-    }
+    /* We are either at one of the entry points or between the entry points.
+       If we are not at the alt_entry point, go back to the alt_entry_point
+       If we at the normal entry point step back one instruction, when we
+       stop we will determine if we entered via the entry point or the
+       alternate entry point.  If we are at the alternate entry point,
+       single step back to the function call.  */
+    tp->control.step_range_start = tp->control.step_range_end = 1;
+
+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
 /* finish_forward -- helper function for finish_command.  FRAME is the
diff --git a/gdb/infrun.c b/gdb/infrun.c
index ab77300f1ff..ca2fc02898a 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1938,6 +1938,7 @@ struct execution_control_state
 
   struct target_waitstatus ws;
   int stop_func_filled_in = 0;
+  CORE_ADDR stop_func_alt_start = 0;
   CORE_ADDR stop_func_start = 0;
   CORE_ADDR stop_func_end = 0;
   const char *stop_func_name = nullptr;
@@ -4822,6 +4823,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 	  ecs->stop_func_start
 	    += gdbarch_deprecated_function_start_offset (gdbarch);
 
+	  /* PowerPC functions have a Local Entry Point (LEP) and a Global
+	     Entry Point (GEP).  There is only one Entry Point (GEP = LEP) for
+	     other architectures.  */
+	  ecs->stop_func_alt_start = ecs->stop_func_start;
+
 	  if (gdbarch_skip_entrypoint_p (gdbarch))
 	    ecs->stop_func_start
 	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
@@ -7411,6 +7417,24 @@ process_event_stop_test (struct execution_control_state *ecs)
 	}
     }
 
+  if (execution_direction == EXEC_REVERSE
+      && ecs->event_thread->control.proceed_to_finish
+      && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
+      && ecs->event_thread->stop_pc () < ecs->stop_func_start)
+    {
+      /* We are executing the reverse-finish command.
+	 If the system supports multiple entry points and we are finishing a
+	 function in reverse.   If we are between the entry points singe-step
+	 back to the alternate entry point.  If we are at the alternate entry
+	 point -- just   need to back up by one more single-step, which
+	 should take us back to the function call.  */
+      ecs->event_thread->control.step_range_start
+	= ecs->event_thread->control.step_range_end = 1;
+      keep_going (ecs);
+      return;
+
+    }
+
   if (ecs->event_thread->control.step_range_end == 1)
     {
       /* It is stepi or nexti.  We always want to stop stepping after
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
new file mode 100644
index 00000000000..e95ee8e33a6
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -0,0 +1,91 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The reverse finish command should return from a function and stop on
+   the first instruction of the source line where the function call is made.
+   Specifically, the behavior should match doing a reverse next from the
+   first instruction in the function.  GDB should only require one reverse
+   step or next statement to reach the previous source code line.
+
+   This test verifies the fix for gdb bugzilla:
+
+   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+   PowerPC supports two entry points to a function.  The normal entry point
+   is called the local entry point (LEP).  The alternate entry point is called
+   the global entry point (GEP).  The GEP is only used if the table of
+   contents (TOC) value stored in register r2 needs to be setup prior to
+   execution starting at the LEP.  A function call via a function pointer
+   will entry via the GEP.  A normal function call will enter via the LEP.
+
+   This test has been expanded to include tests to verify the reverse-finish
+   command works properly if the function is called via the GEP.  The original
+   test only verified the reverse-finish command for a normal call that used
+   the LEP.  */
+
+int
+function2 (int a, int b)
+{
+  int ret = 0;
+  ret = ret + a + b;
+  return ret;
+}
+
+int
+function1 (int a, int b)   // FUNCTION1
+{
+  int ret = 0;
+  int (*funp) (int, int) = &function2;
+  /* The assembly code for this function when compiled for PowerPC is as
+     follows:
+
+     0000000010000758 <function1>:
+     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
+     1000075c:	00 7f 42 38 	addi    r2,r2,32512
+     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
+     10000764:	10 00 01 f8 	std     r0,16(r1)
+     ....
+
+     When the function is called on PowerPC with function1 (a, b) the call
+     enters at the Local Entry Point (LEP).  When the function is called via
+     a function pointer, the Global Entry Point (GEP) for function1 is used.
+     The GEP sets up register 2 before reaching the LEP.
+  */
+  ret = funp (a + 1, b + 2);
+  return ret;
+}
+
+int
+main(int argc, char* argv[])
+{
+  int a, b;
+  int (*funp) (int, int) = &function1;
+
+  /* Call function via Local Entry Point (LEP).  */
+
+  a = 1;
+  b = 5;
+
+  function1 (a, b);   // CALL VIA LEP
+
+  /* Call function via Global Entry Point (GEP).  */
+  a = 10;
+  b = 50;
+
+  funp (a, b);        // CALL VIA GEP
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
new file mode 100644
index 00000000000..1f53b649a7d
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -0,0 +1,224 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+# PowerPC supports two entry points to a function.  The normal entry point
+# is called the local entry point (LEP).  The alternate entry point is called
+# the global entry point (GEP).  A function call via a function pointer
+# will entry via the GEP.  A normal function call will enter via the LEP.
+#
+# This test has been expanded to include tests to verify the reverse-finish
+# command works properly if the function is called via the GEP.  The original
+# test only verified the reverse-finish command for a normal call that used
+# the LEP.
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+### TEST 1: reverse finish from the entry point instruction (LEP) in
+### function1 when called using the normal entry point (LEP).
+
+# Set breakpoint at call to function1 in main.
+set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function1
+repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call" "100"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from LEP "
+gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
+    "reverse next 1 LEP entry point function call from LEP"
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call from LEP"
+
+
+gdb_test "reverse-continue" ".*" "setup for test 2"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+### TEST 2: reverse finish from the body of function1.
+
+# Set breakpoint at call to function1 in main.
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+# do a step instruction to get to the body of the function
+gdb_test "step" ".*int ret = 0;.*" "step test 1"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from function body"
+gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse next 1 LEP from function body"
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse next 2 at b = 5, from function body"
+
+gdb_test "reverse-continue" ".*" "setup for test 3"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test2"
+gdb_test_no_output "record" "turn on process record for test3"
+
+
+### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP"
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP entry point function call from GEP"
+gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, call from GEP"
+
+gdb_test "reverse-continue" ".*" "setup for test 4"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test3"
+gdb_test_no_output "record" "turn on process record for test4"
+
+### TEST 4: reverse finish from between the GEP and LEP in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp again" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call again"
+
+# do one more stepi so we are between the GEP and LEP.
+gdb_test "stepi" "{" "stepi to between GEP and LEP"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP again"
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP entry point function call from GEP again"
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next 2 at b = 50, call from GEP again"
+
+gdb_test "reverse-continue" ".*" "setup for test 5"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test4"
+gdb_test_no_output "record" "turn on process record for test5"
+
+
+### TEST 5: reverse finish from the body of function 1 when calling using the
+### alternate entrypoint (GEP).
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of funp call" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# Step into body of funp, called via GEP.
+gdb_test "step" ".*int ret = 0;.*" "step test 2"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "reverse-finish function1 GEP call, from function body  "
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP call from function body"
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next 2 at b = 50 from function body"
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 20:59                                                                                         ` [PATCH 1/2] " Carl Love
@ 2023-03-03 11:56                                                                                           ` Bruno Larsen
  2023-03-08 16:19                                                                                             ` [PING] " Carl Love
  2023-03-09 19:03                                                                                           ` Tom Tromey
  1 sibling, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-03-03 11:56 UTC (permalink / raw)
  To: Carl Love, Tom de Vries, Ulrich Weigand, gdb-patches, pedro

On 01/03/2023 21:59, Carl Love wrote:
> Tom, Ulrich, Bruno, Pedro, GDB maintainers:
>
> This patch moves the step_until procedure from gdb.reverse/step-
> indirect-call-thunk.exp to gdb/testsuite/lib/gdb.exp and renames it
> repeat_cmd_until.  There are no functional changes as a result of this
> change.
>
> Patch tested on PowerPC and 5th generation X86 with no regression
> failures.
>
>                    Carl
>
> --------------------------------------------------------
The changes seem simple enough and dont change any outputs neither for 
gcc nor clang testing, so:
Reviewed-By: Bruno Larsen <blarsen@redhat.com>

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PING] Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 20:59                                                                                         ` [PATCH 2/2 ] " Carl Love
@ 2023-03-08 16:19                                                                                           ` Carl Love
  2023-03-09 16:09                                                                                             ` Carl Love
  2023-03-13 14:16                                                                                           ` Ulrich Weigand
  2023-03-24 17:23                                                                                           ` [PATCH 2/2 ] " Simon Marchi
  2 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-08 16:19 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro; +Cc: cel

GCC developers:

Ping.  Just wondering if someone could review this patch for
me.  Thanks.

                Carl 

On Wed, 2023-03-01 at 12:59 -0800, Carl Love wrote:
> Tom, Ulrich, Bruno, Pedro, GDB maintainers:
> 
> This patch fixes the reverse-finish command on PowerPC.  The command
> now works the same as on other architectures, specifically
> X86.  There
> are no functional changes for other architectures.  The patch
> includes
> a new testcase to verify the reverse-finish command works correctly
> with the multiple entry points supported by PowerPC.
> 
> 
> Patch tested on PowerPC and 5th generation X86 with no regression
> failures.
> 
>                   Carl 
> 
> --------------------------------------------------------
> PowerPC: fix for gdb.reverse/finish-precsave.exp and
> gdb.reverse/finish-reverse.exp
> 
> PPC64 multiple entry points, a normal entry point and an alternate
> entry
> point.  The alternate entry point is to setup the Table of Contents
> (TOC)
> register before continuing at the normal entry point.  When the TOC
> is
> already valid, the normal entry point is used, this is typically the
> case.
> The alternate entry point is typically referred to as the global
> entry
> point (GEP) in IBM.  The normal entry point is typically referred to
> as
> the local entry point (LEP).
> 
> When GDB is executing the finish command in reverse, the function
> finish_backward currently sets the break point at the alternate entry
> point.
> This issue is if the function, when executing in the forward
> direction, entered
> the function via the normal entry point, execution in the reverse
> direction
> will never sees the break point at the alternate entry point.  In
> this case,
> the reverse execution continues until the next break point is
> encountered thus
> stopping at the wrong place.
> 
> This patch adds a new address to struct execution_control_state to
> hold the
> address of the alternate entry point (GEP).  The finish_backwards
> function
> is updated, if the stopping point is between the normal entry point
> (LEP)
> and the end of the function, a breakpoint is set at the normal entry
> point.
> If the stopping point is between the entry points, a breakpoint is
> set at
> the alternate entry point.  This ensures that GDB will always stop at
> the
> normal entry point.  If the function did enter via the alternate
> entry point,
> GDB will detect that and continue to execute backwards in the
> function until
> the alternate entry point is reached.
> 
> The patch fixes the behavior of the reverse-finish command on PowerPC
> to
> match the behavior of the command on other platforms, specifically
> X86.
> The patch does not change the behavior of the command on X86.
> 
> A new test is added to verify the reverse-finish command on PowerPC
> correctly stops at the instruction where the function call is made.
> 
> The patch fixes 11 regression errors in test gdb.reverse/finish-
> precsave.exp
> and 11 regression errors in test gdb.reverse/finish-reverse.exp.
> 
> The patch has been tested on Power 10 and X86 processor with no new
> regression failures.
> ---
>  gdb/infcmd.c                                  |  47 ++--
>  gdb/infrun.c                                  |  24 ++
>  .../gdb.reverse/finish-reverse-next.c         |  91 +++++++
>  .../gdb.reverse/finish-reverse-next.exp       | 224
> ++++++++++++++++++
>  4 files changed, 369 insertions(+), 17 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
>  create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> 
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index c369b795757..81c617448af 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm
> *sm)
>       no way that a function up the stack can have a return address
>       that's equal to its entry point.  */
> 
> -  if (sal.pc != pc)
> -    {
> -      frame_info_ptr frame = get_selected_frame (nullptr);
> -      struct gdbarch *gdbarch = get_frame_arch (frame);
> +  CORE_ADDR alt_entry_point = sal.pc;
> +  CORE_ADDR entry_point = alt_entry_point;
> +  frame_info_ptr frame = get_selected_frame (nullptr);
> +  struct gdbarch *gdbarch = get_frame_arch (frame);
> +
> +  if (gdbarch_skip_entrypoint_p (gdbarch))
> +    /* Some architectures, like PowerPC use local and global entry
> points.
> +       There is only one Entry Point (GEP = LEP) for other
> architectures.
> +       The GEP is an alternate entry point.  The LEP is the normal
> entry point.
> +       The value of entry_point was initialized to the alternate
> entry point
> +       (GEP).  It will be adjusted to the normal entry point if the
> function
> +       has two entry points.  */
> +    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
> 
> -      /* Set a step-resume at the function's entry point.  Once
> that's
> -	 hit, we'll do one more step backwards.  */
> +  if  ((pc < alt_entry_point) || (pc > entry_point))
> +    {
> +      /* We are in the body of the function.  Set a breakpoint to go
> back to
> +	 the normal entry point.  */
>        symtab_and_line sr_sal;
> -      sr_sal.pc = sal.pc;
> +      sr_sal.pc = entry_point;
>        sr_sal.pspace = get_frame_program_space (frame);
> -      insert_step_resume_breakpoint_at_sal (gdbarch,
> -					    sr_sal, null_frame_id);
> -
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> +      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
> +					    null_frame_id);
>      }
> +
>    else
> -    {
> -      /* We're almost there -- we just need to back up by one more
> -	 single-step.  */
> -      tp->control.step_range_start = tp->control.step_range_end = 1;
> -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> -    }
> +    /* We are either at one of the entry points or between the entry
> points.
> +       If we are not at the alt_entry point, go back to the
> alt_entry_point
> +       If we at the normal entry point step back one instruction,
> when we
> +       stop we will determine if we entered via the entry point or
> the
> +       alternate entry point.  If we are at the alternate entry
> point,
> +       single step back to the function call.  */
> +    tp->control.step_range_start = tp->control.step_range_end = 1;
> +
> +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>  }
> 
>  /* finish_forward -- helper function for finish_command.  FRAME is
> the
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index ab77300f1ff..ca2fc02898a 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -1938,6 +1938,7 @@ struct execution_control_state
> 
>    struct target_waitstatus ws;
>    int stop_func_filled_in = 0;
> +  CORE_ADDR stop_func_alt_start = 0;
>    CORE_ADDR stop_func_start = 0;
>    CORE_ADDR stop_func_end = 0;
>    const char *stop_func_name = nullptr;
> @@ -4822,6 +4823,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
>  	  ecs->stop_func_start
>  	    += gdbarch_deprecated_function_start_offset (gdbarch);
> 
> +	  /* PowerPC functions have a Local Entry Point (LEP) and a
> Global
> +	     Entry Point (GEP).  There is only one Entry Point (GEP =
> LEP) for
> +	     other architectures.  */
> +	  ecs->stop_func_alt_start = ecs->stop_func_start;
> +
>  	  if (gdbarch_skip_entrypoint_p (gdbarch))
>  	    ecs->stop_func_start
>  	      = gdbarch_skip_entrypoint (gdbarch, ecs-
> >stop_func_start);
> @@ -7411,6 +7417,24 @@ process_event_stop_test (struct
> execution_control_state *ecs)
>  	}
>      }
> 
> +  if (execution_direction == EXEC_REVERSE
> +      && ecs->event_thread->control.proceed_to_finish
> +      && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
> +      && ecs->event_thread->stop_pc () < ecs->stop_func_start)
> +    {
> +      /* We are executing the reverse-finish command.
> +	 If the system supports multiple entry points and we are
> finishing a
> +	 function in reverse.   If we are between the entry points
> singe-step
> +	 back to the alternate entry point.  If we are at the alternate
> entry
> +	 point -- just   need to back up by one more single-step, which
> +	 should take us back to the function call.  */
> +      ecs->event_thread->control.step_range_start
> +	= ecs->event_thread->control.step_range_end = 1;
> +      keep_going (ecs);
> +      return;
> +
> +    }
> +
>    if (ecs->event_thread->control.step_range_end == 1)
>      {
>        /* It is stepi or nexti.  We always want to stop stepping
> after
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> new file mode 100644
> index 00000000000..e95ee8e33a6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> @@ -0,0 +1,91 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2012-2023 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or
> modify
> +   it under the terms of the GNU General Public License as published
> by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <
> http://www.gnu.org/licenses/>.  */
> +
> +/* The reverse finish command should return from a function and stop
> on
> +   the first instruction of the source line where the function call
> is made.
> +   Specifically, the behavior should match doing a reverse next from
> the
> +   first instruction in the function.  GDB should only require one
> reverse
> +   step or next statement to reach the previous source code line.
> +
> +   This test verifies the fix for gdb bugzilla:
> +
> +   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +   PowerPC supports two entry points to a function.  The normal
> entry point
> +   is called the local entry point (LEP).  The alternate entry point
> is called
> +   the global entry point (GEP).  The GEP is only used if the table
> of
> +   contents (TOC) value stored in register r2 needs to be setup
> prior to
> +   execution starting at the LEP.  A function call via a function
> pointer
> +   will entry via the GEP.  A normal function call will enter via
> the LEP.
> +
> +   This test has been expanded to include tests to verify the
> reverse-finish
> +   command works properly if the function is called via the
> GEP.  The original
> +   test only verified the reverse-finish command for a normal call
> that used
> +   the LEP.  */
> +
> +int
> +function2 (int a, int b)
> +{
> +  int ret = 0;
> +  ret = ret + a + b;
> +  return ret;
> +}
> +
> +int
> +function1 (int a, int b)   // FUNCTION1
> +{
> +  int ret = 0;
> +  int (*funp) (int, int) = &function2;
> +  /* The assembly code for this function when compiled for PowerPC
> is as
> +     follows:
> +
> +     0000000010000758 <function1>:
> +     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
> +     1000075c:	00 7f 42 38 	addi    r2,r2,32512
> +     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
> +     10000764:	10 00 01 f8 	std     r0,16(r1)
> +     ....
> +
> +     When the function is called on PowerPC with function1 (a, b)
> the call
> +     enters at the Local Entry Point (LEP).  When the function is
> called via
> +     a function pointer, the Global Entry Point (GEP) for function1
> is used.
> +     The GEP sets up register 2 before reaching the LEP.
> +  */
> +  ret = funp (a + 1, b + 2);
> +  return ret;
> +}
> +
> +int
> +main(int argc, char* argv[])
> +{
> +  int a, b;
> +  int (*funp) (int, int) = &function1;
> +
> +  /* Call function via Local Entry Point (LEP).  */
> +
> +  a = 1;
> +  b = 5;
> +
> +  function1 (a, b);   // CALL VIA LEP
> +
> +  /* Call function via Global Entry Point (GEP).  */
> +  a = 10;
> +  b = 50;
> +
> +  funp (a, b);        // CALL VIA GEP
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> new file mode 100644
> index 00000000000..1f53b649a7d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> @@ -0,0 +1,224 @@
> +# Copyright 2008-2023 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or
> modify
> +# it under the terms of the GNU General Public License as published
> by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <
> http://www.gnu.org/licenses/>.  */
> +
> +# This file is part of the GDB testsuite.  It tests reverse
> stepping.
> +# Lots of code borrowed from "step-test.exp".
> +
> +# The reverse finish command should return from a function and stop
> on
> +# the first instruction of the source line where the function call
> is made.
> +# Specifically, the behavior should match doing a reverse next from
> the
> +# first instruction in the function.  GDB should only take one
> reverse step
> +# or next statement to reach the previous source code line.
> +
> +# This testcase verifies the reverse-finish command stops at the
> first
> +# instruction in the source code line where the function was
> called.  There
> +# are two scenarios that must be checked:
> +#   1) gdb is at the entry point instruction for the function
> +#   2) gdb is in the body of the function.
> +
> +# This test verifies the fix for gdb bugzilla:
> +#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +# PowerPC supports two entry points to a function.  The normal entry
> point
> +# is called the local entry point (LEP).  The alternate entry point
> is called
> +# the global entry point (GEP).  A function call via a function
> pointer
> +# will entry via the GEP.  A normal function call will enter via the
> LEP.
> +#
> +# This test has been expanded to include tests to verify the
> reverse-finish
> +# command works properly if the function is called via the GEP.  The
> original
> +# test only verified the reverse-finish command for a normal call
> that used
> +# the LEP.
> +
> +if ![supports_reverse] {
> +    return
> +}
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] }
> {
> +    return -1
> +}
> +
> +runto_main
> +set target_remote [gdb_is_target_remote]
> +
> +if [supports_process_record] {
> +    # Activate process record/replay.
> +    gdb_test_no_output "record" "turn on process record for test1"
> +}
> +
> +
> +### TEST 1: reverse finish from the entry point instruction (LEP) in
> +### function1 when called using the normal entry point (LEP).
> +
> +# Set breakpoint at call to function1 in main.
> +set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into
> function" \
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function1
> +repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1
> call" "100"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA
> LEP.*" \
> +    "reverse-finish function1 LEP call from LEP "
> +gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP"
> \
> +    "reverse next 1 LEP entry point function call from LEP"
> +gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call
> from LEP"
> +
> +
> +gdb_test "reverse-continue" ".*" "setup for test 2"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test1"
> +gdb_test_no_output "record" "turn on process record for test2"
> +
> +
> +### TEST 2: reverse finish from the body of function1.
> +
> +# Set breakpoint at call to function1 in main.
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "at function1 entry point instruction to step to body of
> function" \
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
> +
> +# do a step instruction to get to the body of the function
> +gdb_test "step" ".*int ret = 0;.*" "step test 1"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA
> LEP.*" \
> +    "reverse-finish function1 LEP call from function body"
> +gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA
> LEP.*" \
> +    "reverse next 1 LEP from function body"
> +gdb_test "reverse-next" ".*b = 5;.*" \
> +    "reverse next 2 at b = 5, from function body"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 3"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test2"
> +gdb_test_no_output "record" "turn on process record for test3"
> +
> +
> +### TEST 3: reverse finish from the alternate entry point
> instruction (GEP) in
> +### function1 when called using the alternate entry point (GEP).
> +
> +# Set breakpoint at call to funp in main.
> +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into
> funp" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function.
> +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "function1 GEP call call from GEP"
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP entry point function call from GEP"
> +gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50,
> call from GEP"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 4"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test3"
> +gdb_test_no_output "record" "turn on process record for test4"
> +
> +### TEST 4: reverse finish from between the GEP and LEP in
> +### function1 when called using the alternate entry point (GEP).
> +
> +# Set breakpoint at call to funp in main.
> +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into funp
> again" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# stepi until we see "{" indicating we entered function.
> +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call
> again"
> +
> +# do one more stepi so we are between the GEP and LEP.
> +gdb_test "stepi" "{" "stepi to between GEP and LEP"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "function1 GEP call call from GEP again"
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP entry point function call from GEP again"
> +gdb_test "reverse-next" ".*b = 50;.*" \
> +    "reverse next 2 at b = 50, call from GEP again"
> +
> +gdb_test "reverse-continue" ".*" "setup for test 5"
> +
> +# Turn off record to clear logs and turn on again
> +gdb_test "record stop"  "Process record is stopped.*" \
> +    "turn off process record for test4"
> +gdb_test_no_output "record" "turn on process record for test5"
> +
> +
> +### TEST 5: reverse finish from the body of function 1 when calling
> using the
> +### alternate entrypoint (GEP).
> +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> +
> +# Continue to break point at funp call.
> +gdb_continue_to_breakpoint \
> +    "at function1 entry point instruction to step to body of funp
> call" \
> +    ".*$srcfile:$bp_GEP_test\r\n.*"
> +
> +# Step into body of funp, called via GEP.
> +gdb_test "step" ".*int ret = 0;.*" "step test 2"
> +
> +# The reverse-finish command should stop on the function call
> instruction
> +# which is the last instruction in the source code line.  A reverse-
> next
> +# instruction should then stop at the first instruction in the same
> source
> +# code line.  Another revers-next instruction stops at the previous
> source
> +# code line.
> +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> +    "reverse-finish function1 GEP call, from function body  "
> +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +    "reverse next 1 GEP call from function body"
> +gdb_test "reverse-next" ".*b = 50;.*" \
> +    "reverse next 2 at b = 50 from function body"


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PING] Re: [PATCH 1/2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-03 11:56                                                                                           ` Bruno Larsen
@ 2023-03-08 16:19                                                                                             ` Carl Love
  2023-03-09 16:09                                                                                               ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-08 16:19 UTC (permalink / raw)
  To: Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches, pedro; +Cc: cel

GCC developers:

Ping.  Just wondering if anyone else has had a chance to review this
patch.  Thanks.

                Carl 

On Fri, 2023-03-03 at 12:56 +0100, Bruno Larsen wrote:
> On 01/03/2023 21:59, Carl Love wrote:
> > Tom, Ulrich, Bruno, Pedro, GDB maintainers:
> > 
> > This patch moves the step_until procedure from gdb.reverse/step-
> > indirect-call-thunk.exp to gdb/testsuite/lib/gdb.exp and renames it
> > repeat_cmd_until.  There are no functional changes as a result of
> > this
> > change.
> > 
> > Patch tested on PowerPC and 5th generation X86 with no regression
> > failures.
> > 
> >                    Carl
> > 
> > --------------------------------------------------------
> The changes seem simple enough and dont change any outputs neither
> for 
> gcc nor clang testing, so:
> Reviewed-By: Bruno Larsen <blarsen@redhat.com>
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PING] Re: [PATCH 1/2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-08 16:19                                                                                             ` [PING] " Carl Love
@ 2023-03-09 16:09                                                                                               ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-03-09 16:09 UTC (permalink / raw)
  To: Bruno Larsen, Tom de Vries, Ulrich Weigand, gdb-patches, pedro; +Cc: cel

Oops, typo that should read GDB developers.  Sorry about that.

On Wed, 2023-03-08 at 08:19 -0800, Carl Love wrote:
> GCC developers:
> 
> Ping.  Just wondering if anyone else has had a chance to review this
> patch.  Thanks.
> 
>                 Carl 
> 
> On Fri, 2023-03-03 at 12:56 +0100, Bruno Larsen wrote:
> > On 01/03/2023 21:59, Carl Love wrote:
> > > Tom, Ulrich, Bruno, Pedro, GDB maintainers:
> > > 
> > > This patch moves the step_until procedure from gdb.reverse/step-
> > > indirect-call-thunk.exp to gdb/testsuite/lib/gdb.exp and renames
> > > it
> > > repeat_cmd_until.  There are no functional changes as a result of
> > > this
> > > change.
> > > 
> > > Patch tested on PowerPC and 5th generation X86 with no regression
> > > failures.
> > > 
> > >                    Carl
> > > 
> > > --------------------------------------------------------
> > The changes seem simple enough and dont change any outputs neither
> > for 
> > gcc nor clang testing, so:
> > Reviewed-By: Bruno Larsen <blarsen@redhat.com>
> > 
> 
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PING] Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-08 16:19                                                                                           ` [PING] " Carl Love
@ 2023-03-09 16:09                                                                                             ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-03-09 16:09 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro; +Cc: cel

Oops, that should have read GDB developers.  Sorry about that.

On Wed, 2023-03-08 at 08:19 -0800, Carl Love wrote:
> GCC developers:
> 
> Ping.  Just wondering if someone could review this patch for
> me.  Thanks.
> 
>                 Carl 
> 
> On Wed, 2023-03-01 at 12:59 -0800, Carl Love wrote:
> > Tom, Ulrich, Bruno, Pedro, GDB maintainers:
> > 
> > This patch fixes the reverse-finish command on PowerPC.  The
> > command
> > now works the same as on other architectures, specifically
> > X86.  There
> > are no functional changes for other architectures.  The patch
> > includes
> > a new testcase to verify the reverse-finish command works correctly
> > with the multiple entry points supported by PowerPC.
> > 
> > 
> > Patch tested on PowerPC and 5th generation X86 with no regression
> > failures.
> > 
> >                   Carl 
> > 
> > --------------------------------------------------------
> > PowerPC: fix for gdb.reverse/finish-precsave.exp and
> > gdb.reverse/finish-reverse.exp
> > 
> > PPC64 multiple entry points, a normal entry point and an alternate
> > entry
> > point.  The alternate entry point is to setup the Table of Contents
> > (TOC)
> > register before continuing at the normal entry point.  When the TOC
> > is
> > already valid, the normal entry point is used, this is typically
> > the
> > case.
> > The alternate entry point is typically referred to as the global
> > entry
> > point (GEP) in IBM.  The normal entry point is typically referred
> > to
> > as
> > the local entry point (LEP).
> > 
> > When GDB is executing the finish command in reverse, the function
> > finish_backward currently sets the break point at the alternate
> > entry
> > point.
> > This issue is if the function, when executing in the forward
> > direction, entered
> > the function via the normal entry point, execution in the reverse
> > direction
> > will never sees the break point at the alternate entry point.  In
> > this case,
> > the reverse execution continues until the next break point is
> > encountered thus
> > stopping at the wrong place.
> > 
> > This patch adds a new address to struct execution_control_state to
> > hold the
> > address of the alternate entry point (GEP).  The finish_backwards
> > function
> > is updated, if the stopping point is between the normal entry point
> > (LEP)
> > and the end of the function, a breakpoint is set at the normal
> > entry
> > point.
> > If the stopping point is between the entry points, a breakpoint is
> > set at
> > the alternate entry point.  This ensures that GDB will always stop
> > at
> > the
> > normal entry point.  If the function did enter via the alternate
> > entry point,
> > GDB will detect that and continue to execute backwards in the
> > function until
> > the alternate entry point is reached.
> > 
> > The patch fixes the behavior of the reverse-finish command on
> > PowerPC
> > to
> > match the behavior of the command on other platforms, specifically
> > X86.
> > The patch does not change the behavior of the command on X86.
> > 
> > A new test is added to verify the reverse-finish command on PowerPC
> > correctly stops at the instruction where the function call is made.
> > 
> > The patch fixes 11 regression errors in test gdb.reverse/finish-
> > precsave.exp
> > and 11 regression errors in test gdb.reverse/finish-reverse.exp.
> > 
> > The patch has been tested on Power 10 and X86 processor with no new
> > regression failures.
> > ---
> >  gdb/infcmd.c                                  |  47 ++--
> >  gdb/infrun.c                                  |  24 ++
> >  .../gdb.reverse/finish-reverse-next.c         |  91 +++++++
> >  .../gdb.reverse/finish-reverse-next.exp       | 224
> > ++++++++++++++++++
> >  4 files changed, 369 insertions(+), 17 deletions(-)
> >  create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
> >  create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-
> > next.exp
> > 
> > diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> > index c369b795757..81c617448af 100644
> > --- a/gdb/infcmd.c
> > +++ b/gdb/infcmd.c
> > @@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm
> > *sm)
> >       no way that a function up the stack can have a return address
> >       that's equal to its entry point.  */
> > 
> > -  if (sal.pc != pc)
> > -    {
> > -      frame_info_ptr frame = get_selected_frame (nullptr);
> > -      struct gdbarch *gdbarch = get_frame_arch (frame);
> > +  CORE_ADDR alt_entry_point = sal.pc;
> > +  CORE_ADDR entry_point = alt_entry_point;
> > +  frame_info_ptr frame = get_selected_frame (nullptr);
> > +  struct gdbarch *gdbarch = get_frame_arch (frame);
> > +
> > +  if (gdbarch_skip_entrypoint_p (gdbarch))
> > +    /* Some architectures, like PowerPC use local and global entry
> > points.
> > +       There is only one Entry Point (GEP = LEP) for other
> > architectures.
> > +       The GEP is an alternate entry point.  The LEP is the normal
> > entry point.
> > +       The value of entry_point was initialized to the alternate
> > entry point
> > +       (GEP).  It will be adjusted to the normal entry point if
> > the
> > function
> > +       has two entry points.  */
> > +    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
> > 
> > -      /* Set a step-resume at the function's entry point.  Once
> > that's
> > -	 hit, we'll do one more step backwards.  */
> > +  if  ((pc < alt_entry_point) || (pc > entry_point))
> > +    {
> > +      /* We are in the body of the function.  Set a breakpoint to
> > go
> > back to
> > +	 the normal entry point.  */
> >        symtab_and_line sr_sal;
> > -      sr_sal.pc = sal.pc;
> > +      sr_sal.pc = entry_point;
> >        sr_sal.pspace = get_frame_program_space (frame);
> > -      insert_step_resume_breakpoint_at_sal (gdbarch,
> > -					    sr_sal, null_frame_id);
> > -
> > -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> > +      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
> > +					    null_frame_id);
> >      }
> > +
> >    else
> > -    {
> > -      /* We're almost there -- we just need to back up by one more
> > -	 single-step.  */
> > -      tp->control.step_range_start = tp->control.step_range_end =
> > 1;
> > -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> > -    }
> > +    /* We are either at one of the entry points or between the
> > entry
> > points.
> > +       If we are not at the alt_entry point, go back to the
> > alt_entry_point
> > +       If we at the normal entry point step back one instruction,
> > when we
> > +       stop we will determine if we entered via the entry point or
> > the
> > +       alternate entry point.  If we are at the alternate entry
> > point,
> > +       single step back to the function call.  */
> > +    tp->control.step_range_start = tp->control.step_range_end = 1;
> > +
> > +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> >  }
> > 
> >  /* finish_forward -- helper function for finish_command.  FRAME is
> > the
> > diff --git a/gdb/infrun.c b/gdb/infrun.c
> > index ab77300f1ff..ca2fc02898a 100644
> > --- a/gdb/infrun.c
> > +++ b/gdb/infrun.c
> > @@ -1938,6 +1938,7 @@ struct execution_control_state
> > 
> >    struct target_waitstatus ws;
> >    int stop_func_filled_in = 0;
> > +  CORE_ADDR stop_func_alt_start = 0;
> >    CORE_ADDR stop_func_start = 0;
> >    CORE_ADDR stop_func_end = 0;
> >    const char *stop_func_name = nullptr;
> > @@ -4822,6 +4823,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
> >  	  ecs->stop_func_start
> >  	    += gdbarch_deprecated_function_start_offset (gdbarch);
> > 
> > +	  /* PowerPC functions have a Local Entry Point (LEP) and a
> > Global
> > +	     Entry Point (GEP).  There is only one Entry Point (GEP =
> > LEP) for
> > +	     other architectures.  */
> > +	  ecs->stop_func_alt_start = ecs->stop_func_start;
> > +
> >  	  if (gdbarch_skip_entrypoint_p (gdbarch))
> >  	    ecs->stop_func_start
> >  	      = gdbarch_skip_entrypoint (gdbarch, ecs-
> > > stop_func_start);
> > @@ -7411,6 +7417,24 @@ process_event_stop_test (struct
> > execution_control_state *ecs)
> >  	}
> >      }
> > 
> > +  if (execution_direction == EXEC_REVERSE
> > +      && ecs->event_thread->control.proceed_to_finish
> > +      && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
> > +      && ecs->event_thread->stop_pc () < ecs->stop_func_start)
> > +    {
> > +      /* We are executing the reverse-finish command.
> > +	 If the system supports multiple entry points and we are
> > finishing a
> > +	 function in reverse.   If we are between the entry points
> > singe-step
> > +	 back to the alternate entry point.  If we are at the alternate
> > entry
> > +	 point -- just   need to back up by one more single-step, which
> > +	 should take us back to the function call.  */
> > +      ecs->event_thread->control.step_range_start
> > +	= ecs->event_thread->control.step_range_end = 1;
> > +      keep_going (ecs);
> > +      return;
> > +
> > +    }
> > +
> >    if (ecs->event_thread->control.step_range_end == 1)
> >      {
> >        /* It is stepi or nexti.  We always want to stop stepping
> > after
> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > new file mode 100644
> > index 00000000000..e95ee8e33a6
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
> > @@ -0,0 +1,91 @@
> > +/* This testcase is part of GDB, the GNU debugger.
> > +
> > +   Copyright 2012-2023 Free Software Foundation, Inc.
> > +
> > +   This program is free software; you can redistribute it and/or
> > modify
> > +   it under the terms of the GNU General Public License as
> > published
> > by
> > +   the Free Software Foundation; either version 3 of the License,
> > or
> > +   (at your option) any later version.
> > +
> > +   This program is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +   GNU General Public License for more details.
> > +
> > +   You should have received a copy of the GNU General Public
> > License
> > +   along with this program.  If not, see <
> > http://www.gnu.org/licenses/>.  */
> > +
> > +/* The reverse finish command should return from a function and
> > stop
> > on
> > +   the first instruction of the source line where the function
> > call
> > is made.
> > +   Specifically, the behavior should match doing a reverse next
> > from
> > the
> > +   first instruction in the function.  GDB should only require one
> > reverse
> > +   step or next statement to reach the previous source code line.
> > +
> > +   This test verifies the fix for gdb bugzilla:
> > +
> > +   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> > +
> > +   PowerPC supports two entry points to a function.  The normal
> > entry point
> > +   is called the local entry point (LEP).  The alternate entry
> > point
> > is called
> > +   the global entry point (GEP).  The GEP is only used if the
> > table
> > of
> > +   contents (TOC) value stored in register r2 needs to be setup
> > prior to
> > +   execution starting at the LEP.  A function call via a function
> > pointer
> > +   will entry via the GEP.  A normal function call will enter via
> > the LEP.
> > +
> > +   This test has been expanded to include tests to verify the
> > reverse-finish
> > +   command works properly if the function is called via the
> > GEP.  The original
> > +   test only verified the reverse-finish command for a normal call
> > that used
> > +   the LEP.  */
> > +
> > +int
> > +function2 (int a, int b)
> > +{
> > +  int ret = 0;
> > +  ret = ret + a + b;
> > +  return ret;
> > +}
> > +
> > +int
> > +function1 (int a, int b)   // FUNCTION1
> > +{
> > +  int ret = 0;
> > +  int (*funp) (int, int) = &function2;
> > +  /* The assembly code for this function when compiled for PowerPC
> > is as
> > +     follows:
> > +
> > +     0000000010000758 <function1>:
> > +     10000758:	02 10 40 3c 	lis     r2,4098        <-
> > GEP
> > +     1000075c:	00 7f 42 38 	addi    r2,r2,32512
> > +     10000760:	a6 02 08 7c 	mflr    r0             <-
> > LEP
> > +     10000764:	10 00 01 f8 	std     r0,16(r1)
> > +     ....
> > +
> > +     When the function is called on PowerPC with function1 (a, b)
> > the call
> > +     enters at the Local Entry Point (LEP).  When the function is
> > called via
> > +     a function pointer, the Global Entry Point (GEP) for
> > function1
> > is used.
> > +     The GEP sets up register 2 before reaching the LEP.
> > +  */
> > +  ret = funp (a + 1, b + 2);
> > +  return ret;
> > +}
> > +
> > +int
> > +main(int argc, char* argv[])
> > +{
> > +  int a, b;
> > +  int (*funp) (int, int) = &function1;
> > +
> > +  /* Call function via Local Entry Point (LEP).  */
> > +
> > +  a = 1;
> > +  b = 5;
> > +
> > +  function1 (a, b);   // CALL VIA LEP
> > +
> > +  /* Call function via Global Entry Point (GEP).  */
> > +  a = 10;
> > +  b = 50;
> > +
> > +  funp (a, b);        // CALL VIA GEP
> > +  return 0;
> > +}
> > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > new file mode 100644
> > index 00000000000..1f53b649a7d
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> > @@ -0,0 +1,224 @@
> > +# Copyright 2008-2023 Free Software Foundation, Inc.
> > +
> > +# This program is free software; you can redistribute it and/or
> > modify
> > +# it under the terms of the GNU General Public License as
> > published
> > by
> > +# the Free Software Foundation; either version 3 of the License,
> > or
> > +# (at your option) any later version.
> > +#
> > +# This program is distributed in the hope that it will be useful,
> > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +# GNU General Public License for more details.
> > +#
> > +# You should have received a copy of the GNU General Public
> > License
> > +# along with this program.  If not, see <
> > http://www.gnu.org/licenses/>.  */
> > +
> > +# This file is part of the GDB testsuite.  It tests reverse
> > stepping.
> > +# Lots of code borrowed from "step-test.exp".
> > +
> > +# The reverse finish command should return from a function and
> > stop
> > on
> > +# the first instruction of the source line where the function call
> > is made.
> > +# Specifically, the behavior should match doing a reverse next
> > from
> > the
> > +# first instruction in the function.  GDB should only take one
> > reverse step
> > +# or next statement to reach the previous source code line.
> > +
> > +# This testcase verifies the reverse-finish command stops at the
> > first
> > +# instruction in the source code line where the function was
> > called.  There
> > +# are two scenarios that must be checked:
> > +#   1) gdb is at the entry point instruction for the function
> > +#   2) gdb is in the body of the function.
> > +
> > +# This test verifies the fix for gdb bugzilla:
> > +#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> > +
> > +# PowerPC supports two entry points to a function.  The normal
> > entry
> > point
> > +# is called the local entry point (LEP).  The alternate entry
> > point
> > is called
> > +# the global entry point (GEP).  A function call via a function
> > pointer
> > +# will entry via the GEP.  A normal function call will enter via
> > the
> > LEP.
> > +#
> > +# This test has been expanded to include tests to verify the
> > reverse-finish
> > +# command works properly if the function is called via the
> > GEP.  The
> > original
> > +# test only verified the reverse-finish command for a normal call
> > that used
> > +# the LEP.
> > +
> > +if ![supports_reverse] {
> > +    return
> > +}
> > +
> > +standard_testfile
> > +
> > +if { [prepare_for_testing "failed to prepare" $testfile $srcfile]
> > }
> > {
> > +    return -1
> > +}
> > +
> > +runto_main
> > +set target_remote [gdb_is_target_remote]
> > +
> > +if [supports_process_record] {
> > +    # Activate process record/replay.
> > +    gdb_test_no_output "record" "turn on process record for test1"
> > +}
> > +
> > +
> > +### TEST 1: reverse finish from the entry point instruction (LEP)
> > in
> > +### function1 when called using the normal entry point (LEP).
> > +
> > +# Set breakpoint at call to function1 in main.
> > +set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
> > +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> > +
> > +# Continue to break point at function1 call in main.
> > +gdb_continue_to_breakpoint \
> > +    "stopped at function1 entry point instruction to stepi into
> > function" \
> > +    ".*$srcfile:$bp_LEP_test\r\n.*"
> > +
> > +# stepi until we see "{" indicating we entered function1
> > +repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1
> > call" "100"
> > +
> > +# The reverse-finish command should stop on the function call
> > instruction
> > +# which is the last instruction in the source code line.  A
> > reverse-
> > next
> > +# instruction should then stop at the first instruction in the
> > same
> > source
> > +# code line.  Another revers-next instruction stops at the
> > previous
> > source
> > +# code line.
> > +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA
> > LEP.*" \
> > +    "reverse-finish function1 LEP call from LEP "
> > +gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA
> > LEP"
> > \
> > +    "reverse next 1 LEP entry point function call from LEP"
> > +gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5,
> > call
> > from LEP"
> > +
> > +
> > +gdb_test "reverse-continue" ".*" "setup for test 2"
> > +
> > +# Turn off record to clear logs and turn on again
> > +gdb_test "record stop"  "Process record is stopped.*" \
> > +    "turn off process record for test1"
> > +gdb_test_no_output "record" "turn on process record for test2"
> > +
> > +
> > +### TEST 2: reverse finish from the body of function1.
> > +
> > +# Set breakpoint at call to function1 in main.
> > +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> > +
> > +# Continue to break point at function1 call in main.
> > +gdb_continue_to_breakpoint \
> > +    "at function1 entry point instruction to step to body of
> > function" \
> > +    ".*$srcfile:$bp_LEP_test\r\n.*"
> > +
> > +# do a step instruction to get to the body of the function
> > +gdb_test "step" ".*int ret = 0;.*" "step test 1"
> > +
> > +# The reverse-finish command should stop on the function call
> > instruction
> > +# which is the last instruction in the source code line.  A
> > reverse-
> > next
> > +# instruction should then stop at the first instruction in the
> > same
> > source
> > +# code line.  Another revers-next instruction stops at the
> > previous
> > source
> > +# code line.
> > +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA
> > LEP.*" \
> > +    "reverse-finish function1 LEP call from function body"
> > +gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA
> > LEP.*" \
> > +    "reverse next 1 LEP from function body"
> > +gdb_test "reverse-next" ".*b = 5;.*" \
> > +    "reverse next 2 at b = 5, from function body"
> > +
> > +gdb_test "reverse-continue" ".*" "setup for test 3"
> > +
> > +# Turn off record to clear logs and turn on again
> > +gdb_test "record stop"  "Process record is stopped.*" \
> > +    "turn off process record for test2"
> > +gdb_test_no_output "record" "turn on process record for test3"
> > +
> > +
> > +### TEST 3: reverse finish from the alternate entry point
> > instruction (GEP) in
> > +### function1 when called using the alternate entry point (GEP).
> > +
> > +# Set breakpoint at call to funp in main.
> > +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> > +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> > +
> > +# Continue to break point at funp call in main.
> > +gdb_continue_to_breakpoint \
> > +    "stopped at function1 entry point instruction to stepi into
> > funp" \
> > +    ".*$srcfile:$bp_GEP_test\r\n.*"
> > +
> > +# stepi until we see "{" indicating we entered function.
> > +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
> > +
> > +# The reverse-finish command should stop on the function call
> > instruction
> > +# which is the last instruction in the source code line.  A
> > reverse-
> > next
> > +# instruction should then stop at the first instruction in the
> > same
> > source
> > +# code line.  Another revers-next instruction stops at the
> > previous
> > source
> > +# code line.
> > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> > +    "function1 GEP call call from GEP"
> > +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> > +    "reverse next 1 GEP entry point function call from GEP"
> > +gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50,
> > call from GEP"
> > +
> > +gdb_test "reverse-continue" ".*" "setup for test 4"
> > +
> > +# Turn off record to clear logs and turn on again
> > +gdb_test "record stop"  "Process record is stopped.*" \
> > +    "turn off process record for test3"
> > +gdb_test_no_output "record" "turn on process record for test4"
> > +
> > +### TEST 4: reverse finish from between the GEP and LEP in
> > +### function1 when called using the alternate entry point (GEP).
> > +
> > +# Set breakpoint at call to funp in main.
> > +set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
> > +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> > +
> > +# Continue to break point at funp call in main.
> > +gdb_continue_to_breakpoint \
> > +    "stopped at function1 entry point instruction to stepi into
> > funp
> > again" \
> > +    ".*$srcfile:$bp_GEP_test\r\n.*"
> > +
> > +# stepi until we see "{" indicating we entered function.
> > +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call
> > again"
> > +
> > +# do one more stepi so we are between the GEP and LEP.
> > +gdb_test "stepi" "{" "stepi to between GEP and LEP"
> > +
> > +# The reverse-finish command should stop on the function call
> > instruction
> > +# which is the last instruction in the source code line.  A
> > reverse-
> > next
> > +# instruction should then stop at the first instruction in the
> > same
> > source
> > +# code line.  Another revers-next instruction stops at the
> > previous
> > source
> > +# code line.
> > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> > +    "function1 GEP call call from GEP again"
> > +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> > +    "reverse next 1 GEP entry point function call from GEP again"
> > +gdb_test "reverse-next" ".*b = 50;.*" \
> > +    "reverse next 2 at b = 50, call from GEP again"
> > +
> > +gdb_test "reverse-continue" ".*" "setup for test 5"
> > +
> > +# Turn off record to clear logs and turn on again
> > +gdb_test "record stop"  "Process record is stopped.*" \
> > +    "turn off process record for test4"
> > +gdb_test_no_output "record" "turn on process record for test5"
> > +
> > +
> > +### TEST 5: reverse finish from the body of function 1 when
> > calling
> > using the
> > +### alternate entrypoint (GEP).
> > +gdb_breakpoint $srcfile:$bp_GEP_test temporary
> > +
> > +# Continue to break point at funp call.
> > +gdb_continue_to_breakpoint \
> > +    "at function1 entry point instruction to step to body of funp
> > call" \
> > +    ".*$srcfile:$bp_GEP_test\r\n.*"
> > +
> > +# Step into body of funp, called via GEP.
> > +gdb_test "step" ".*int ret = 0;.*" "step test 2"
> > +
> > +# The reverse-finish command should stop on the function call
> > instruction
> > +# which is the last instruction in the source code line.  A
> > reverse-
> > next
> > +# instruction should then stop at the first instruction in the
> > same
> > source
> > +# code line.  Another revers-next instruction stops at the
> > previous
> > source
> > +# code line.
> > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
> > +    "reverse-finish function1 GEP call, from function body  "
> > +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> > +    "reverse next 1 GEP call from function body"
> > +gdb_test "reverse-next" ".*b = 50;.*" \
> > +    "reverse next 2 at b = 50 from function body"
> 
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 20:59                                                                                         ` [PATCH 1/2] " Carl Love
  2023-03-03 11:56                                                                                           ` Bruno Larsen
@ 2023-03-09 19:03                                                                                           ` Tom Tromey
  2023-03-09 21:42                                                                                             ` Carl Love
  2023-03-09 21:54                                                                                             ` [PATCH 1/2 ver 2] " Carl Love
  1 sibling, 2 replies; 105+ messages in thread
From: Tom Tromey @ 2023-03-09 19:03 UTC (permalink / raw)
  To: Carl Love via Gdb-patches
  Cc: Tom de Vries, Ulrich Weigand, Bruno Larsen, pedro, Carl Love

>>>>> "Carl" == Carl Love via Gdb-patches <gdb-patches@sourceware.org> writes:

Carl> Procedure proc_step_until from test gdb.reverse/step-indirect-call-thunk.exp

The "proc_" in there seems incorrect.

Carl>  # Step until the pattern REGEXP is found.  Step at most
Carl>  # MAX_STEPS times, but stop stepping once REGEXP is found.
Carl> -#
Carl> +# CURRENT matches current location
Carl>  # If REGEXP is found then a single pass is emitted, otherwise, after
Carl>  # MAX_STEPS steps, a single fail is emitted.
Carl>  #
Carl>  # TEST_NAME is the name used in the pass/fail calls.
 
Carl> -proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
Carl> +proc gdb_step_until { regexp {test_name ""} {current ""} \
Carl> +			  { max_steps 10 } } {
Carl> +    if { $current == "" } {
Carl> +	set current "\}"
Carl> +    }
Carl> +    if { $test_name == "" } {
Carl> +	set test_name "stepping until regexp"
Carl> +    }

I think you can just supply these as defaults directly in the proc
definition.

Carl> +# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
Carl> +#
Carl> +#  COMMAND is a stepping command
Carl> +#  CURRENT is a string matching the current location
Carl> +#  TARGET  is a string matching the target location
Carl> +#  TEST    is the test name
Carl> +#  MAX_STEPS is number of steps attempted before fail is emitted
Carl> +#
Carl> +# The function issues repeated COMMANDs as long as the location matches
Carl> +# CURRENT up to a maximum of 100 steps.

s/100/MAX_STEPS

Carl> +#
Carl> +# TEST passes if the resulting location matches TARGET and fails
Carl> +# otherwise.
Carl> +#
Carl> +proc repeat_cmd_until { command current target test_name {max_steps 100} } {

The docs refer to "TEST" but should use "TEST_NAME".

thanks,
Tom

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 1/2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-09 19:03                                                                                           ` Tom Tromey
@ 2023-03-09 21:42                                                                                             ` Carl Love
  2023-03-09 21:54                                                                                             ` [PATCH 1/2 ver 2] " Carl Love
  1 sibling, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-03-09 21:42 UTC (permalink / raw)
  To: Tom Tromey, Carl Love via Gdb-patches
  Cc: Tom de Vries, Ulrich Weigand, Bruno Larsen, pedro

On Thu, 2023-03-09 at 12:03 -0700, Tom Tromey wrote:
> > > > > > "Carl" == Carl Love via Gdb-patches <
> > > > > > gdb-patches@sourceware.org> writes:
> 
> Carl> Procedure proc_step_until from test gdb.reverse/step-indirect-
> call-thunk.exp
> 
> The "proc_" in there seems incorrect.

Ah, yea.  Good catch.  Fixed that.

> 
> Carl>  # Step until the pattern REGEXP is found.  Step at most
> Carl>  # MAX_STEPS times, but stop stepping once REGEXP is found.
> Carl> -#
> Carl> +# CURRENT matches current location
> Carl>  # If REGEXP is found then a single pass is emitted, otherwise,
> after
> Carl>  # MAX_STEPS steps, a single fail is emitted.
> Carl>  #
> Carl>  # TEST_NAME is the name used in the pass/fail calls.
> 
> Carl> -proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
> Carl> +proc gdb_step_until { regexp {test_name ""} {current ""} \
> Carl> +			  { max_steps 10 } } {
> Carl> +    if { $current == "" } {
> Carl> +	set current "\}"
> Carl> +    }
> Carl> +    if { $test_name == "" } {
> Carl> +	set test_name "stepping until regexp"
> Carl> +    }
> 
> I think you can just supply these as defaults directly in the proc
> definition.

True, I guess I was just keeping with the original "style".  But yea,
better to do these as defaults.  Changed to use defaults in this
function and similarly in the the new proceedure gdb_step_until.
> 
> Carl> +# Do repeated stepping COMMANDs in order to reach TARGET from
> CURRENT
> Carl> +#
> Carl> +#  COMMAND is a stepping command
> Carl> +#  CURRENT is a string matching the current location
> Carl> +#  TARGET  is a string matching the target location
> Carl> +#  TEST    is the test name
> Carl> +#  MAX_STEPS is number of steps attempted before fail is
> emitted
> Carl> +#
> Carl> +# The function issues repeated COMMANDs as long as the
> location matches
> Carl> +# CURRENT up to a maximum of 100 steps.
> 
> s/100/MAX_STEPS
OK, changed.
> 
> Carl> +#
> Carl> +# TEST passes if the resulting location matches TARGET and
> fails
> Carl> +# otherwise.
> Carl> +#
> Carl> +proc repeat_cmd_until { command current target test_name
> {max_steps 100} } {
> 
> The docs refer to "TEST" but should use "TEST_NAME".

yup, thanks.  Changed.

Will post version 2.  Thanks for the review.

                            Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH 1/2 ver 2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-09 19:03                                                                                           ` Tom Tromey
  2023-03-09 21:42                                                                                             ` Carl Love
@ 2023-03-09 21:54                                                                                             ` Carl Love
  2023-03-10  3:53                                                                                               ` Tom Tromey
  1 sibling, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-09 21:54 UTC (permalink / raw)
  To: Tom Tromey, Carl Love via Gdb-patches, cel
  Cc: Tom de Vries, Ulrich Weigand, Bruno Larsen, pedro

GDB maintainers, Tom, Ulrich, Bruno, Pedro:

I fixed the documentation errors and changed the arguments of the
proceedures to set the values by default rather than using an
additional if statement.

Fixed a couple of spelling mistakes in the commit log.

I retested the patch to make sure everything still works.

Thanks for the reviews.

                  Carl

--------------------------------------------------------
Move step_until procedure

Procedure step_until from test gdb.reverse/step-indirect-call-thunk.exp
is moved to lib/gdb.exp and renamed repeat_cmd_until.  The existing procedure
gdb_step_until in lib/gdb.exp is simpler variant of the new repeat_cmd_until
procedure.  The existing procedure gdb_step_until is changed to just call
the new repeat_cmd_until procedure with the command set to "step" and an
optional CURRENT string.  The default CURRENT string is set to "\}" to work
with the existing uses of procedure gdb_step_until.
---
 .../gdb.reverse/step-indirect-call-thunk.exp  | 49 +++----------------
 gdb/testsuite/lib/gdb.exp                     | 47 ++++++++++++------
 2 files changed, 41 insertions(+), 55 deletions(-)

diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
index f433efb11c2..e6c81b80a7b 100644
--- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
+++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp
@@ -38,39 +38,6 @@ if { ![runto_main] } {
     return -1
 }
 
-# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
-#
-#  COMMAND is a stepping command
-#  CURRENT is a string matching the current location
-#  TARGET  is a string matching the target location
-#  TEST    is the test name
-#
-# The function issues repeated COMMANDs as long as the location matches
-# CURRENT up to a maximum of 100 steps.
-#
-# TEST passes if the resulting location matches TARGET and fails
-# otherwise.
-#
-proc step_until { command current target test } {
-    global gdb_prompt
-
-    set count 0
-    gdb_test_multiple "$command" "$test" {
-        -re "$current.*$gdb_prompt $" {
-            incr count
-            if { $count < 100 } {
-                send_gdb "$command\n"
-                exp_continue
-            } else {
-                fail "$test"
-            }
-        }
-        -re "$target.*$gdb_prompt $" {
-            pass "$test"
-        }
-    }
-}
-
 gdb_test_no_output "record"
 gdb_test "next" ".*" "record trace"
 
@@ -90,20 +57,20 @@ gdb_test "reverse-next" "apply\.2.*" \
     "reverse-step through thunks and over inc"
 
 # We can use instruction stepping to step into thunks.
-step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
-step_until "stepi" "indirect_thunk" "inc" \
+repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into call thunk"
+repeat_cmd_until "stepi" "indirect_thunk" "inc" \
     "stepi out of call thunk into inc"
 set alphanum_re "\[a-zA-Z0-9\]"
 set pic_thunk_re  "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* \\(\\)"
-step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
-step_until "stepi" "return_thunk" "apply" \
+repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into return thunk"
+repeat_cmd_until "stepi" "return_thunk" "apply" \
     "stepi out of return thunk back into apply"
 
-step_until "reverse-stepi" "apply" "return_thunk" \
+repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \
     "reverse-stepi into return thunk"
-step_until "reverse-stepi" "return_thunk" "inc" \
+repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \
     "reverse-stepi out of return thunk into inc"
-step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
+repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \
     "reverse-stepi into call thunk"
-step_until "reverse-stepi" "indirect_thunk" "apply" \
+repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \
     "reverse-stepi out of call thunk into apply"
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 19c782bea46..46bd40318f6 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -9270,31 +9270,50 @@ gdb_caching_proc arm_cc_for_target {
 
 # Step until the pattern REGEXP is found.  Step at most
 # MAX_STEPS times, but stop stepping once REGEXP is found.
-#
+# CURRENT matches current location
 # If REGEXP is found then a single pass is emitted, otherwise, after
 # MAX_STEPS steps, a single fail is emitted.
 #
 # TEST_NAME is the name used in the pass/fail calls.
 
-proc gdb_step_until { regexp {test_name ""} {max_steps 10} } {
-    if { $test_name == "" } {
-	set test_name "stepping until regexp"
-    }
+proc gdb_step_until { regexp {test_name "stepping until regexp"} \
+			  {current "\}"} { max_steps 10 } } {
+    repeat_cmd_until "step" $current  $regexp  $test_name "10"
+}
+
+# Do repeated stepping COMMANDs in order to reach TARGET from CURRENT
+#
+#  COMMAND   is a stepping command
+#  CURRENT   is a string matching the current location
+#  TARGET    is a string matching the target location
+#  TEST_NAME is the test name
+#  MAX_STEPS is number of steps attempted before fail is emitted
+#
+# The function issues repeated COMMANDs as long as the location matches
+# CURRENT up to a maximum of MAX_STEPS.
+#
+# TEST_NAME passes if the resulting location matches TARGET and fails
+# otherwise.
+
+proc repeat_cmd_until { command current target \
+			    {test_name "stepping until regexp"} \
+			    {max_steps 100} } {
+    global gdb_prompt
 
     set count 0
-    gdb_test_multiple "step" "$test_name" {
-	-re "$regexp\r\n$::gdb_prompt $" {
-	    pass $test_name
-	}
-	-re ".*$::gdb_prompt $" {
-	    if {$count < $max_steps} {
-		incr count
-		send_gdb "step\n"
+    gdb_test_multiple "$command" "$test_name" {
+	-re "$current.*$gdb_prompt $" {
+	    incr count
+	    if { $count < $max_steps } {
+		send_gdb "$command\n"
 		exp_continue
 	    } else {
-		fail $test_name
+		fail "$test_name"
 	    }
 	}
+	-re "$target.*$gdb_prompt $" {
+	    pass "$test_name"
+	}
     }
 }
 
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 1/2 ver 2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-09 21:54                                                                                             ` [PATCH 1/2 ver 2] " Carl Love
@ 2023-03-10  3:53                                                                                               ` Tom Tromey
  0 siblings, 0 replies; 105+ messages in thread
From: Tom Tromey @ 2023-03-10  3:53 UTC (permalink / raw)
  To: Carl Love
  Cc: Tom Tromey, Carl Love via Gdb-patches, Tom de Vries,
	Ulrich Weigand, Bruno Larsen, pedro

>>>>> Carl Love <cel@us.ibm.com> writes:

> Move step_until procedure

> Procedure step_until from test gdb.reverse/step-indirect-call-thunk.exp
> is moved to lib/gdb.exp and renamed repeat_cmd_until.  The existing procedure
> gdb_step_until in lib/gdb.exp is simpler variant of the new repeat_cmd_until
> procedure.  The existing procedure gdb_step_until is changed to just call
> the new repeat_cmd_until procedure with the command set to "step" and an
> optional CURRENT string.  The default CURRENT string is set to "\}" to work
> with the existing uses of procedure gdb_step_until.

Thanks, this looks good to me.

Tom

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 20:59                                                                                         ` [PATCH 2/2 ] " Carl Love
  2023-03-08 16:19                                                                                           ` [PING] " Carl Love
@ 2023-03-13 14:16                                                                                           ` Ulrich Weigand
  2023-03-13 17:31                                                                                             ` Carl Love
  2023-03-13 17:38                                                                                             ` [PATCH 2/2 ver2] " Carl Love
  2023-03-24 17:23                                                                                           ` [PATCH 2/2 ] " Simon Marchi
  2 siblings, 2 replies; 105+ messages in thread
From: Ulrich Weigand @ 2023-03-13 14:16 UTC (permalink / raw)
  To: gdb-patches, Bruno Larsen, tdevries, cel, pedro

Carl Love <cel@us.ibm.com> wrote:

>This patch fixes the reverse-finish command on PowerPC.  The command
>now works the same as on other architectures, specifically X86.  There
>are no functional changes for other architectures.  The patch includes
>a new testcase to verify the reverse-finish command works correctly
>with the multiple entry points supported by PowerPC.

This looks good to me in general, just one cosmetic issue:

>-      /* Set a step-resume at the function's entry point.  Once that's
>-	 hit, we'll do one more step backwards.  */
>+  if  ((pc < alt_entry_point) || (pc > entry_point))
>+    {
>+      /* We are in the body of the function.  Set a breakpoint to go back to
>+	 the normal entry point.  */
>       symtab_and_line sr_sal;
>-      sr_sal.pc = sal.pc;
>+      sr_sal.pc = entry_point;
>       sr_sal.pspace = get_frame_program_space (frame);
>-      insert_step_resume_breakpoint_at_sal (gdbarch,
>-					    sr_sal, null_frame_id);
>-
>-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>+      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
>+					    null_frame_id);
>     }
>+
>   else
>-    {
>-      /* We're almost there -- we just need to back up by one more
>-	 single-step.  */
>-      tp->control.step_range_start = tp->control.step_range_end = 1;
>-      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
>-    }
>+    /* We are either at one of the entry points or between the entry points.
>+       If we are not at the alt_entry point, go back to the alt_entry_point
>+       If we at the normal entry point step back one instruction, when we
>+       stop we will determine if we entered via the entry point or the
>+       alternate entry point.  If we are at the alternate entry point,
>+       single step back to the function call.  */
>+    tp->control.step_range_start = tp->control.step_range_end = 1;
>+
>+  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);

There's still a bunch of unnecessary changes in there (changes
in formatting, moving the "proceed" call, etc.).  It would be
preferable to not have those in.


Bye,
Ulrich


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-13 14:16                                                                                           ` Ulrich Weigand
@ 2023-03-13 17:31                                                                                             ` Carl Love
  2023-03-13 17:38                                                                                             ` [PATCH 2/2 ver2] " Carl Love
  1 sibling, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-03-13 17:31 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches, Bruno Larsen, tdevries, pedro; +Cc: cel

Ulrich:

On Mon, 2023-03-13 at 14:16 +0000, Ulrich Weigand wrote:
> Carl Love <cel@us.ibm.com> wrote:
> 
> > This patch fixes the reverse-finish command on PowerPC.  The
> > command
> > now works the same as on other architectures, specifically
> > X86.  There
> > are no functional changes for other architectures.  The patch
> > includes
> > a new testcase to verify the reverse-finish command works correctly
> > with the multiple entry points supported by PowerPC.
> 
> This looks good to me in general, just one cosmetic issue:
> 
> > -      /* Set a step-resume at the function's entry point.  Once
> > that's
> > -	 hit, we'll do one more step backwards.  */
> > +  if  ((pc < alt_entry_point) || (pc > entry_point))
> > +    {
> > +      /* We are in the body of the function.  Set a breakpoint to
> > go back to
> > +	 the normal entry point.  */
> >       symtab_and_line sr_sal;
> > -      sr_sal.pc = sal.pc;
> > +      sr_sal.pc = entry_point;
> >       sr_sal.pspace = get_frame_program_space (frame);
> > -      insert_step_resume_breakpoint_at_sal (gdbarch,
> > -					    sr_sal, null_frame_id);
> > -
> > -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> > +      insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
> > +					    null_frame_id);
> >     }
> > +
> >   else
> > -    {
> > -      /* We're almost there -- we just need to back up by one more
> > -	 single-step.  */
> > -      tp->control.step_range_start = tp->control.step_range_end =
> > 1;
> > -      proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> > -    }
> > +    /* We are either at one of the entry points or between the
> > entry points.
> > +       If we are not at the alt_entry point, go back to the
> > alt_entry_point
> > +       If we at the normal entry point step back one instruction,
> > when we
> > +       stop we will determine if we entered via the entry point or
> > the
> > +       alternate entry point.  If we are at the alternate entry
> > point,
> > +       single step back to the function call.  */
> > +    tp->control.step_range_start = tp->control.step_range_end = 1;
> > +
> > +  proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> 
> There's still a bunch of unnecessary changes in there (changes
> in formatting, moving the "proceed" call, etc.).  It would be
> preferable to not have those in.

OK, I went back and looked again to see what else I could do to remove
"unecessary changes", etc in gdg/infcmd.c.  I took out the move of the
proceed call from the if/else branches to a single call after the
if/else statement.  I moved the declarations to the top with the other
declarations.  I moved the new if statement up a little.  These changes
make the changes in the if/else are easier to read.  I made a few other
cosmetic changes to get the diff to be as minimal as I could.

I hope this addresses your concerns.  There are no functional changes. 
I retested the patch.  I will post an updated version of the patch.

                        Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ver2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-13 14:16                                                                                           ` Ulrich Weigand
  2023-03-13 17:31                                                                                             ` Carl Love
@ 2023-03-13 17:38                                                                                             ` Carl Love
  2023-03-17 17:19                                                                                               ` Ulrich Weigand
  1 sibling, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-13 17:38 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches, Bruno Larsen, tdevries, pedro; +Cc: cel

Ulrich, GDB maintainers:

I have updated gdb/infrun.c per the comments from Ulrich to remove
"unnecessary" code and format changes to make the diff as minimal as I
can.  There are no functional changes in these changes.

The patch has been retested on PowerPC to make sure there are no
regressions.

Please let me know if this version of this patch (second in the series)
is acceptable.  Thanks.

                         Carl 


----------------------------------------------------------
PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp

PPC64 multiple entry points, a normal entry point and an alternate entry
point.  The alternate entry point is to setup the Table of Contents (TOC)
register before continuing at the normal entry point.  When the TOC is
already valid, the normal entry point is used, this is typically the case.
The alternate entry point is typically referred to as the global entry
point (GEP) in IBM.  The normal entry point is typically referred to as
the local entry point (LEP).

When GDB is executing the finish command in reverse, the function
finish_backward currently sets the break point at the alternate entry point.
This issue is if the function, when executing in the forward direction, entered
the function via the normal entry point, execution in the reverse direction
will never sees the break point at the alternate entry point.  In this case,
the reverse execution continues until the next break point is encountered thus
stopping at the wrong place.

This patch adds a new address to struct execution_control_state to hold the
address of the alternate entry point (GEP).  The finish_backwards function
is updated, if the stopping point is between the normal entry point (LEP)
and the end of the function, a breakpoint is set at the normal entry point.
If the stopping point is between the entry points, a breakpoint is set at
the alternate entry point.  This ensures that GDB will always stop at the
normal entry point.  If the function did enter via the alternate entry point,
GDB will detect that and continue to execute backwards in the function until
the alternate entry point is reached.

The patch fixes the behavior of the reverse-finish command on PowerPC to
match the behavior of the command on other platforms, specifically X86.
The patch does not change the behavior of the command on X86.

A new test is added to verify the reverse-finish command on PowerPC
correctly stops at the instruction where the function call is made.

The patch fixes 11 regression errors in test gdb.reverse/finish-precsave.exp
and 11 regression errors in test gdb.reverse/finish-reverse.exp.

The patch has been tested on Power 10 and X86 processor with no new
regression failures.
---
 gdb/infcmd.c                                  |  32 ++-
 gdb/infrun.c                                  |  24 ++
 .../gdb.reverse/finish-reverse-next.c         |  91 +++++++
 .../gdb.reverse/finish-reverse-next.exp       | 224 ++++++++++++++++++
 4 files changed, 362 insertions(+), 9 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c
 create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index c369b795757..f46461512fe 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1710,6 +1710,10 @@ finish_backward (struct finish_command_fsm *sm)
   struct thread_info *tp = inferior_thread ();
   CORE_ADDR pc;
   CORE_ADDR func_addr;
+  CORE_ADDR alt_entry_point = sal.pc;
+  CORE_ADDR entry_point = alt_entry_point;
+  frame_info_ptr frame = get_selected_frame (nullptr);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
 
   pc = get_frame_pc (get_current_frame ());
 
@@ -1718,6 +1722,15 @@ finish_backward (struct finish_command_fsm *sm)
 
   sal = find_pc_line (func_addr, 0);
 
+  if (gdbarch_skip_entrypoint_p (gdbarch))
+    /* Some architectures, like PowerPC use local and global entry points.
+       There is only one Entry Point (GEP = LEP) for other architectures.
+       The GEP is an alternate entry point.  The LEP is the normal entry point.
+       The value of entry_point was initialized to the alternate entry point
+       (GEP).  It will be adjusted to the normal entry point if the function
+       has two entry points.  */
+    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
+
   tp->control.proceed_to_finish = 1;
   /* Special case: if we're sitting at the function entry point,
      then all we need to do is take a reverse singlestep.  We
@@ -1728,15 +1741,12 @@ finish_backward (struct finish_command_fsm *sm)
      no way that a function up the stack can have a return address
      that's equal to its entry point.  */
 
-  if (sal.pc != pc)
+  if ((pc < alt_entry_point) || (pc > entry_point))
     {
-      frame_info_ptr frame = get_selected_frame (nullptr);
-      struct gdbarch *gdbarch = get_frame_arch (frame);
-
-      /* Set a step-resume at the function's entry point.  Once that's
-	 hit, we'll do one more step backwards.  */
+      /* We are in the body of the function.  Set a breakpoint to go back to
+	 the normal entry point.  */
       symtab_and_line sr_sal;
-      sr_sal.pc = sal.pc;
+      sr_sal.pc = entry_point;
       sr_sal.pspace = get_frame_program_space (frame);
       insert_step_resume_breakpoint_at_sal (gdbarch,
 					    sr_sal, null_frame_id);
@@ -1745,8 +1755,12 @@ finish_backward (struct finish_command_fsm *sm)
     }
   else
     {
-      /* We're almost there -- we just need to back up by one more
-	 single-step.  */
+      /* We are either at one of the entry points or between the entry points.
+	 If we are not at the alt_entry point, go back to the alt_entry_point
+	 If we at the normal entry point step back one instruction, when we
+	 stop we will determine if we entered via the entry point or the
+	 alternate entry point.  If we are at the alternate entry point,
+	 single step back to the function call.  */
       tp->control.step_range_start = tp->control.step_range_end = 1;
       proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 33aa0c8794b..5c9babb9104 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1938,6 +1938,7 @@ struct execution_control_state
 
   struct target_waitstatus ws;
   int stop_func_filled_in = 0;
+  CORE_ADDR stop_func_alt_start = 0;
   CORE_ADDR stop_func_start = 0;
   CORE_ADDR stop_func_end = 0;
   const char *stop_func_name = nullptr;
@@ -4822,6 +4823,11 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 	  ecs->stop_func_start
 	    += gdbarch_deprecated_function_start_offset (gdbarch);
 
+	  /* PowerPC functions have a Local Entry Point (LEP) and a Global
+	     Entry Point (GEP).  There is only one Entry Point (GEP = LEP) for
+	     other architectures.  */
+	  ecs->stop_func_alt_start = ecs->stop_func_start;
+
 	  if (gdbarch_skip_entrypoint_p (gdbarch))
 	    ecs->stop_func_start
 	      = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
@@ -7411,6 +7417,24 @@ process_event_stop_test (struct execution_control_state *ecs)
 	}
     }
 
+  if (execution_direction == EXEC_REVERSE
+      && ecs->event_thread->control.proceed_to_finish
+      && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start
+      && ecs->event_thread->stop_pc () < ecs->stop_func_start)
+    {
+      /* We are executing the reverse-finish command.
+	 If the system supports multiple entry points and we are finishing a
+	 function in reverse.   If we are between the entry points singe-step
+	 back to the alternate entry point.  If we are at the alternate entry
+	 point -- just   need to back up by one more single-step, which
+	 should take us back to the function call.  */
+      ecs->event_thread->control.step_range_start
+	= ecs->event_thread->control.step_range_end = 1;
+      keep_going (ecs);
+      return;
+
+    }
+
   if (ecs->event_thread->control.step_range_end == 1)
     {
       /* It is stepi or nexti.  We always want to stop stepping after
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
new file mode 100644
index 00000000000..e95ee8e33a6
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c
@@ -0,0 +1,91 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The reverse finish command should return from a function and stop on
+   the first instruction of the source line where the function call is made.
+   Specifically, the behavior should match doing a reverse next from the
+   first instruction in the function.  GDB should only require one reverse
+   step or next statement to reach the previous source code line.
+
+   This test verifies the fix for gdb bugzilla:
+
+   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+   PowerPC supports two entry points to a function.  The normal entry point
+   is called the local entry point (LEP).  The alternate entry point is called
+   the global entry point (GEP).  The GEP is only used if the table of
+   contents (TOC) value stored in register r2 needs to be setup prior to
+   execution starting at the LEP.  A function call via a function pointer
+   will entry via the GEP.  A normal function call will enter via the LEP.
+
+   This test has been expanded to include tests to verify the reverse-finish
+   command works properly if the function is called via the GEP.  The original
+   test only verified the reverse-finish command for a normal call that used
+   the LEP.  */
+
+int
+function2 (int a, int b)
+{
+  int ret = 0;
+  ret = ret + a + b;
+  return ret;
+}
+
+int
+function1 (int a, int b)   // FUNCTION1
+{
+  int ret = 0;
+  int (*funp) (int, int) = &function2;
+  /* The assembly code for this function when compiled for PowerPC is as
+     follows:
+
+     0000000010000758 <function1>:
+     10000758:	02 10 40 3c 	lis     r2,4098        <- GEP
+     1000075c:	00 7f 42 38 	addi    r2,r2,32512
+     10000760:	a6 02 08 7c 	mflr    r0             <- LEP
+     10000764:	10 00 01 f8 	std     r0,16(r1)
+     ....
+
+     When the function is called on PowerPC with function1 (a, b) the call
+     enters at the Local Entry Point (LEP).  When the function is called via
+     a function pointer, the Global Entry Point (GEP) for function1 is used.
+     The GEP sets up register 2 before reaching the LEP.
+  */
+  ret = funp (a + 1, b + 2);
+  return ret;
+}
+
+int
+main(int argc, char* argv[])
+{
+  int a, b;
+  int (*funp) (int, int) = &function1;
+
+  /* Call function via Local Entry Point (LEP).  */
+
+  a = 1;
+  b = 5;
+
+  function1 (a, b);   // CALL VIA LEP
+
+  /* Call function via Global Entry Point (GEP).  */
+  a = 10;
+  b = 50;
+
+  funp (a, b);        // CALL VIA GEP
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
new file mode 100644
index 00000000000..1f53b649a7d
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -0,0 +1,224 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+# PowerPC supports two entry points to a function.  The normal entry point
+# is called the local entry point (LEP).  The alternate entry point is called
+# the global entry point (GEP).  A function call via a function pointer
+# will entry via the GEP.  A normal function call will enter via the LEP.
+#
+# This test has been expanded to include tests to verify the reverse-finish
+# command works properly if the function is called via the GEP.  The original
+# test only verified the reverse-finish command for a normal call that used
+# the LEP.
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+### TEST 1: reverse finish from the entry point instruction (LEP) in
+### function1 when called using the normal entry point (LEP).
+
+# Set breakpoint at call to function1 in main.
+set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function1
+repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call" "100"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from LEP "
+gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
+    "reverse next 1 LEP entry point function call from LEP"
+gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call from LEP"
+
+
+gdb_test "reverse-continue" ".*" "setup for test 2"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test1"
+gdb_test_no_output "record" "turn on process record for test2"
+
+
+### TEST 2: reverse finish from the body of function1.
+
+# Set breakpoint at call to function1 in main.
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+# do a step instruction to get to the body of the function
+gdb_test "step" ".*int ret = 0;.*" "step test 1"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish function1 LEP call from function body"
+gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse next 1 LEP from function body"
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse next 2 at b = 5, from function body"
+
+gdb_test "reverse-continue" ".*" "setup for test 3"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test2"
+gdb_test_no_output "record" "turn on process record for test3"
+
+
+### TEST 3: reverse finish from the alternate entry point instruction (GEP) in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP"
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP entry point function call from GEP"
+gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, call from GEP"
+
+gdb_test "reverse-continue" ".*" "setup for test 4"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test3"
+gdb_test_no_output "record" "turn on process record for test4"
+
+### TEST 4: reverse finish from between the GEP and LEP in
+### function1 when called using the alternate entry point (GEP).
+
+# Set breakpoint at call to funp in main.
+set bp_GEP_test  [gdb_get_line_number "CALL VIA GEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into funp again" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# stepi until we see "{" indicating we entered function.
+repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call again"
+
+# do one more stepi so we are between the GEP and LEP.
+gdb_test "stepi" "{" "stepi to between GEP and LEP"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "function1 GEP call call from GEP again"
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP entry point function call from GEP again"
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next 2 at b = 50, call from GEP again"
+
+gdb_test "reverse-continue" ".*" "setup for test 5"
+
+# Turn off record to clear logs and turn on again
+gdb_test "record stop"  "Process record is stopped.*" \
+    "turn off process record for test4"
+gdb_test_no_output "record" "turn on process record for test5"
+
+
+### TEST 5: reverse finish from the body of function 1 when calling using the
+### alternate entrypoint (GEP).
+gdb_breakpoint $srcfile:$bp_GEP_test temporary
+
+# Continue to break point at funp call.
+gdb_continue_to_breakpoint \
+    "at function1 entry point instruction to step to body of funp call" \
+    ".*$srcfile:$bp_GEP_test\r\n.*"
+
+# Step into body of funp, called via GEP.
+gdb_test "step" ".*int ret = 0;.*" "step test 2"
+
+# The reverse-finish command should stop on the function call instruction
+# which is the last instruction in the source code line.  A reverse-next
+# instruction should then stop at the first instruction in the same source
+# code line.  Another revers-next instruction stops at the previous source
+# code line.
+gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
+    "reverse-finish function1 GEP call, from function body  "
+gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+    "reverse next 1 GEP call from function body"
+gdb_test "reverse-next" ".*b = 50;.*" \
+    "reverse next 2 at b = 50 from function body"
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ver2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-13 17:38                                                                                             ` [PATCH 2/2 ver2] " Carl Love
@ 2023-03-17 17:19                                                                                               ` Ulrich Weigand
  2023-03-17 23:05                                                                                                 ` Tom de Vries
  0 siblings, 1 reply; 105+ messages in thread
From: Ulrich Weigand @ 2023-03-17 17:19 UTC (permalink / raw)
  To: gdb-patches, Bruno Larsen, tdevries, cel, pedro

Carl Love <cel@us.ibm.com> wrote:

>I have updated gdb/infrun.c per the comments from Ulrich to remove
>"unnecessary" code and format changes to make the diff as minimal as I
>can.  There are no functional changes in these changes.
>
>The patch has been retested on PowerPC to make sure there are no
>regressions.
>
>Please let me know if this version of this patch (second in the series)
>is acceptable.  Thanks.

This version is OK.

Thanks,
Ulrich


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ver2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-17 17:19                                                                                               ` Ulrich Weigand
@ 2023-03-17 23:05                                                                                                 ` Tom de Vries
  2023-03-20 15:04                                                                                                   ` Carl Love
  2023-03-20 23:21                                                                                                   ` Carl Love
  0 siblings, 2 replies; 105+ messages in thread
From: Tom de Vries @ 2023-03-17 23:05 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches, Bruno Larsen, cel, pedro

On 3/17/23 18:19, Ulrich Weigand wrote:
> Carl Love <cel@us.ibm.com> wrote:
> 
>> I have updated gdb/infrun.c per the comments from Ulrich to remove
>> "unnecessary" code and format changes to make the diff as minimal as I
>> can.  There are no functional changes in these changes.
>>
>> The patch has been retested on PowerPC to make sure there are no
>> regressions.
>>
>> Please let me know if this version of this patch (second in the series)
>> is acceptable.  Thanks.
> 
> This version is OK.


I'm running into these regressions on x86_64-linux:
...
Running 
/data/vries/gdb/src/gdb/testsuite/gdb.reverse/finish-precsave.exp ...
FAIL: gdb.reverse/finish-precsave.exp: reverse finish from long_long_func
FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint: long_func 
backward
FAIL: gdb.reverse/finish-precsave.exp: reverse finish from long_func
FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint: int_func 
backward
FAIL: gdb.reverse/finish-precsave.exp: reverse finish from int_func
FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint: 
short_func backward
FAIL: gdb.reverse/finish-precsave.exp: reverse finish from short_func
FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint: char_func 
backward
FAIL: gdb.reverse/finish-precsave.exp: reverse finish from char_func
FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint: void_func 
backward
FAIL: gdb.reverse/finish-precsave.exp: reverse finish from void_func
Running /data/vries/gdb/src/gdb/testsuite/gdb.btrace/tailcall.exp ...
FAIL: gdb.btrace/tailcall.exp: reverse-finish.1
FAIL: gdb.btrace/tailcall.exp: reverse-step.2
FAIL: gdb.btrace/tailcall.exp: next.1
FAIL: gdb.btrace/tailcall.exp: reverse-next.1
FAIL: gdb.btrace/tailcall.exp: step.1
FAIL: gdb.btrace/tailcall.exp: finish.2
FAIL: gdb.btrace/tailcall.exp: reverse-step.3
FAIL: gdb.btrace/tailcall.exp: finish.3
Running /data/vries/gdb/src/gdb/testsuite/gdb.mi/mi-reverse.exp ...
FAIL: gdb.mi/mi-reverse.exp: reverse finish from callme (unknown output 
after running)
FAIL: gdb.mi/mi-reverse.exp: reverse next to get over the call to 
do_nothing (unknown output after running)
FAIL: gdb.mi/mi-reverse.exp: reverse step to callee1 (unknown output 
after running)
FAIL: gdb.mi/mi-reverse.exp: reverse step to callee2 (unknown output 
after running)
FAIL: gdb.mi/mi-reverse.exp: reverse step to callee3 (unknown output 
after running)
FAIL: gdb.mi/mi-reverse.exp: reverse step to callee4 (unknown output 
after running)
FAIL: gdb.mi/mi-reverse.exp: reverse-step-instruction at callee4 
(unknown output after running)
FAIL: gdb.mi/mi-reverse.exp: reverse-next-instruction at callee4 
(unknown output after running)
FAIL: gdb.mi/mi-reverse.exp: reverse-continue at callee3 (unknown output 
after running)
Running /data/vries/gdb/src/gdb/testsuite/gdb.btrace/step.exp ...
FAIL: gdb.btrace/step.exp: replay: reverse-finish.1
FAIL: gdb.btrace/step.exp: replay: reverse-next.2
FAIL: gdb.btrace/step.exp: replay: reverse-finish.2 (GDB internal error)
Running /data/vries/gdb/src/gdb/testsuite/gdb.reverse/until-precsave.exp ...
FAIL: gdb.reverse/until-precsave.exp: reverse-finish from marker2
FAIL: gdb.reverse/until-precsave.exp: reverse-advance to final return of 
factorial
FAIL: gdb.reverse/until-precsave.exp: reverse-until to entry of factorial
Running /data/vries/gdb/src/gdb/testsuite/gdb.reverse/finish-reverse.exp ...
FAIL: gdb.reverse/finish-reverse.exp: reverse finish from long_long_func
FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint: long_func 
backward
FAIL: gdb.reverse/finish-reverse.exp: reverse finish from long_func
FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint: int_func 
backward
FAIL: gdb.reverse/finish-reverse.exp: reverse finish from int_func
FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint: short_func 
backward
FAIL: gdb.reverse/finish-reverse.exp: reverse finish from short_func
FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint: char_func 
backward
FAIL: gdb.reverse/finish-reverse.exp: reverse finish from char_func
FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint: void_func 
backward
FAIL: gdb.reverse/finish-reverse.exp: reverse finish from void_func
Running 
/data/vries/gdb/src/gdb/testsuite/gdb.reverse/finish-reverse-next.exp ...
FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 LEP 
call from LEP
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP entry 
point function call from LEP
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2, at b = 5, 
call from LEP
FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 LEP 
call from function body
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from 
function body
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5, from 
function body
FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call from GEP
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry 
point function call from GEP
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50, 
call from GEP
FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call from 
GEP again
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry 
point function call from GEP again
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50, 
call from GEP again
FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 GEP 
call, from function body
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP call from 
function body
FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50 from 
function body
Running /data/vries/gdb/src/gdb/testsuite/gdb.btrace/tailcall-only.exp ...
FAIL: gdb.btrace/tailcall-only.exp: reverse-step
FAIL: gdb.btrace/tailcall-only.exp: up
...

Thanks,
- Tom


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ver2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-17 23:05                                                                                                 ` Tom de Vries
@ 2023-03-20 15:04                                                                                                   ` Carl Love
  2023-03-20 23:21                                                                                                   ` Carl Love
  1 sibling, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-03-20 15:04 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro; +Cc: cel

On Sat, 2023-03-18 at 00:05 +0100, Tom de Vries wrote:
> On 3/17/23 18:19, Ulrich Weigand wrote:
> > Carl Love <cel@us.ibm.com> wrote:
> > 
> > > I have updated gdb/infrun.c per the comments from Ulrich to
> > > remove
> > > "unnecessary" code and format changes to make the diff as minimal
> > > as I
> > > can.  There are no functional changes in these changes.
> > > 
> > > The patch has been retested on PowerPC to make sure there are no
> > > regressions.
> > > 
> > > Please let me know if this version of this patch (second in the
> > > series)
> > > is acceptable.  Thanks.
> > 
> > This version is OK.
> 
> I'm running into these regressions on x86_64-linux:

I will take a look to see if I can reproduce the issues.  

                   Carl 
> 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ver2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-17 23:05                                                                                                 ` Tom de Vries
  2023-03-20 15:04                                                                                                   ` Carl Love
@ 2023-03-20 23:21                                                                                                   ` Carl Love
  2023-03-21  3:17                                                                                                     ` Carl Love
  1 sibling, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-20 23:21 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro
  Cc: cel, luis.machado

Tom, Luis:

On Sat, 2023-03-18 at 00:05 +0100, Tom de Vries wrote:
> On 3/17/23 18:19, Ulrich Weigand wrote:
> > Carl Love <cel@us.ibm.com> wrote:
> > 
> > > I have updated gdb/infrun.c per the comments from Ulrich to
> > > remove
> > > "unnecessary" code and format changes to make the diff as minimal
> > > as I
> > > can.  There are no functional changes in these changes.
> > > 
> > > The patch has been retested on PowerPC to make sure there are no
> > > regressions.
> > > 
> > > Please let me know if this version of this patch (second in the
> > > series)
> > > is acceptable.  Thanks.
> > 
> > This version is OK.
> 
> I'm running into these regressions on x86_64-linux:
> ...
> Running 
> /data/vries/gdb/src/gdb/testsuite/gdb.reverse/finish-precsave.exp ...
> FAIL: gdb.reverse/finish-precsave.exp: reverse finish from
> long_long_func
> FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint:
> long_func 
> backward
> FAIL: gdb.reverse/finish-precsave.exp: reverse finish from long_func
> FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint:
> int_func 
> backward
> FAIL: gdb.reverse/finish-precsave.exp: reverse finish from int_func
> FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint: 
> short_func backward
> FAIL: gdb.reverse/finish-precsave.exp: reverse finish from short_func
> FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint:
> char_func 
> backward
> FAIL: gdb.reverse/finish-precsave.exp: reverse finish from char_func
> FAIL: gdb.reverse/finish-precsave.exp: continue to breakpoint:
> void_func 
> backward
> FAIL: gdb.reverse/finish-precsave.exp: reverse finish from void_func
> Running /data/vries/gdb/src/gdb/testsuite/gdb.btrace/tailcall.exp ...
> FAIL: gdb.btrace/tailcall.exp: reverse-finish.1
> FAIL: gdb.btrace/tailcall.exp: reverse-step.2
> FAIL: gdb.btrace/tailcall.exp: next.1
> FAIL: gdb.btrace/tailcall.exp: reverse-next.1
> FAIL: gdb.btrace/tailcall.exp: step.1
> FAIL: gdb.btrace/tailcall.exp: finish.2
> FAIL: gdb.btrace/tailcall.exp: reverse-step.3
> FAIL: gdb.btrace/tailcall.exp: finish.3
> Running /data/vries/gdb/src/gdb/testsuite/gdb.mi/mi-reverse.exp ...
> FAIL: gdb.mi/mi-reverse.exp: reverse finish from callme (unknown
> output 
> after running)
> FAIL: gdb.mi/mi-reverse.exp: reverse next to get over the call to 
> do_nothing (unknown output after running)
> FAIL: gdb.mi/mi-reverse.exp: reverse step to callee1 (unknown output 
> after running)
> FAIL: gdb.mi/mi-reverse.exp: reverse step to callee2 (unknown output 
> after running)
> FAIL: gdb.mi/mi-reverse.exp: reverse step to callee3 (unknown output 
> after running)
> FAIL: gdb.mi/mi-reverse.exp: reverse step to callee4 (unknown output 
> after running)
> FAIL: gdb.mi/mi-reverse.exp: reverse-step-instruction at callee4 
> (unknown output after running)
> FAIL: gdb.mi/mi-reverse.exp: reverse-next-instruction at callee4 
> (unknown output after running)
> FAIL: gdb.mi/mi-reverse.exp: reverse-continue at callee3 (unknown
> output 
> after running)
> Running /data/vries/gdb/src/gdb/testsuite/gdb.btrace/step.exp ...
> FAIL: gdb.btrace/step.exp: replay: reverse-finish.1
> FAIL: gdb.btrace/step.exp: replay: reverse-next.2
> FAIL: gdb.btrace/step.exp: replay: reverse-finish.2 (GDB internal
> error)
> Running /data/vries/gdb/src/gdb/testsuite/gdb.reverse/until-
> precsave.exp ...
> FAIL: gdb.reverse/until-precsave.exp: reverse-finish from marker2
> FAIL: gdb.reverse/until-precsave.exp: reverse-advance to final return
> of 
> factorial
> FAIL: gdb.reverse/until-precsave.exp: reverse-until to entry of
> factorial
> Running /data/vries/gdb/src/gdb/testsuite/gdb.reverse/finish-
> reverse.exp ...
> FAIL: gdb.reverse/finish-reverse.exp: reverse finish from
> long_long_func
> FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint:
> long_func 
> backward
> FAIL: gdb.reverse/finish-reverse.exp: reverse finish from long_func
> FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint:
> int_func 
> backward
> FAIL: gdb.reverse/finish-reverse.exp: reverse finish from int_func
> FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint:
> short_func 
> backward
> FAIL: gdb.reverse/finish-reverse.exp: reverse finish from short_func
> FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint:
> char_func 
> backward
> FAIL: gdb.reverse/finish-reverse.exp: reverse finish from char_func
> FAIL: gdb.reverse/finish-reverse.exp: continue to breakpoint:
> void_func 
> backward
> FAIL: gdb.reverse/finish-reverse.exp: reverse finish from void_func
> Running 
> /data/vries/gdb/src/gdb/testsuite/gdb.reverse/finish-reverse-next.exp 
> ...
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
> LEP 
> call from LEP
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP entry 
> point function call from LEP
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2, at b = 5, 
> call from LEP
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
> LEP 
> call from function body
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from 
> function body
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5,
> from 
> function body
> FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call
> from GEP
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry 
> point function call from GEP
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50, 
> call from GEP
> FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call
> from 
> GEP again
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry 
> point function call from GEP again
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50, 
> call from GEP again
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
> GEP 
> call, from function body
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP call
> from 
> function body
> FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50
> from 
> function body
> Running /data/vries/gdb/src/gdb/testsuite/gdb.btrace/tailcall-
> only.exp ...
> FAIL: gdb.btrace/tailcall-only.exp: reverse-step
> FAIL: gdb.btrace/tailcall-only.exp: up

I believe I have found the issue.  Somewhere along the line, probably
in the code cleanup, the initialization of the new variables in
gdb/infcmd.c got out of order.  Basically, alt_entry_point and
entry_point are initialized to sal.pc.  However, sal has been declared
but not initialized so alt_entry_point and entry_point are always equal
to zero.  That doesn't work so well.  The fix is simple, just need to
move the initialization of the two variables after sal has been
initialized.  

I am still running some tests to make sure everything is OK.  But so
far it looks like the fix works on PowerPC and on one of the X86 boxes
I am testing on.  I am double checking the results on the other X86
box.  I hope to post a fix soon.

This should fix the errors on X86 and Arm.

Sorry for the regression.

                   Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ver2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-20 23:21                                                                                                   ` Carl Love
@ 2023-03-21  3:17                                                                                                     ` Carl Love
  2023-03-21  6:52                                                                                                       ` Ulrich Weigand
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-21  3:17 UTC (permalink / raw)
  To: Tom de Vries, Ulrich Weigand, gdb-patches, Bruno Larsen, pedro
  Cc: luis.machado, cel

Tom, Luis, GDB maintainers:

The recent commit to fix the reverse-finish command on PowerPC
introduced some regression test failures on X86 and Arm.  The following
patch fixes the failures.

The fix has been tested on Power10 and X86.  

Please let me know if this patch is acceptable.  Thanks.

                  Carl 

----------------------------------------
PowerPC: regression fix for reverse-finish command.

The recent commit:

  commit 2a8339b71f37f2d02f5b2194929c9d702ef27223
  Author: Carl Love <cel@us.ibm.com>
  Date:   Thu Mar 9 16:10:18 2023 -0500

   PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-rev\
erse.exp

   PPC64 multiple entry points, a normal entry point and an alternate entry
   point.  The alternate entry point is to setup the Table of Contents (TOC)
   register before continuing at the normal entry point.  When the TOC is
   already valid, the normal entry point is used, this is typically the case.
   The alternate entry point is typically referred to as the global entry
   point (GEP) in IBM.  The normal entry point is typically referred to as
   the local entry point (LEP).
     .....

Is causing regression failures on on PowerPC platforms.  The regression
failures are in tests:

  gdb.reverse/finish-precsave.exp
  gdb.btrace/tailcall.exp
  gdb.mi/mi-reverse.exp
  gdb.btrace/step.exp
  gdb.reverse/until-precsave.exp
  gdb.reverse/finish-reverse.exp
  gdb.btrace/tailcall-only.exp

The issue is in gdb/infcmd.c, function finish_command.  The value of the
two new variables ALT_ENTRY_POINT and ENTRY_POINT are being initializezed
to SAL.PC.  However, SAL has just been declared.  The value of SAL.PC is
zero at this point.  The intialization of ALT_ENTRY_POINT and ENTRY_POINT
needs to be after the initialization of SAL.

This patch moves the initialization of ALT_ENTRY_POINT and ENTRY_POINT
variables to fix the regression failures.

The patch has been tested on Power10 and on X86.
---
 gdb/infcmd.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index f46461512fe..e2032d18564 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1710,8 +1710,8 @@ finish_backward (struct finish_command_fsm *sm)
   struct thread_info *tp = inferior_thread ();
   CORE_ADDR pc;
   CORE_ADDR func_addr;
-  CORE_ADDR alt_entry_point = sal.pc;
-  CORE_ADDR entry_point = alt_entry_point;
+  CORE_ADDR alt_entry_point;
+  CORE_ADDR entry_point;
   frame_info_ptr frame = get_selected_frame (nullptr);
   struct gdbarch *gdbarch = get_frame_arch (frame);
 
@@ -1721,6 +1721,8 @@ finish_backward (struct finish_command_fsm *sm)
     error (_("Cannot find bounds of current function"));
 
   sal = find_pc_line (func_addr, 0);
+  alt_entry_point = sal.pc;
+  entry_point = alt_entry_point;
 
   if (gdbarch_skip_entrypoint_p (gdbarch))
     /* Some architectures, like PowerPC use local and global entry points.
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ver2] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-21  3:17                                                                                                     ` Carl Love
@ 2023-03-21  6:52                                                                                                       ` Ulrich Weigand
  0 siblings, 0 replies; 105+ messages in thread
From: Ulrich Weigand @ 2023-03-21  6:52 UTC (permalink / raw)
  To: gdb-patches, Bruno Larsen, tdevries, cel, pedro; +Cc: luis.machado

Carl Love <cel@us.ibm.com> wrote:

>PowerPC: regression fix for reverse-finish command.

This is OK.

Thanks,
Ulrich


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-01 20:59                                                                                         ` [PATCH 2/2 ] " Carl Love
  2023-03-08 16:19                                                                                           ` [PING] " Carl Love
  2023-03-13 14:16                                                                                           ` Ulrich Weigand
@ 2023-03-24 17:23                                                                                           ` Simon Marchi
  2023-03-24 22:16                                                                                             ` Carl Love
  2 siblings, 1 reply; 105+ messages in thread
From: Simon Marchi @ 2023-03-24 17:23 UTC (permalink / raw)
  To: Carl Love, Tom de Vries, Ulrich Weigand, gdb-patches,
	Bruno Larsen, pedro

On 3/1/23 15:59, Carl Love via Gdb-patches wrote:
> Tom, Ulrich, Bruno, Pedro, GDB maintainers:
> 
> This patch fixes the reverse-finish command on PowerPC.  The command
> now works the same as on other architectures, specifically X86.  There
> are no functional changes for other architectures.  The patch includes
> a new testcase to verify the reverse-finish command works correctly
> with the multiple entry points supported by PowerPC.
> 
> 
> Patch tested on PowerPC and 5th generation X86 with no regression
> failures.
> 
>                   Carl 

Hi Carl,

I don't know if that particular failure has been reported yet, but I see
these failures when running with native-gdbserver or
native-extended-gdbserver:

  $ make check TESTS="gdb.reverse/finish-reverse-next.exp" RUNTESTFLAGS="--target_board=native-gdbserver"
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 LEP call from LEP
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP entry point function call from LEP
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2, at b = 5, call from LEP
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 LEP call from function body
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from function body
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5, from function body
  FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call from GEP
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry point function call from GEP
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50, call from GEP
  FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call from GEP again
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry point function call from GEP again
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50, call from GEP again
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 GEP call, from function body
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP call from function body
  FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50 from function body

Simon

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-24 17:23                                                                                           ` [PATCH 2/2 ] " Simon Marchi
@ 2023-03-24 22:16                                                                                             ` Carl Love
  2023-03-25 12:39                                                                                               ` Simon Marchi
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-24 22:16 UTC (permalink / raw)
  To: Simon Marchi, Tom de Vries, Ulrich Weigand, gdb-patches,
	Bruno Larsen, pedro
  Cc: cel

On Fri, 2023-03-24 at 13:23 -0400, Simon Marchi wrote:
> 

<snip>

> I don't know if that particular failure has been reported yet, but I
> see
> these failures when running with native-gdbserver or
> native-extended-gdbserver:
> 
>   $ make check TESTS="gdb.reverse/finish-reverse-next.exp"
> RUNTESTFLAGS="--target_board=native-gdbserver"
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
> LEP call from LEP
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP entry
> point function call from LEP
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2, at b =
> 5, call from LEP
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
> LEP call from function body
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from
> function body
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5,
> from function body
>   FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call
> from GEP
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry
> point function call from GEP
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b =
> 50, call from GEP
>   FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call
> from GEP again
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry
> point function call from GEP again
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b =
> 50, call from GEP again
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
> GEP call, from function body
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP call
> from function body
>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50
> from function body

Yes, there was a regression failure.  The following was committed to
fix the reported regression issues.

https://sourceware.org/pipermail/gdb-patches/2023-March/198139.html

Are you testing with this fix?

I don't normally run the tests with --target_board=native-gdbserver but
I did try that and it seemed to work for me.  Note I had to also
specify GDBFLAGS to get the test to run.  Specifically, I used the
command:

make check TESTS="gdb.reverse/finish-reverse-next.exp"  RUNTESTFLAGS="GDBFLAGS=' ' --target_board=native-gdbserver "

The test ran fine and reported 40 passes and no errors.
                 
       Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-24 22:16                                                                                             ` Carl Love
@ 2023-03-25 12:39                                                                                               ` Simon Marchi
  2023-03-27 23:59                                                                                                 ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Simon Marchi @ 2023-03-25 12:39 UTC (permalink / raw)
  To: Carl Love, Tom de Vries, Ulrich Weigand, gdb-patches,
	Bruno Larsen, pedro



On 3/24/23 18:16, Carl Love wrote:
> On Fri, 2023-03-24 at 13:23 -0400, Simon Marchi wrote:
>>
> 
> <snip>
> 
>> I don't know if that particular failure has been reported yet, but I
>> see
>> these failures when running with native-gdbserver or
>> native-extended-gdbserver:
>>
>>   $ make check TESTS="gdb.reverse/finish-reverse-next.exp"
>> RUNTESTFLAGS="--target_board=native-gdbserver"
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
>> LEP call from LEP
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP entry
>> point function call from LEP
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2, at b =
>> 5, call from LEP
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
>> LEP call from function body
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from
>> function body
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5,
>> from function body
>>   FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call
>> from GEP
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry
>> point function call from GEP
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b =
>> 50, call from GEP
>>   FAIL: gdb.reverse/finish-reverse-next.exp: function1 GEP call call
>> from GEP again
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP entry
>> point function call from GEP again
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b =
>> 50, call from GEP again
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse-finish function1
>> GEP call, from function body
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP call
>> from function body
>>   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50
>> from function body
> 
> Yes, there was a regression failure.  The following was committed to
> fix the reported regression issues.
> 
> https://sourceware.org/pipermail/gdb-patches/2023-March/198139.html

I also saw these regressions, but they are fixed (by that commit).  This
seems like a different thing.

> Are you testing with this fix?

Yes, and I just tried with today's master, same thing.

> I don't normally run the tests with --target_board=native-gdbserver but
> I did try that and it seemed to work for me.  Note I had to also
> specify GDBFLAGS to get the test to run.  Specifically, I used the
> command:
> 
> make check TESTS="gdb.reverse/finish-reverse-next.exp"  RUNTESTFLAGS="GDBFLAGS=' ' --target_board=native-gdbserver "

That's odd, I never had to do that thing with GDBFLAGS.  What happens
when you don't specify it?

For reference, here's an example failure:

147 reverse-next^M
148 81        b = 5;^M 
149 (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from function body
150 reverse-next^M
151 80        a = 1;^M
152 (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5, from function body

Simon

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-25 12:39                                                                                               ` Simon Marchi
@ 2023-03-27 23:59                                                                                                 ` Carl Love
  2023-03-28  1:19                                                                                                   ` Simon Marchi
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-27 23:59 UTC (permalink / raw)
  To: Simon Marchi, Tom de Vries, Ulrich Weigand, gdb-patches,
	Bruno Larsen, pedro
  Cc: cel

Simon:

On Sat, 2023-03-25 at 08:39 -0400, Simon Marchi wrote:
> 

<snip>

> > 
> > Yes, there was a regression failure.  The following was committed
> > to
> > fix the reported regression issues.
> > 
> > https://sourceware.org/pipermail/gdb-patches/2023-March/198139.html 
> 
> I also saw these regressions, but they are fixed (by that
> commit).  This
> seems like a different thing.
> 
> > Are you testing with this fix?
> 
> Yes, and I just tried with today's master, same thing.
> 
> > I don't normally run the tests with --target_board=native-gdbserver 
> > but
> > I did try that and it seemed to work for me.  Note I had to also
> > specify GDBFLAGS to get the test to run.  Specifically, I used the
> > command:
> > 
> > make check TESTS="gdb.reverse/finish-reverse-
> > next.exp"  RUNTESTFLAGS="GDBFLAGS=' ' --target_board=native-
> > gdbserver "
> 
> That's odd, I never had to do that thing with GDBFLAGS.  What happens
> when you don't specify it?

When I run on Power 10 without GDBFLAGS I get the message:

   make check TESTS="gdb.reverse/finish-reverse-next.exp"  RUNTESTFLAGS=" --target_board=native-gdbserver " 

   <snip>

   ERROR: tcl error sourcing board description file for target /home.../gdb/testsuite/boards/gdbserver-base.exp.
   can't read "GDBFLAGS": no such variable
   can't read "GDBFLAGS": no such variable
       while executing
   "set GDBFLAGS "${GDBFLAGS} -iex \"set auto-connect-native-target off\"""
       (file "/home.../gdb/testsuite/boards/gdbserver-base.exp" line 35)
       invoked from within
   "source /home.../gdb/testsuite/boards/gdbserver-base.exp"
       ("uplevel" body line 1)
       invoked from within
   "uplevel #0 source /home/.../gdb/testsuite/boards/gdbserver-base.exp"
       invoked from within
   "catch "uplevel #0 source $filename" error"
   make[5]: *** [Makefile:1829: check-DEJAGNU] Error 1

> 
> For reference, here's an example failure:
> 
> 147 reverse-next^M
> 148 81        b = 5;^M 
> 149 (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1
> LEP from function body
> 150 reverse-next^M
> 151 80        a = 1;^M
> 152 (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2
> at b = 5, from function body

You didn't mention what platform you are running on, but I am guessing
X86.  I created a little run script to run the test with and without
the --target-board argument on Power 10.  Here is my script.

    more check-reverse

   echo " "
   echo reverse.exp
   rm testsuite/gdb.log
   make check RUNTESTFLAGS='GDB=/home/carll/bin/gdb   gdb.reverse/finish-reverse-next.exp   ' > out-reverse-next
   grep "of expected passes" testsuite/gdb.log
   grep "of unexpected failures" testsuite/gdb.log
   mv testsuite/gdb.log testsuite/gdb.log-reverse-next


   echo " "
   echo reverse.exp
   rm testsuite/gdb.log
   make check TESTS="gdb.reverse/finish-reverse-next.exp"  RUNTESTFLAGS="GDBFLAGS=' ' --target_board=native-gdbserver "  > out-reverse-next-gdbserver
   grep "of expected passes" testsuite/gdb.log
   grep "of unexpected failures" testsuite/gdb.log
   mv testsuite/gdb.log testsuite/gdb.log-reverse-next-gdbserver

So, assuming you are on X86, I copied the script to my X86 box and tried it out there as well.

I ran the script in the top of the build directory.  For the first test
without --target_board I get the results:

   Using /usr/share/dejagnu/config/unix.exp as generic interface file for target.
      Using /.../gdb/testsuite/config/unix.exp as tool-and-target-specific interface file.
      Running /.../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/gdb.reverse/finish-reverse-next.exp ...

                   === gdb Summary ===

      # of expected passes            40
      gdb version  14.0.50.20230324-git -nw -nx -iex "set height 0" -iex "set width 0"

                   === gdb Summary ===

      # of expected passes            40
      gdb version  14.0.50.20230324-git -nw -nx -iex "set height 0" -iex "set width 0"

The second test with the --target_board I get a number of failures and
never actually get to run the finish-reverse-next test.  The output I
see is:

   Running target native-gdbserver
   Using /usr/share/dejagnu/baseboards/native-gdbserver.exp as board description file for target.
   Using /home/carll/GDB/binutils-gdb-finish-precsave-PPC-Only/gprofng/testsuite/config/default.exp as tool-and-target-specific interface file.
   Running /home/carll/GDB/binutils-gdb-finish-precsave-PPC-Only/gprofng/testsuite/gprofng.display/display.exp ...
   ERROR: comparison of results in mttest failed
   ERROR: comparison of results in mttest failed
   ERROR: comparison of results in synprog failed
   ERROR: comparison of results in synprog failed

   		=== gprofng Summary ===

   # of unresolved testcases       4
   # of unsupported tests          1
   make[4]: Leaving directory '/home/.../gprofng'
   make[3]: Leaving directory '/home/.../gprofng'
   make[2]: Leaving directory '/home/.../gprofng'
   make[1]: Leaving directory '/home/...'

So, tried changing the paths in the script from gdb/testscript to
testscript and then ran the script in the subdirectory gdb.  When I do
that, I get the same results for the first test as I saw befor.  Now,
the second test with --target_board runs and I get the following
output:

   ...
   Using /home/.../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/boards/../boards/gdbserver-base.exp as board de
   scription file for target.
   Using /home/.../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/boards/../boards/local-board.exp as board description file for target.
   Using /home/carll/GDB/build-finish-precsave-PPC-Only/gdb/testsuite/../../../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/config/gdbserver.exp as tool-and-target-specifi
   c interface file.
   Running /home/carll/GDB/build-finish-precsave-PPC-Only/gdb/testsuite/../../../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/gdb.reverse/finish-reverse-next.exp ...
   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from function body
   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5, from function body
   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP call from function body
   FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50 from function body

   		=== gdb Summary ===

   # of expected passes		36
   # of unexpected failures	4

which appears to match the failures you saw.  Why the --target-board
argument seems to make a difference is a mystery to me at this point!!

I can see what what happens...  So, when you do a reverse-finish, gdb
stops at the branch instruction for the function call.  Then when you
do a reverse-next and gdb stops at the beginning of the same source
code line.  This is the expected behavior for gdb per the discussion we
had a few months ago.  Hence in the test file we have:

   # The reverse-finish command should stop on the function call instruction                              
   # which is the last instruction in the source code line.  A reverse-next                               
   # instruction should then stop at the first instruction in the same source                             
   # code line.  Another revers-next instruction stops at the previous source                             
   # code line.                                                                                           
   gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
       "reverse-finish function1 LEP call from function body"
   gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
       "reverse next 1 LEP from function body"
   gdb_test "reverse-next" ".*b = 5;.*" \
       "reverse next 2 at b = 5, from function body"

The test is looking to see that it is at source line function1 (a, b)
after both reverse-finish and the reverse-next commands.

Looking in the output file for the run with and without the --target-
board on X86, we see:

without the target board specified:


   step
   function1 (a=1, b=5) at /home/carll/.../gdb/testsuite/gdb.reverse/finish-reverse-next.c:51
   51        int ret = 0;
   (gdb) PASS: gdb.reverse/finish-reverse-next.exp: step test 1

   reverse-finish
   Run back to call of #0  function1 (a=1, b=5) at /home/carll/..../gdb/testsuite/gdb.reverse/finish-reverse-next.c:51
   0x00005555555551cb in main (argc=1, argv=0x7fffffffde88) at /home/carll/.../gdb/testsuite/gdb.reverse/finish-reverse-next.c:83^M
   83        function1 (a, b);   // CALL VIA LEP
   (gdb) PASS: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 LEP call from function body

   reverse-next
   83        function1 (a, b);   // CALL VIA LEP
   (gdb) PASS: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from function body reverse-next
   81        b = 5;

   reverse-continue
   Continuing.

   No more reverse-execution history.

   We see the reverse-finish and the reverse-next both stop at function1
   (a, b) as expected.

   But with  --target-board, we see:

   step
   function1 (a=1, b=5) at /home/carll/..../gdb/testsuite/gdb.reverse/finish-reverse-next.c:51
   51        int ret = 0;
   (gdb) PASS: gdb.reverse/finish-reverse-next.exp: step test 1

   reverse-finish
   Run back to call of #0  function1 (a=1, b=5) at /home/carll/..../gdb/testsuite/gdb.reverse/finish-reverse-next.c:51
   main (argc=1, argv=0x7fffffffde88) at /home/carll/.../gdb/testsuite/gdb.reverse/finish-reverse-next.c:83
   83        function1 (a, b);   // CALL VIA LEP
   (gdb) PASS: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 LEP call from function body

   reverse-next
   81        b = 5;
   (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from function body

   reverse-next
   80        a = 1;
   (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5, from function body

   reverse-continue
   Continuing.

It appears the reverse-finish stopped at the beginning of the source
line, not the function call as expected, because the reverse-next stops
at the previous source line not the same source line as expected.  I
think it would only do that if GDB was at the beginning of the source
line after the reverse-finish command is done.  The issue "appears to
be" that the reverse-finish command behaves differently with the --
target_board???

I am at a loss as to why using gdbserver causes this change in the
behavior of the test.  Unfortunately, I have never looked at how
gdbserver works so I don't know what the issue might be.  

I tried rewinding my gdb tree on X86 to the commit
  
commit 334d405c2ac395fca67b952affb20893002d969f (HEAD)
Author: Carl Love <cel@us.ibm.com>
Date:   Wed Mar 1 11:45:43 2023 -0500

    Move step_until procedure
    ....

which is the commit before the fix for the reverse-finish command on
Power10.  Note, the finish-reverse-next is a new test that is added
with the Power 10 reverse-finish command fix.  I had to make a copy of 
finish-reverse-next.c and finish-reverse-next.exp before rewinding the
source tree and restoring them after the rewind.  I rebuilt gdb without
the PowerPC fix.  When I run my script I see the exact same behavior on
X86, i.e. the first test works fine, the second test fails.  So, it
looks to me like the issue is independent of the changes made in my
commit for Power10.  

It would probably be good if you can try to reproduce the failure
without the Power10 fix.  Note, you do need the patch to move the
step_until proceedure so when you restore the test it will work.  The
test is dependent on that commit.

Let me know if you can verify the test fails without the Power10 fix
and with --target_board.  

When I run the above script on Power 10, the first test runs fine and
is the only test that is run.  The second test results in running a
whole bunch of tests in addition to finish-reverse-next.  I have to
search thru the log file to find where the test ran.  No errors are
reported for the finish-reverse-next test.  But I do see errors in
other tests.  Actually, the output looks like what I get when I run
"make check".  I looked to see if I could find an error about the
arguments that would explain why the test "appears" to ignore the
request to run one test and runs what appears to be everything.  I
don't see reported errors or warnings.  I also tried moving the script
to the gdb build directory/gdb, like what I did on X86, and tweaked the
paths in the script.  Again, the first test runs just fine and appears
to be the only test that is run.  The second test seems to actually run
all of the tests again.  When I look in the log file, again I can see
where finish-reverse-next ran and doesn't appear to generate any errors
but I am seeing all these other tests that ran.

In summary, there seems to be an issue with using the --target_board
argument.  On X86, the reverse-finish command seems to work a little
different with and without the --target-board command.  This is
independent of the Power 10 reverse-finish patch.  On Power 10, the use
of the --target_board option seems to cause all tests to run not just
the one requested.  Maybe there is something wrong with the make
command in the test file that explains the behavior on Power 10??
Unfortunately, I have not worked on gdbserver so I really have no idea
what is going on.

                        Carl 






^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-27 23:59                                                                                                 ` Carl Love
@ 2023-03-28  1:19                                                                                                   ` Simon Marchi
  2023-03-28 15:17                                                                                                     ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Simon Marchi @ 2023-03-28  1:19 UTC (permalink / raw)
  To: Carl Love, Tom de Vries, Ulrich Weigand, gdb-patches,
	Bruno Larsen, pedro

On 3/27/23 19:59, Carl Love wrote:
> Simon:
> 
> On Sat, 2023-03-25 at 08:39 -0400, Simon Marchi wrote:
>>
> 
> <snip>
> 
>>>
>>> Yes, there was a regression failure.  The following was committed
>>> to
>>> fix the reported regression issues.
>>>
>>> https://sourceware.org/pipermail/gdb-patches/2023-March/198139.html 
>>
>> I also saw these regressions, but they are fixed (by that
>> commit).  This
>> seems like a different thing.
>>
>>> Are you testing with this fix?
>>
>> Yes, and I just tried with today's master, same thing.
>>
>>> I don't normally run the tests with --target_board=native-gdbserver 
>>> but
>>> I did try that and it seemed to work for me.  Note I had to also
>>> specify GDBFLAGS to get the test to run.  Specifically, I used the
>>> command:
>>>
>>> make check TESTS="gdb.reverse/finish-reverse-
>>> next.exp"  RUNTESTFLAGS="GDBFLAGS=' ' --target_board=native-
>>> gdbserver "
>>
>> That's odd, I never had to do that thing with GDBFLAGS.  What happens
>> when you don't specify it?
> 
> When I run on Power 10 without GDBFLAGS I get the message:
> 
>    make check TESTS="gdb.reverse/finish-reverse-next.exp"  RUNTESTFLAGS=" --target_board=native-gdbserver " 
> 
>    <snip>
> 
>    ERROR: tcl error sourcing board description file for target /home.../gdb/testsuite/boards/gdbserver-base.exp.
>    can't read "GDBFLAGS": no such variable
>    can't read "GDBFLAGS": no such variable
>        while executing
>    "set GDBFLAGS "${GDBFLAGS} -iex \"set auto-connect-native-target off\"""
>        (file "/home.../gdb/testsuite/boards/gdbserver-base.exp" line 35)
>        invoked from within
>    "source /home.../gdb/testsuite/boards/gdbserver-base.exp"
>        ("uplevel" body line 1)
>        invoked from within
>    "uplevel #0 source /home/.../gdb/testsuite/boards/gdbserver-base.exp"
>        invoked from within
>    "catch "uplevel #0 source $filename" error"
>    make[5]: *** [Makefile:1829: check-DEJAGNU] Error 1
> 
>>
>> For reference, here's an example failure:
>>
>> 147 reverse-next^M
>> 148 81        b = 5;^M 
>> 149 (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1
>> LEP from function body
>> 150 reverse-next^M
>> 151 80        a = 1;^M
>> 152 (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2
>> at b = 5, from function body
> 
> You didn't mention what platform you are running on, but I am guessing
> X86.  I created a little run script to run the test with and without
> the --target-board argument on Power 10.  Here is my script.
> 
>     more check-reverse
> 
>    echo " "
>    echo reverse.exp
>    rm testsuite/gdb.log
>    make check RUNTESTFLAGS='GDB=/home/carll/bin/gdb   gdb.reverse/finish-reverse-next.exp   ' > out-reverse-next
>    grep "of expected passes" testsuite/gdb.log
>    grep "of unexpected failures" testsuite/gdb.log
>    mv testsuite/gdb.log testsuite/gdb.log-reverse-next
> 
> 
>    echo " "
>    echo reverse.exp
>    rm testsuite/gdb.log
>    make check TESTS="gdb.reverse/finish-reverse-next.exp"  RUNTESTFLAGS="GDBFLAGS=' ' --target_board=native-gdbserver "  > out-reverse-next-gdbserver
>    grep "of expected passes" testsuite/gdb.log
>    grep "of unexpected failures" testsuite/gdb.log
>    mv testsuite/gdb.log testsuite/gdb.log-reverse-next-gdbserver
> 
> So, assuming you are on X86, I copied the script to my X86 box and tried it out there as well.
> 
> I ran the script in the top of the build directory.  For the first test
> without --target_board I get the results:
> 
>    Using /usr/share/dejagnu/config/unix.exp as generic interface file for target.
>       Using /.../gdb/testsuite/config/unix.exp as tool-and-target-specific interface file.
>       Running /.../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/gdb.reverse/finish-reverse-next.exp ...
> 
>                    === gdb Summary ===
> 
>       # of expected passes            40
>       gdb version  14.0.50.20230324-git -nw -nx -iex "set height 0" -iex "set width 0"
> 
>                    === gdb Summary ===
> 
>       # of expected passes            40
>       gdb version  14.0.50.20230324-git -nw -nx -iex "set height 0" -iex "set width 0"
> 
> The second test with the --target_board I get a number of failures and
> never actually get to run the finish-reverse-next test.  The output I
> see is:
> 
>    Running target native-gdbserver
>    Using /usr/share/dejagnu/baseboards/native-gdbserver.exp as board description file for target.
>    Using /home/carll/GDB/binutils-gdb-finish-precsave-PPC-Only/gprofng/testsuite/config/default.exp as tool-and-target-specific interface file.
>    Running /home/carll/GDB/binutils-gdb-finish-precsave-PPC-Only/gprofng/testsuite/gprofng.display/display.exp ...
>    ERROR: comparison of results in mttest failed
>    ERROR: comparison of results in mttest failed
>    ERROR: comparison of results in synprog failed
>    ERROR: comparison of results in synprog failed
> 
>    		=== gprofng Summary ===
> 
>    # of unresolved testcases       4
>    # of unsupported tests          1
>    make[4]: Leaving directory '/home/.../gprofng'
>    make[3]: Leaving directory '/home/.../gprofng'
>    make[2]: Leaving directory '/home/.../gprofng'
>    make[1]: Leaving directory '/home/...'
> 
> So, tried changing the paths in the script from gdb/testscript to
> testscript and then ran the script in the subdirectory gdb.  When I do
> that, I get the same results for the first test as I saw befor.  Now,
> the second test with --target_board runs and I get the following
> output:
> 
>    ...
>    Using /home/.../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/boards/../boards/gdbserver-base.exp as board de
>    scription file for target.
>    Using /home/.../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/boards/../boards/local-board.exp as board description file for target.
>    Using /home/carll/GDB/build-finish-precsave-PPC-Only/gdb/testsuite/../../../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/config/gdbserver.exp as tool-and-target-specifi
>    c interface file.
>    Running /home/carll/GDB/build-finish-precsave-PPC-Only/gdb/testsuite/../../../binutils-gdb-finish-precsave-PPC-Only/gdb/testsuite/gdb.reverse/finish-reverse-next.exp ...
>    FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from function body
>    FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5, from function body
>    FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 GEP call from function body
>    FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 50 from function body
> 
>    		=== gdb Summary ===
> 
>    # of expected passes		36
>    # of unexpected failures	4
> 
> which appears to match the failures you saw.  Why the --target-board
> argument seems to make a difference is a mystery to me at this point!!

Ahh, that must be it.  You were running the make check at the top-level.
We pretty much always run it inside gdb/ or gdb/testsuite/.

> I can see what what happens...  So, when you do a reverse-finish, gdb
> stops at the branch instruction for the function call.  Then when you
> do a reverse-next and gdb stops at the beginning of the same source
> code line.  This is the expected behavior for gdb per the discussion we
> had a few months ago.  Hence in the test file we have:
> 
>    # The reverse-finish command should stop on the function call instruction                              
>    # which is the last instruction in the source code line.  A reverse-next                               
>    # instruction should then stop at the first instruction in the same source                             
>    # code line.  Another revers-next instruction stops at the previous source                             
>    # code line.                                                                                           
>    gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
>        "reverse-finish function1 LEP call from function body"
>    gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
>        "reverse next 1 LEP from function body"
>    gdb_test "reverse-next" ".*b = 5;.*" \
>        "reverse next 2 at b = 5, from function body"
> 
> The test is looking to see that it is at source line function1 (a, b)
> after both reverse-finish and the reverse-next commands.
> 
> Looking in the output file for the run with and without the --target-
> board on X86, we see:
> 
> without the target board specified:
> 
> 
>    step
>    function1 (a=1, b=5) at /home/carll/.../gdb/testsuite/gdb.reverse/finish-reverse-next.c:51
>    51        int ret = 0;
>    (gdb) PASS: gdb.reverse/finish-reverse-next.exp: step test 1
> 
>    reverse-finish
>    Run back to call of #0  function1 (a=1, b=5) at /home/carll/..../gdb/testsuite/gdb.reverse/finish-reverse-next.c:51
>    0x00005555555551cb in main (argc=1, argv=0x7fffffffde88) at /home/carll/.../gdb/testsuite/gdb.reverse/finish-reverse-next.c:83^M
>    83        function1 (a, b);   // CALL VIA LEP
>    (gdb) PASS: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 LEP call from function body
> 
>    reverse-next
>    83        function1 (a, b);   // CALL VIA LEP
>    (gdb) PASS: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from function body reverse-next
>    81        b = 5;
> 
>    reverse-continue
>    Continuing.
> 
>    No more reverse-execution history.
> 
>    We see the reverse-finish and the reverse-next both stop at function1
>    (a, b) as expected.
> 
>    But with  --target-board, we see:
> 
>    step
>    function1 (a=1, b=5) at /home/carll/..../gdb/testsuite/gdb.reverse/finish-reverse-next.c:51
>    51        int ret = 0;
>    (gdb) PASS: gdb.reverse/finish-reverse-next.exp: step test 1
> 
>    reverse-finish
>    Run back to call of #0  function1 (a=1, b=5) at /home/carll/..../gdb/testsuite/gdb.reverse/finish-reverse-next.c:51
>    main (argc=1, argv=0x7fffffffde88) at /home/carll/.../gdb/testsuite/gdb.reverse/finish-reverse-next.c:83
>    83        function1 (a, b);   // CALL VIA LEP
>    (gdb) PASS: gdb.reverse/finish-reverse-next.exp: reverse-finish function1 LEP call from function body
> 
>    reverse-next
>    81        b = 5;
>    (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 1 LEP from function body
> 
>    reverse-next
>    80        a = 1;
>    (gdb) FAIL: gdb.reverse/finish-reverse-next.exp: reverse next 2 at b = 5, from function body
> 
>    reverse-continue
>    Continuing.
> 
> It appears the reverse-finish stopped at the beginning of the source
> line, not the function call as expected, because the reverse-next stops
> at the previous source line not the same source line as expected.  I
> think it would only do that if GDB was at the beginning of the source
> line after the reverse-finish command is done.  The issue "appears to
> be" that the reverse-finish command behaves differently with the --
> target_board???
> 
> I am at a loss as to why using gdbserver causes this change in the
> behavior of the test.  Unfortunately, I have never looked at how
> gdbserver works so I don't know what the issue might be.  
> 
> I tried rewinding my gdb tree on X86 to the commit
>   
> commit 334d405c2ac395fca67b952affb20893002d969f (HEAD)
> Author: Carl Love <cel@us.ibm.com>
> Date:   Wed Mar 1 11:45:43 2023 -0500
> 
>     Move step_until procedure
>     ....
> 
> which is the commit before the fix for the reverse-finish command on
> Power10.  Note, the finish-reverse-next is a new test that is added
> with the Power 10 reverse-finish command fix.  I had to make a copy of 
> finish-reverse-next.c and finish-reverse-next.exp before rewinding the
> source tree and restoring them after the rewind.  I rebuilt gdb without
> the PowerPC fix.  When I run my script I see the exact same behavior on
> X86, i.e. the first test works fine, the second test fails.  So, it
> looks to me like the issue is independent of the changes made in my
> commit for Power10.  
> 
> It would probably be good if you can try to reproduce the failure
> without the Power10 fix.  Note, you do need the patch to move the
> step_until proceedure so when you restore the test it will work.  The
> test is dependent on that commit.
> 
> Let me know if you can verify the test fails without the Power10 fix
> and with --target_board.  
> 
> When I run the above script on Power 10, the first test runs fine and
> is the only test that is run.  The second test results in running a
> whole bunch of tests in addition to finish-reverse-next.  I have to
> search thru the log file to find where the test ran.  No errors are
> reported for the finish-reverse-next test.  But I do see errors in
> other tests.  Actually, the output looks like what I get when I run
> "make check".  I looked to see if I could find an error about the
> arguments that would explain why the test "appears" to ignore the
> request to run one test and runs what appears to be everything.  I
> don't see reported errors or warnings.  I also tried moving the script
> to the gdb build directory/gdb, like what I did on X86, and tweaked the
> paths in the script.  Again, the first test runs just fine and appears
> to be the only test that is run.  The second test seems to actually run
> all of the tests again.  When I look in the log file, again I can see
> where finish-reverse-next ran and doesn't appear to generate any errors
> but I am seeing all these other tests that ran.
> 
> In summary, there seems to be an issue with using the --target_board
> argument.  On X86, the reverse-finish command seems to work a little
> different with and without the --target-board command.  This is
> independent of the Power 10 reverse-finish patch.  On Power 10, the use
> of the --target_board option seems to cause all tests to run not just
> the one requested.  Maybe there is something wrong with the make
> command in the test file that explains the behavior on Power 10??
> Unfortunately, I have not worked on gdbserver so I really have no idea
> what is going on.

Indeed, it just looks like a pre-existing issue that the new test has
uncovered.  Don't worry, it happens all the time in GDB.

I was able to reproduce by hand, and used the "maintenance print
record-instruction" command to print the recorded instructions in both
cases.  In the case of native debugging, these are all the recorded
instructions between the beginning of the function call line to the end
of the recording:

    (gdb) maintenance print record-instruction -9
    Register rdx changed: 140737488346408
[1] Register rip changed: (void (*)()) 0x5555555551a5 <main+40>
    (gdb) maintenance print record-instruction -8
    Register rax changed: 93824992235839
    Register rip changed: (void (*)()) 0x5555555551a8 <main+43>
    (gdb) maintenance print record-instruction -7
    Register rsi changed: 140737488346392
    Register rip changed: (void (*)()) 0x5555555551ab <main+46>
    (gdb) maintenance print record-instruction -6
    Register rdi changed: 1
    Register rip changed: (void (*)()) 0x5555555551ad <main+48>
    (gdb) maintenance print record-instruction -5
    Register rsp changed: (void *) 0x7fffffffdbe0
    8 bytes of memory at address 0x00007fffffffdbd8 changed from: 00 00 00 00 00 00 00 00
[2] Register rip changed: (void (*)()) 0x5555555551af <main+50>
    (gdb) maintenance print record-instruction -4
    Register rsp changed: (void *) 0x7fffffffdbd8
    8 bytes of memory at address 0x00007fffffffdbd0 changed from: 00 00 00 00 00 00 00 00
    Register rip changed: (void (*)()) 0x55555555513f <function1>
    (gdb) maintenance print record-instruction -3
    Register rbp changed: (void *) 0x7fffffffdc00
    Register rip changed: (void (*)()) 0x555555555140 <function1+1>
    (gdb) maintenance print record-instruction -2
    Register rsp changed: (void *) 0x7fffffffdbd0
    Register eflags changed: [ IF ]
    Register rip changed: (void (*)()) 0x555555555143 <function1+4>
    (gdb) maintenance print record-instruction -1
    4 bytes of memory at address 0x00007fffffffdbbc changed from: 00 00 00 00
    Register rip changed: (void (*)()) 0x555555555147 <function1+8>
    (gdb) maintenance print record-instruction 0
    4 bytes of memory at address 0x00007fffffffdbb8 changed from: 00 00 00 00
[3] Register rip changed: (void (*)()) 0x55555555514a <function1+11>

With gdbserver:

    (gdb) maintenance print record-instruction -5
    Register rdx changed: 140737488346600
[1] Register rip changed: (void (*)()) 0x5555555551a5 <main+40>
    (gdb) maintenance print record-instruction -4
    Register rsp changed: (void *) 0x7fffffffdc98
    8 bytes of memory at address 0x00007fffffffdc90 changed from: 00 00 00 00 00 00 00 00
    Register rip changed: (void (*)()) 0x55555555513f <function1>
    (gdb) maintenance print record-instruction -3
    Register rbp changed: (void *) 0x7fffffffdcc0
    Register rip changed: (void (*)()) 0x555555555140 <function1+1>
    (gdb) maintenance print record-instruction -2
    Register rsp changed: (void *) 0x7fffffffdc90
    Register eflags changed: [ PF IF ]
    Register rip changed: (void (*)()) 0x555555555143 <function1+4>
    (gdb) maintenance print record-instruction -1
    4 bytes of memory at address 0x00007fffffffdc7c changed from: 00 00 00 00
    Register rip changed: (void (*)()) 0x555555555147 <function1+8>
    (gdb) maintenance print record-instruction 0
    4 bytes of memory at address 0x00007fffffffdc78 changed from: 00 00 00 00
[3] Register rip changed: (void (*)()) 0x55555555514a <function1+11>

The important points are:

[1] Beginning of function call line
[2] Call instruction
[3] Starting point

We see that there are fewer recorded instructions with gdbserver.
Seeing this, I thought of the range-stepping feature of the remote
protocol.  This allows GDB to tell GDBserver to step a thread as long as
it's within a certain range of PC.  This is useful when stepping over a
source line, to avoid the back and forth of GDB asking GDBserver to step
instructions repeatedly.

If you enable "set debug remote 1" while doing the "step" command, when
connected to GDBserver, you'll see this resumption packet:


  [remote] Sending packet: $vCont;r5555555551a5,5555555551b4:p3b326.3b326;c:p3b326.-1#67

This tells GDBserver to resume the thread 3b326 (thread id in hex),
single-stepping it as long as within those PCs.  Because of that, GDB
never sees the individual steps in that region:

    83        function1 (a, b);   // CALL VIA LEP
       0x00005555555551a5 <+40>:    mov    -0x10(%rbp),%edx
       0x00005555555551a8 <+43>:    mov    -0xc(%rbp),%eax
       0x00005555555551ab <+46>:    mov    %edx,%esi
       0x00005555555551ad <+48>:    mov    %eax,%edi
       0x00005555555551af <+50>:    call   0x55555555513f <function1>

And therefore, GDB's record-full target doesn't record the individual
steps.  The native linux target doesn't use range stepping (it reports
stops for all individual steps).

To confirm the theory, I added a:

   gdb_test "set range-stepping off"

somewhere near the beginning of your test, and it makes the test pass
with native-gdbserver.

If we want recording to work the same with process targets using
range-stepping and those that don't, maybe GDB should avoid using
range-stepping when the record-full target is in effect?

Simon

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-28  1:19                                                                                                   ` Simon Marchi
@ 2023-03-28 15:17                                                                                                     ` Carl Love
  2023-03-28 15:38                                                                                                       ` Simon Marchi
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-03-28 15:17 UTC (permalink / raw)
  To: Simon Marchi, Tom de Vries, Ulrich Weigand, gdb-patches,
	Bruno Larsen, pedro
  Cc: cel

Simon:

On Mon, 2023-03-27 at 21:19 -0400, Simon Marchi wrote:
> To confirm the theory, I added a:
> 
>    gdb_test "set range-stepping off"
> 
> somewhere near the beginning of your test, and it makes the test pass
> with native-gdbserver.
> 
> If we want recording to work the same with process targets using
> range-stepping and those that don't, maybe GDB should avoid using
> range-stepping when the record-full target is in effect?

We could just update the test to include gdb_test "set range-stepping
off" with a brief explanation of the issue. This would have a minimal
impact on performance of this test and no performance degradation for
any other tests.  It sounds like this would fix the issue for just this
test. 

It sounds like disabling range-stepping when record-full is enabled
would be the more general fix for the issue.  Not sure if there are
other tests where this issue occurs.  Doing the more general fix would
probably have some performance impact on the other tests that need to
use record-full. I can't really say how much of an impact it would be.

Thanks for the insight on how gdbserver works.  At this point, I have
not looked into that part of gdb.  

                            Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-28 15:17                                                                                                     ` Carl Love
@ 2023-03-28 15:38                                                                                                       ` Simon Marchi
  2023-07-20 12:01                                                                                                         ` Bruno Larsen
  0 siblings, 1 reply; 105+ messages in thread
From: Simon Marchi @ 2023-03-28 15:38 UTC (permalink / raw)
  To: Carl Love, Tom de Vries, Ulrich Weigand, gdb-patches,
	Bruno Larsen, pedro

On 3/28/23 11:17, Carl Love wrote:
> Simon:
> 
> On Mon, 2023-03-27 at 21:19 -0400, Simon Marchi wrote:
>> To confirm the theory, I added a:
>>
>>    gdb_test "set range-stepping off"
>>
>> somewhere near the beginning of your test, and it makes the test pass
>> with native-gdbserver.
>>
>> If we want recording to work the same with process targets using
>> range-stepping and those that don't, maybe GDB should avoid using
>> range-stepping when the record-full target is in effect?
> 
> We could just update the test to include gdb_test "set range-stepping
> off" with a brief explanation of the issue. This would have a minimal
> impact on performance of this test and no performance degradation for
> any other tests.  It sounds like this would fix the issue for just this
> test. 
> 
> It sounds like disabling range-stepping when record-full is enabled
> would be the more general fix for the issue.  Not sure if there are
> other tests where this issue occurs.  Doing the more general fix would
> probably have some performance impact on the other tests that need to
> use record-full. I can't really say how much of an impact it would be.

It depends on what the goal is.  In general, we try to minimize the
differences in behavior when debugging native vs debugging remote.  So,
if we say that it's a bug that the record-full target doesn't see all
the intermediary steps, then putting "set range-stepping off" in that
test would just be papering over the bug.  I think the correct thing to
do would be to fix GDB.  And yes there will be a performance impact when
using remote debugging + record-full, but if that's what's needed to get
correct behavior...

Some ideas to implement this:

 - Add a target method supports_range_stepping, record-full would
   implement it and return false.  The default would be true.
 - record-full's resume method could clean the resumed thread's
   may_range_step flag.

I'm open to other ideas.  Note that we don't want to disable range
stepping for other record implementations (only btrace, currently), I
don't think that one is affected by the problem (the hardware should
record all intermediary steps in any case).

Simon

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-03-28 15:38                                                                                                       ` Simon Marchi
@ 2023-07-20 12:01                                                                                                         ` Bruno Larsen
  2023-07-20 14:45                                                                                                           ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-07-20 12:01 UTC (permalink / raw)
  To: Simon Marchi, Carl Love, Tom de Vries, Ulrich Weigand,
	gdb-patches, pedro

On 28/03/2023 17:38, Simon Marchi wrote:
> On 3/28/23 11:17, Carl Love wrote:
>> Simon:
>>
>> On Mon, 2023-03-27 at 21:19 -0400, Simon Marchi wrote:
>>> To confirm the theory, I added a:
>>>
>>>     gdb_test "set range-stepping off"
>>>
>>> somewhere near the beginning of your test, and it makes the test pass
>>> with native-gdbserver.
>>>
>>> If we want recording to work the same with process targets using
>>> range-stepping and those that don't, maybe GDB should avoid using
>>> range-stepping when the record-full target is in effect?
>> We could just update the test to include gdb_test "set range-stepping
>> off" with a brief explanation of the issue. This would have a minimal
>> impact on performance of this test and no performance degradation for
>> any other tests.  It sounds like this would fix the issue for just this
>> test.
>>
>> It sounds like disabling range-stepping when record-full is enabled
>> would be the more general fix for the issue.  Not sure if there are
>> other tests where this issue occurs.  Doing the more general fix would
>> probably have some performance impact on the other tests that need to
>> use record-full. I can't really say how much of an impact it would be.
> It depends on what the goal is.  In general, we try to minimize the
> differences in behavior when debugging native vs debugging remote.  So,
> if we say that it's a bug that the record-full target doesn't see all
> the intermediary steps, then putting "set range-stepping off" in that
> test would just be papering over the bug.  I think the correct thing to
> do would be to fix GDB.  And yes there will be a performance impact when
> using remote debugging + record-full, but if that's what's needed to get
> correct behavior...
>
> Some ideas to implement this:
>
>   - Add a target method supports_range_stepping, record-full would
>     implement it and return false.  The default would be true.
>   - record-full's resume method could clean the resumed thread's
>     may_range_step flag.
>
> I'm open to other ideas.  Note that we don't want to disable range
> stepping for other record implementations (only btrace, currently), I
> don't think that one is affected by the problem (the hardware should
> record all intermediary steps in any case).
>
> Simon
>
Sorry for possibly necromancing this thread, but I decided to look into 
gdb.reverse failures when testing with clang and the same issue occurs 
as with gdbserver. I decided to take a look and re-read old messages and 
what Pedro actually said in that thread is a bit confusing, because 
there were multiple intertwined issues being discussed. Looking at this 
email 
(https://sourceware.org/pipermail/gdb-patches/2023-January/196130.html) 
he does mention that GDB should not stop in the same line when a 
reverse-step or reverse-next is used. Because of that, I believe that 
the behavior that the test expects is actually incorrect, and we should 
try and fix this.

Looking at the state of the program when it is compiled with GCC we get:

➜  gdb ./gdb -q 
testsuite/outputs/gdb.reverse/finish-reverse-next/finish-reverse-next 
-ex start -ex record
Reading symbols from 
testsuite/outputs/gdb.reverse/finish-reverse-next/finish-reverse-next...
Temporary breakpoint 1 at 0x401176: file 
/home/blarsen/Documents/fsf_build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.revers3/finish-reverse-next.c, 
line 76.
Starting program: 
/home/blarsen/Documents/fsf_build/gdb/testsuite/outputs/gdb.reverse/finish-reverse-next/finish-reverse-next
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffde78)
     at 
/home/blarsen/Documents/fsf_build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.reverse/finish-reverse-next.c:76
76        int (*funp) (int, int) = &function1;
(gdb) until 83
main (argc=1, argv=0x7fffffffde78)
     at 
/home/blarsen/Documents/fsf_build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.reverse/finish-reverse-next.c:83
83        function1 (a, b);   // CALL VIA LEP
(gdb) n
86        a = 10;
(gdb) rs
function1 (a=1, b=5)
     at 
/home/blarsen/Documents/fsf_build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.reverse/finish-reverse-next.c:70
70      }
(gdb) reverse-finish
Run back to call of #0  function1 (a=1, b=5)
     at 
/home/blarsen/Documents/fsf_build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.reverse/finish-reverse-next.c:70
0x0000000000401196 in main (argc=1, argv=0x7fffffffde78)
     at 
/home/blarsen/Documents/fsf_build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.reverse/finish-reverse-next.c:83
83        function1 (a, b);   // CALL VIA LEP
(gdb) maint info line-table
             (snip)
15     81     0x0000000000401185 0x0000000000401185 Y
16     83     0x000000000040118c 0x000000000040118c Y
17     86     0x000000000040119b 0x000000000040119b Y
(gdb) disas /s
Dump of assembler code for function main:
       (snip)
83        function1 (a, b);   // CALL VIA LEP
    0x000000000040118c <+37>:    mov    -0x10(%rbp),%edx
    0x000000000040118f <+40>:    mov    -0xc(%rbp),%eax
    0x0000000000401192 <+43>:    mov    %edx,%esi
    0x0000000000401194 <+45>:    mov    %eax,%edi
=> 0x0000000000401196 <+47>:    call   0x40112c <function1>

We can see that we have stopped at the right instruction, but it isn't 
mapped to any line number directly. If we reverse-next from there:

82
83        function1 (a, b);   // CALL VIA LEP
=> 0x000000000040118c <+37>:    mov    -0x10(%rbp),%edx
    0x000000000040118f <+40>:    mov    -0xc(%rbp),%eax
    0x0000000000401192 <+43>:    mov    %edx,%esi
    0x0000000000401194 <+45>:    mov    %eax,%edi
    0x0000000000401196 <+47>:    call   0x40112c <function1>

We at at an address that _is_ mapped in the line table. So my guess is 
that the code setting up the reverse-next or reverse-step is failing to 
figure out our current line (83) so cant properly setup a stepping 
range, GDB would reverse step a single instruction, but since that 
leaves us in a place that is not marked IS_STMT, GDB will continue to 
step until we hit an IS_STMT location, and we end up stopping at the 
same line twice.

For completeness sake, here's what the Clang session looks like:
(gdb) reverse-finish
Run back to call of #0  0x000000000040117b in function1 (a=1, b=5) at 
/home/blarsen/Documents/fsf_build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.reverse/finish-reverse-next.c:69
0x00000000004011c8 in main (argc=1, argv=0x7fffffffde78) at 
/home/blarsen/Documents/fsf_build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.reverse/finish-reverse-next.c:83
83        function1 (a, b);   // CALL VIA LEP
(gdb) maint info line-table
          (snip)
22     80     0x00000000004011b4 0x00000000004011b4 Y
23     81     0x00000000004011bb 0x00000000004011bb Y
24     83     0x00000000004011c2 0x00000000004011c2 Y
25     83     0x00000000004011c5 0x00000000004011c5
26     83     0x00000000004011c8 0x00000000004011c8
27     86     0x00000000004011cd 0x00000000004011cd Y
(gdb) disas /s
          (snip)
81        b = 5;
    0x00000000004011bb <+43>:    movl   $0x5,-0x18(%rbp)

82
83        function1 (a, b);   // CALL VIA LEP
    0x00000000004011c2 <+50>:    mov    -0x14(%rbp),%edi
    0x00000000004011c5 <+53>:    mov    -0x18(%rbp),%esi
=> 0x00000000004011c8 <+56>:    call   0x401140 <function1>
(gdb) rn
81        b = 5;

Basically, the best way to fix this solution is to get reverse-next and 
reverse-step to properly figure out the stepping range and not have a 
reverse-next that ends up in the same line

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-07-20 12:01                                                                                                         ` Bruno Larsen
@ 2023-07-20 14:45                                                                                                           ` Carl Love
  2023-07-21  7:24                                                                                                             ` Bruno Larsen
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-07-20 14:45 UTC (permalink / raw)
  To: Bruno Larsen, Simon Marchi, Tom de Vries, Ulrich Weigand,
	gdb-patches, pedro
  Cc: cel

Bruno:

On Thu, 2023-07-20 at 14:01 +0200, Bruno Larsen wrote:
> (gdb) disas /s
>           (snip)
> 81        b = 5;
>     0x00000000004011bb <+43>:    movl   $0x5,-0x18(%rbp)
> 
> 82
> 83        function1 (a, b);   // CALL VIA LEP
>     0x00000000004011c2 <+50>:    mov    -0x14(%rbp),%edi
>     0x00000000004011c5 <+53>:    mov    -0x18(%rbp),%esi
> => 0x00000000004011c8 <+56>:    call   0x401140 <function1>
> (gdb) rn
> 81        b = 5;
> 
> Basically, the best way to fix this solution is to get reverse-next
> and 
> reverse-step to properly figure out the stepping range and not have
> a 
> reverse-next that ends up in the same line

---------------------

Per my reply to Simon in "Re: [EXTERNAL] Re: [PATCH 2/2 v5] Fix reverse
stepping multiple contiguous PC ranges over the line table." on
6/23/2023. Where he was wondering why control.step_range_start was not
set to the "real" range....


This is the code in the Patch:
> 
> > +{
> > +  /* The line table may have multiple entries for the same source
> > code line.
> > +     Given the PC, check the line table and return the PC that
> > corresponds
> > +     to the line table entry for the source line that PC is
> > in.  */
> > +  CORE_ADDR start_line_pc = ecs->event_thread-
> > >control.step_range_start;
> > +  gdb::optional<CORE_ADDR> real_range_start;
> > +
> > +  /* Call find_line_range_start to get the smallest address in the
> > +     linetable for multiple Line X entries in the line table.  */
> > +  real_range_start = find_line_range_start (pc);
> > +
> > +  if (real_range_start.has_value ())
> > +    start_line_pc = *real_range_start;
> > +
> > +  return start_line_pc;


Simon's comment about the code:

> 
> When I read this, I wonder: why was control.step_range_start not set
> to
> the "real" range start in the first place (not only in the context of
> reverse execution, every time it is set)?  It would seem more robust
> than patching it afterwards in some very specific spots.
> 
> I could see some benefits for range-stepping uses cases too (relevant
> when debugging remotely).  Using your example here:
> 
>    Line X - [0x0 - 0x8]
>    Line X - [0x8 - 0x10]
>    Line X - [0x10 - 0x18]
> 
> Imagine we are stopped at 0x14, and we type "next", and 0x14 is a
> conditional jump to 0x5.  It seems like current GDB would send a
> "range
> step" request to GDBserver, to step in the [0x10, 0x18[ range.  When
> reaching 0x5, execution would stop, and GDB would resume it again
> with
> the [0x0,0x8[ range.  When reaching 0x8, it would stop again, GDB
> would
> resume it with [0x8,0x10[, and so on.  If GDB could send a "range
> step"
> request with the [0x0,0x18[ range, it would avoid those unnecessary
> intermediary stop.
> 

My reply to Simon's comment:

We looked at trying to set control.step_range_start to the real start
range initially.  Ulrich brought this point up in our internal review
of the patch.  

So, when I am in function finish_backward() in infcmd.c I have no way
to determine what the previous PC was.  If I assume it was the previous
value, i.e. pc - 4byes (on PowerPC).  I get a gdb internal error.  It
seems that I am not allowed to change the line range to something that
does not include the current pc value.  

   ../../binutils-gdb-reverse-multiple-contiguous/gdb/infrun.c:2740:
   internal-error: resume_1:
   Assertion `pc_in_thread_step_range (pc, tp)' failed.

In order to make that work, we concluded that it would probably entail
a much bigger change to how reverse execution works which would be
beyond the scope of what this patch is trying to fix.  So, being able
to do what I believe you want to do is in theory possible but it would
require a larger, independent change to what this patch is trying to
fix.

---------------------------------------

I think what Bruno is again asking is to have control.step_range_start
set to the real start range initially, i.e. what Simon asked about.  I
think to do that, we would need to make significant changes to how
reverse execution works to allow us to make that change.  It didn't
appear to be a straight forward fix to me.  I may be wrong.  Maybe
someone sees a good way to make that work that I am missing.  So it
looks like this patch fixes most issues but not all of the problems
with reverse-step and reverse-next.  It might be good to try and fix
this additional scenario in a separate patch, not sure???  

                 Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-07-20 14:45                                                                                                           ` Carl Love
@ 2023-07-21  7:24                                                                                                             ` Bruno Larsen
  2023-07-31 22:59                                                                                                               ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-07-21  7:24 UTC (permalink / raw)
  To: Carl Love, Simon Marchi, Tom de Vries, Ulrich Weigand,
	gdb-patches, pedro

On 20/07/2023 16:45, Carl Love wrote:
> Bruno:
>
> On Thu, 2023-07-20 at 14:01 +0200, Bruno Larsen wrote:
>> (gdb) disas /s
>>            (snip)
>> 81        b = 5;
>>      0x00000000004011bb <+43>:    movl   $0x5,-0x18(%rbp)
>>
>> 82
>> 83        function1 (a, b);   // CALL VIA LEP
>>      0x00000000004011c2 <+50>:    mov    -0x14(%rbp),%edi
>>      0x00000000004011c5 <+53>:    mov    -0x18(%rbp),%esi
>> => 0x00000000004011c8 <+56>:    call   0x401140 <function1>
>> (gdb) rn
>> 81        b = 5;
>>
>> Basically, the best way to fix this solution is to get reverse-next
>> and
>> reverse-step to properly figure out the stepping range and not have
>> a
>> reverse-next that ends up in the same line
> ---------------------
>
> Per my reply to Simon in "Re: [EXTERNAL] Re: [PATCH 2/2 v5] Fix reverse
> stepping multiple contiguous PC ranges over the line table." on
> 6/23/2023. Where he was wondering why control.step_range_start was not
> set to the "real" range....
>
>
> This is the code in the Patch:
>>> +{
>>> +  /* The line table may have multiple entries for the same source
>>> code line.
>>> +     Given the PC, check the line table and return the PC that
>>> corresponds
>>> +     to the line table entry for the source line that PC is
>>> in.  */
>>> +  CORE_ADDR start_line_pc = ecs->event_thread-
>>>> control.step_range_start;
>>> +  gdb::optional<CORE_ADDR> real_range_start;
>>> +
>>> +  /* Call find_line_range_start to get the smallest address in the
>>> +     linetable for multiple Line X entries in the line table.  */
>>> +  real_range_start = find_line_range_start (pc);
>>> +
>>> +  if (real_range_start.has_value ())
>>> +    start_line_pc = *real_range_start;
>>> +
>>> +  return start_line_pc;
>
> Simon's comment about the code:
>
>> When I read this, I wonder: why was control.step_range_start not set
>> to
>> the "real" range start in the first place (not only in the context of
>> reverse execution, every time it is set)?  It would seem more robust
>> than patching it afterwards in some very specific spots.
>>
>> I could see some benefits for range-stepping uses cases too (relevant
>> when debugging remotely).  Using your example here:
>>
>>     Line X - [0x0 - 0x8]
>>     Line X - [0x8 - 0x10]
>>     Line X - [0x10 - 0x18]
>>
>> Imagine we are stopped at 0x14, and we type "next", and 0x14 is a
>> conditional jump to 0x5.  It seems like current GDB would send a
>> "range
>> step" request to GDBserver, to step in the [0x10, 0x18[ range.  When
>> reaching 0x5, execution would stop, and GDB would resume it again
>> with
>> the [0x0,0x8[ range.  When reaching 0x8, it would stop again, GDB
>> would
>> resume it with [0x8,0x10[, and so on.  If GDB could send a "range
>> step"
>> request with the [0x0,0x18[ range, it would avoid those unnecessary
>> intermediary stop.
>>
> My reply to Simon's comment:
>
> We looked at trying to set control.step_range_start to the real start
> range initially.  Ulrich brought this point up in our internal review
> of the patch.
>
> So, when I am in function finish_backward() in infcmd.c I have no way
> to determine what the previous PC was.  If I assume it was the previous
> value, i.e. pc - 4byes (on PowerPC).  I get a gdb internal error.  It
> seems that I am not allowed to change the line range to something that
> does not include the current pc value.
>
>     ../../binutils-gdb-reverse-multiple-contiguous/gdb/infrun.c:2740:
>     internal-error: resume_1:
>     Assertion `pc_in_thread_step_range (pc, tp)' failed.
>
> In order to make that work, we concluded that it would probably entail
> a much bigger change to how reverse execution works which would be
> beyond the scope of what this patch is trying to fix.  So, being able
> to do what I believe you want to do is in theory possible but it would
> require a larger, independent change to what this patch is trying to
> fix.
>
> ---------------------------------------
>
> I think what Bruno is again asking is to have control.step_range_start
> set to the real start range initially, i.e. what Simon asked about.  I
> think to do that, we would need to make significant changes to how
> reverse execution works to allow us to make that change.  It didn't
> appear to be a straight forward fix to me.  I may be wrong.  Maybe
> someone sees a good way to make that work that I am missing.  So it
> looks like this patch fixes most issues but not all of the problems
> with reverse-step and reverse-next.  It might be good to try and fix
> this additional scenario in a separate patch, not sure???

I just tested with the newest version of the patch relating to reverse 
stepping over contiguous lines, but that didn't make a difference. GCC 
continued broken. I think the problem is that GCC doesn't have 
contiguous ranges, it has a single range that doesn't contain the PC

My (probably naive) thinking is to set step_range_end to the starting PC 
of the following line, and step_range_start to be the real start of the 
current line at the moment the command is parsed. This sounds like it 
would solve the GCC problem, but I assume I'm missing something. 
Unfortunately, I don't have the time to test this theory myself, but 
I'll happily test any patches you submit :). If you want to repeat my 
test, I want the behavior of gdb.reverse/finish-reverse-next from gcc to 
match clang's (on x86 machines), that is, if you reverse finish from 
function1, a single "rn" command would land you on the b=5 line.

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-07-21  7:24                                                                                                             ` Bruno Larsen
@ 2023-07-31 22:59                                                                                                               ` Carl Love
  2023-08-02  9:29                                                                                                                 ` Bruno Larsen
  0 siblings, 1 reply; 105+ messages in thread
From: Carl Love @ 2023-07-31 22:59 UTC (permalink / raw)
  To: Bruno Larsen, Simon Marchi, Tom de Vries, Ulrich Weigand,
	gdb-patches, pedro
  Cc: cel


Bruno:

On Fri, 2023-07-21 at 09:24 +0200, Bruno Larsen wrote:
> > I think what Bruno is again asking is to have
> > control.step_range_start
> > set to the real start range initially, i.e. what Simon asked
> > about.  I
> > think to do that, we would need to make significant changes to how
> > reverse execution works to allow us to make that change.  It didn't
> > appear to be a straight forward fix to me.  I may be wrong.  Maybe
> > someone sees a good way to make that work that I am missing.  So it
> > looks like this patch fixes most issues but not all of the problems
> > with reverse-step and reverse-next.  It might be good to try and
> > fix
> > this additional scenario in a separate patch, not sure???
> 
> I just tested with the newest version of the patch relating to
> reverse 
> stepping over contiguous lines, but that didn't make a difference.
> GCC 
> continued broken. I think the problem is that GCC doesn't have 
> contiguous ranges, it has a single range that doesn't contain the PC
> 
> My (probably naive) thinking is to set step_range_end to the starting
> PC 
> of the following line, and step_range_start to be the real start of
> the 
> current line at the moment the command is parsed. This sounds like
> it 
> would solve the GCC problem, but I assume I'm missing something. 
> Unfortunately, I don't have the time to test this theory myself, but 
> I'll happily test any patches you submit :). If you want to repeat
> my 
> test, I want the behavior of gdb.reverse/finish-reverse-next from gcc
> to 
> match clang's (on x86 machines), that is, if you reverse finish from 
> function1, a single "rn" command would land you on the b=5 line.

So, I took the example of the error from your previous patch where you
demonstrated the scenario where you have stopped at the call to the
function, then do the reverse-next which stops at the beginning of the
same line and put it into a new test case for discussion and for
debugging the issue.  Nice to have a simple example of the issue.  The
new test is bruno_7_20_2023.exp.  So, in this test, when we are stopped
at the call, as you showed on Intel

(gdb) maint info line-table
>              (snip)
> 15     81     0x0000000000401185 0x0000000000401185 Y
> 16     83     0x000000000040118c 0x000000000040118c Y
> 17     86     0x000000000040119b 0x000000000040119b Y
> (gdb) disas /s
> Dump of assembler code for function main:
>        (snip)
> 83        function1 (a, b);   // CALL VIA LEP
>     0x000000000040118c <+37>:    mov    -0x10(%rbp),%edx
>     0x000000000040118f <+40>:    mov    -0xc(%rbp),%eax
>     0x0000000000401192 <+43>:    mov    %edx,%esi
>     0x0000000000401194 <+45>:    mov    %eax,%edi
> => 0x0000000000401196 <+47>:    call   0x40112c <function1>
> 
> We can see that we have stopped at the right instruction, but it
> isn't 
> mapped to any line number directly. If we reverse-next from there:

the tp->control.step_range_start is set to 0x40118c in function
prepare_one_step() in gdb/infcmd.c.  The PC in your case is at
0x401196.  Of course both of the addresses are in the same line.  We
are executing backwards so we need step_range_start to be set to a
value in the previous line.  In general, we have no idea what the
previous line was as we may have arrived on this line via a jump or
branch in theory.  Also, note, when setting the range we need to have
the PC in the range or GDB will give us an assert error.

So really the issue is that we want the step_range_start to be in the
line where we came from.  So, if we see the line number for PC and
step_range_start are the same, we can set step_range_start to one less
then the address of the beginning of the current line when we parse the
instruction and setup the stepping range.  The goal is to have GDB stop
in the previous line and not at the beginning of the line and thus
match the behavior of gdb on clang.

I implemented the check and adjustment for step_range_start as just
described and tested it with your example, bruno_7_20_2023.exp and it
does seem to work as desired.

The existing testcases expect to have to do two reverse step/next
instructions to reach the previous line.  So, we need to fix the
existing tests gdb.reverse/finish-reverse-next.exp and gdb.mi/mi-
reverse.exp to remove the extra reverse step/next command.

Anyway, I put the gdb code fix, the bruno_7_20_2023.exp and test fixes
into the patch below for discussion purposes.  If everyone is happy
with the gdb change and test changes (we can drop the Bruno test) I can
merge these changes into the patch. Hopefully keeping these changes in
a separate patch for the moment will make it easier to see what is
being changed.

If you were to apply the following patch on top of the currently
proposed patch, does gdb then execute as you expect on your system?  I
have tested the change on IBM Power 10.  It would be good to make sure
it works on your X86 system as well.  I also ran the full gdb
regression tests on Power 10 with no additional regression failures.
Thanks for looking at the patch, proposed fix and the additional
testing.

                          Carl 
---------------------------------------------------------------
[PATCH 2/2] finish-reverse-next new test case from bruno.

GDB fix for Bruno test, updated other tests for the gdb fix.
---
 gdb/infcmd.c                                  |  9 ++
 gdb/testsuite/gdb.mi/mi-reverse.exp           |  6 +-
 gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp | 85 +++++++++++++++++++
 .../gdb.reverse/finish-reverse-next.exp       | 44 +++++++---
 4 files changed, 133 insertions(+), 11 deletions(-)
 create mode 100644 gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index b8134665f3f..c09b3edad3d 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -981,6 +981,15 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
 	  find_pc_line_pc_range (pc,
 				 &tp->control.step_range_start,
 				 &tp->control.step_range_end);
+	  symtab_and_line sal = find_pc_line (pc, 0);
+	  symtab_and_line sal_start
+	    = find_pc_line (tp->control.step_range_start, 0);
+
+	  if (sal.line == sal_start.line)
+	    /* The step_range_start address is in the same line.  We want to
+	       stop in the previous line so move step_range_start one
+	       instruction earlier.  */
+	    tp->control.step_range_start--;
 
 	  /* There's a problem in gcc (PR gcc/98780) that causes missing line
 	     table entries, which results in a too large stepping range.
diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
index baa53a495d7..997309cfb71 100644
--- a/gdb/testsuite/gdb.mi/mi-reverse.exp
+++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
@@ -99,8 +99,12 @@ proc test_controlled_execution_reverse {} {
     #   It takes two steps to get back to the previous line,
     #   as the first step moves us to the start of the current line,
     #   and the one after that moves back to the previous line.
+## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
+## stopped at the call, which is the last instruction in the line, the
+## reverse next should take us directly to the previous line, not stop at
+## the first instruction in the same line.
 
-    mi_execute_to "exec-next --reverse 2" \
+    mi_execute_to "exec-next --reverse" \
  	"end-stepping-range" "main" "" \
  	"basics.c" $line_main_hello "" \
  	"reverse next to get over the call to do_nothing"
diff --git a/gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp b/gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp
new file mode 100644
index 00000000000..0f19a959043
--- /dev/null
+++ b/gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp
@@ -0,0 +1,85 @@
+# Copyright 2008-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# This file is part of the GDB testsuite.  It tests reverse stepping.
+# Lots of code borrowed from "step-test.exp".
+
+# The reverse finish command should return from a function and stop on
+# the first instruction of the source line where the function call is made.
+# Specifically, the behavior should match doing a reverse next from the
+# first instruction in the function.  GDB should only take one reverse step
+# or next statement to reach the previous source code line.
+
+# This testcase verifies the reverse-finish command stops at the first
+# instruction in the source code line where the function was called.  There
+# are two scenarios that must be checked:
+#   1) gdb is at the entry point instruction for the function
+#   2) gdb is in the body of the function.
+
+# This test verifies the fix for gdb bugzilla:
+#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
+
+# PowerPC supports two entry points to a function.  The normal entry point
+# is called the local entry point (LEP).  The alternate entry point is called
+# the global entry point (GEP).  A function call via a function pointer
+# will entry via the GEP.  A normal function call will enter via the LEP.
+#
+# This test has been expanded to include tests to verify the reverse-finish
+# command works properly if the function is called via the GEP.  The original
+# test only verified the reverse-finish command for a normal call that used
+# the LEP.
+
+if ![supports_reverse] {
+    return
+}
+
+standard_testfile finish-reverse-next.c
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+    return -1
+}
+
+runto_main
+set target_remote [gdb_is_target_remote]
+
+if [supports_process_record] {
+    # Activate process record/replay.
+    gdb_test_no_output "record" "turn on process record for test1"
+}
+
+
+# until 83
+# Set breakpoint at call to function1 in main.
+set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
+gdb_breakpoint $srcfile:$bp_LEP_test temporary
+
+# Continue to break point at function1 call in main.
+gdb_continue_to_breakpoint \
+    "stopped at function1 entry point instruction to stepi into function" \
+    ".*$srcfile:$bp_LEP_test\r\n.*"
+
+gdb_test "next" ".*a = 10;.*" \
+    "next from function body function1 LEP to a = 10;"
+
+gdb_test "reverse-step" ".*70.*}.*" \
+    "reverse step from a = 10, stops at last inst in function1 call"
+
+gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+    "reverse-finish should stop at last inst in line for function1"
+
+gdb_test "reverse-next" ".*b = 5;.*" \
+    "reverse-finish should stop at b = 5, not first inst in line for function1"
+
+
diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
index 1f53b649a7d..921d0051233 100644
--- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
+++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
@@ -80,10 +80,15 @@ repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call" "100"
 # instruction should then stop at the first instruction in the same source
 # code line.  Another revers-next instruction stops at the previous source
 # code line.
+
+## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
+## stopped at the call, which is the last instruction in the line, the
+## reverse next should take us directly to the previous line, not stop at
+## the first instruction in the same line.
 gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
     "reverse-finish function1 LEP call from LEP "
-gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
-    "reverse next 1 LEP entry point function call from LEP"
+##gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
+##    "reverse next 1 LEP entry point function call from LEP"
 gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call from LEP"
 
 
@@ -113,10 +118,14 @@ gdb_test "step" ".*int ret = 0;.*" "step test 1"
 # instruction should then stop at the first instruction in the same source
 # code line.  Another revers-next instruction stops at the previous source
 # code line.
+## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
+## stopped at the call, which is the last instruction in the line, the
+## reverse next should take us directly to the previous line, not stop at
+## the first instruction in the same line.
 gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
     "reverse-finish function1 LEP call from function body"
-gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
-    "reverse next 1 LEP from function body"
+## gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
+##     "reverse next 1 LEP from function body"
 gdb_test "reverse-next" ".*b = 5;.*" \
     "reverse next 2 at b = 5, from function body"
 
@@ -148,10 +157,15 @@ repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
 # instruction should then stop at the first instruction in the same source
 # code line.  Another revers-next instruction stops at the previous source
 # code line.
+## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
+## stopped at the call, which is the last instruction in the line, the
+## reverse next should take us directly to the previous line, not stop at
+## the first instruction in the same line.
+
 gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
     "function1 GEP call call from GEP"
-gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
-    "reverse next 1 GEP entry point function call from GEP"
+## gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+##    "reverse next 1 GEP entry point function call from GEP"
 gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, call from GEP"
 
 gdb_test "reverse-continue" ".*" "setup for test 4"
@@ -184,10 +198,15 @@ gdb_test "stepi" "{" "stepi to between GEP and LEP"
 # instruction should then stop at the first instruction in the same source
 # code line.  Another revers-next instruction stops at the previous source
 # code line.
+## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
+## stopped at the call, which is the last instruction in the line, the
+## reverse next should take us directly to the previous line, not stop at
+## the first instruction in the same line.
+
 gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
     "function1 GEP call call from GEP again"
-gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
-    "reverse next 1 GEP entry point function call from GEP again"
+##gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+##    "reverse next 1 GEP entry point function call from GEP again"
 gdb_test "reverse-next" ".*b = 50;.*" \
     "reverse next 2 at b = 50, call from GEP again"
 
@@ -216,9 +235,14 @@ gdb_test "step" ".*int ret = 0;.*" "step test 2"
 # instruction should then stop at the first instruction in the same source
 # code line.  Another revers-next instruction stops at the previous source
 # code line.
+## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
+## stopped at the call, which is the last instruction in the line, the
+## reverse next should take us directly to the previous line, not stop at
+## the first instruction in the same line.
+
 gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
     "reverse-finish function1 GEP call, from function body  "
-gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
-    "reverse next 1 GEP call from function body"
+## gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
+##    "reverse next 1 GEP call from function body"
 gdb_test "reverse-next" ".*b = 50;.*" \
     "reverse next 2 at b = 50 from function body"
-- 
2.37.2



^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-07-31 22:59                                                                                                               ` Carl Love
@ 2023-08-02  9:29                                                                                                                 ` Bruno Larsen
  2023-08-02 15:11                                                                                                                   ` Carl Love
  0 siblings, 1 reply; 105+ messages in thread
From: Bruno Larsen @ 2023-08-02  9:29 UTC (permalink / raw)
  To: Carl Love, Simon Marchi, Tom de Vries, Ulrich Weigand,
	gdb-patches, pedro

On 01/08/2023 00:59, Carl Love wrote:
> Bruno:
>
> On Fri, 2023-07-21 at 09:24 +0200, Bruno Larsen wrote:
>>> I think what Bruno is again asking is to have
>>> control.step_range_start
>>> set to the real start range initially, i.e. what Simon asked
>>> about.  I
>>> think to do that, we would need to make significant changes to how
>>> reverse execution works to allow us to make that change.  It didn't
>>> appear to be a straight forward fix to me.  I may be wrong.  Maybe
>>> someone sees a good way to make that work that I am missing.  So it
>>> looks like this patch fixes most issues but not all of the problems
>>> with reverse-step and reverse-next.  It might be good to try and
>>> fix
>>> this additional scenario in a separate patch, not sure???
>> I just tested with the newest version of the patch relating to
>> reverse
>> stepping over contiguous lines, but that didn't make a difference.
>> GCC
>> continued broken. I think the problem is that GCC doesn't have
>> contiguous ranges, it has a single range that doesn't contain the PC
>>
>> My (probably naive) thinking is to set step_range_end to the starting
>> PC
>> of the following line, and step_range_start to be the real start of
>> the
>> current line at the moment the command is parsed. This sounds like
>> it
>> would solve the GCC problem, but I assume I'm missing something.
>> Unfortunately, I don't have the time to test this theory myself, but
>> I'll happily test any patches you submit :). If you want to repeat
>> my
>> test, I want the behavior of gdb.reverse/finish-reverse-next from gcc
>> to
>> match clang's (on x86 machines), that is, if you reverse finish from
>> function1, a single "rn" command would land you on the b=5 line.
> So, I took the example of the error from your previous patch where you
> demonstrated the scenario where you have stopped at the call to the
> function, then do the reverse-next which stops at the beginning of the
> same line and put it into a new test case for discussion and for
> debugging the issue.  Nice to have a simple example of the issue.  The
> new test is bruno_7_20_2023.exp.  So, in this test, when we are stopped
> at the call, as you showed on Intel
>
> (gdb) maint info line-table
>>               (snip)
>> 15     81     0x0000000000401185 0x0000000000401185 Y
>> 16     83     0x000000000040118c 0x000000000040118c Y
>> 17     86     0x000000000040119b 0x000000000040119b Y
>> (gdb) disas /s
>> Dump of assembler code for function main:
>>         (snip)
>> 83        function1 (a, b);   // CALL VIA LEP
>>      0x000000000040118c <+37>:    mov    -0x10(%rbp),%edx
>>      0x000000000040118f <+40>:    mov    -0xc(%rbp),%eax
>>      0x0000000000401192 <+43>:    mov    %edx,%esi
>>      0x0000000000401194 <+45>:    mov    %eax,%edi
>> => 0x0000000000401196 <+47>:    call   0x40112c <function1>
>>
>> We can see that we have stopped at the right instruction, but it
>> isn't
>> mapped to any line number directly. If we reverse-next from there:
> the tp->control.step_range_start is set to 0x40118c in function
> prepare_one_step() in gdb/infcmd.c.  The PC in your case is at
> 0x401196.  Of course both of the addresses are in the same line.  We
> are executing backwards so we need step_range_start to be set to a
> value in the previous line.  In general, we have no idea what the
> previous line was as we may have arrived on this line via a jump or
> branch in theory.  Also, note, when setting the range we need to have
> the PC in the range or GDB will give us an assert error.
>
> So really the issue is that we want the step_range_start to be in the
> line where we came from.  So, if we see the line number for PC and
> step_range_start are the same, we can set step_range_start to one less
> then the address of the beginning of the current line when we parse the
> instruction and setup the stepping range.  The goal is to have GDB stop
> in the previous line and not at the beginning of the line and thus
> match the behavior of gdb on clang.
>
> I implemented the check and adjustment for step_range_start as just
> described and tested it with your example, bruno_7_20_2023.exp and it
> does seem to work as desired.
>
> The existing testcases expect to have to do two reverse step/next
> instructions to reach the previous line.  So, we need to fix the
> existing tests gdb.reverse/finish-reverse-next.exp and gdb.mi/mi-
> reverse.exp to remove the extra reverse step/next command.
>
> Anyway, I put the gdb code fix, the bruno_7_20_2023.exp and test fixes
> into the patch below for discussion purposes.  If everyone is happy
> with the gdb change and test changes (we can drop the Bruno test) I can
> merge these changes into the patch. Hopefully keeping these changes in
> a separate patch for the moment will make it easier to see what is
> being changed.

Hi Carl!

Thanks for the thorough explanation and test. You did understood what I 
meant perfectly :)

This is a little besides the point, but I don't see any other patches 
that touch this area and haven't been committed yet. Am I missing 
something obvious?

Regardless, I feel like this one change can propagate enough that it 
should be its own commit anyway.

>
> If you were to apply the following patch on top of the currently
> proposed patch, does gdb then execute as you expect on your system?  I
> have tested the change on IBM Power 10.  It would be good to make sure
> it works on your X86 system as well.  I also ran the full gdb
> regression tests on Power 10 with no additional regression failures.
> Thanks for looking at the patch, proposed fix and the additional
> testing.

The patch didn't apply on current master, but I added the changes 
manually and tested it. It does fix the issue, and adds no regressions.

I feel like it could be worth sending an official version this patch as 
a new thread, instead of a reply to this one, to get people who might 
not be interested in reverse debugging but may have thoughts on this 
patch, but maybe wait a bit to see if someone in here says anything :)

-- 
Cheers,
Bruno

>
>                            Carl
> ---------------------------------------------------------------
> [PATCH 2/2] finish-reverse-next new test case from bruno.
>
> GDB fix for Bruno test, updated other tests for the gdb fix.
> ---
>   gdb/infcmd.c                                  |  9 ++
>   gdb/testsuite/gdb.mi/mi-reverse.exp           |  6 +-
>   gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp | 85 +++++++++++++++++++
>   .../gdb.reverse/finish-reverse-next.exp       | 44 +++++++---
>   4 files changed, 133 insertions(+), 11 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp
>
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index b8134665f3f..c09b3edad3d 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -981,6 +981,15 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
>   	  find_pc_line_pc_range (pc,
>   				 &tp->control.step_range_start,
>   				 &tp->control.step_range_end);
> +	  symtab_and_line sal = find_pc_line (pc, 0);
> +	  symtab_and_line sal_start
> +	    = find_pc_line (tp->control.step_range_start, 0);
> +
> +	  if (sal.line == sal_start.line)
> +	    /* The step_range_start address is in the same line.  We want to
> +	       stop in the previous line so move step_range_start one
> +	       instruction earlier.  */
> +	    tp->control.step_range_start--;
>   
>   	  /* There's a problem in gcc (PR gcc/98780) that causes missing line
>   	     table entries, which results in a too large stepping range.
> diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp
> index baa53a495d7..997309cfb71 100644
> --- a/gdb/testsuite/gdb.mi/mi-reverse.exp
> +++ b/gdb/testsuite/gdb.mi/mi-reverse.exp
> @@ -99,8 +99,12 @@ proc test_controlled_execution_reverse {} {
>       #   It takes two steps to get back to the previous line,
>       #   as the first step moves us to the start of the current line,
>       #   and the one after that moves back to the previous line.
> +## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
> +## stopped at the call, which is the last instruction in the line, the
> +## reverse next should take us directly to the previous line, not stop at
> +## the first instruction in the same line.
>   
> -    mi_execute_to "exec-next --reverse 2" \
> +    mi_execute_to "exec-next --reverse" \
>    	"end-stepping-range" "main" "" \
>    	"basics.c" $line_main_hello "" \
>    	"reverse next to get over the call to do_nothing"
> diff --git a/gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp b/gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp
> new file mode 100644
> index 00000000000..0f19a959043
> --- /dev/null
> +++ b/gdb/testsuite/gdb.reverse/bruno_7_20_2023.exp
> @@ -0,0 +1,85 @@
> +# Copyright 2008-2023 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +# This file is part of the GDB testsuite.  It tests reverse stepping.
> +# Lots of code borrowed from "step-test.exp".
> +
> +# The reverse finish command should return from a function and stop on
> +# the first instruction of the source line where the function call is made.
> +# Specifically, the behavior should match doing a reverse next from the
> +# first instruction in the function.  GDB should only take one reverse step
> +# or next statement to reach the previous source code line.
> +
> +# This testcase verifies the reverse-finish command stops at the first
> +# instruction in the source code line where the function was called.  There
> +# are two scenarios that must be checked:
> +#   1) gdb is at the entry point instruction for the function
> +#   2) gdb is in the body of the function.
> +
> +# This test verifies the fix for gdb bugzilla:
> +#   https://sourceware.org/bugzilla/show_bug.cgi?id=29927
> +
> +# PowerPC supports two entry points to a function.  The normal entry point
> +# is called the local entry point (LEP).  The alternate entry point is called
> +# the global entry point (GEP).  A function call via a function pointer
> +# will entry via the GEP.  A normal function call will enter via the LEP.
> +#
> +# This test has been expanded to include tests to verify the reverse-finish
> +# command works properly if the function is called via the GEP.  The original
> +# test only verified the reverse-finish command for a normal call that used
> +# the LEP.
> +
> +if ![supports_reverse] {
> +    return
> +}
> +
> +standard_testfile finish-reverse-next.c
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
> +    return -1
> +}
> +
> +runto_main
> +set target_remote [gdb_is_target_remote]
> +
> +if [supports_process_record] {
> +    # Activate process record/replay.
> +    gdb_test_no_output "record" "turn on process record for test1"
> +}
> +
> +
> +# until 83
> +# Set breakpoint at call to function1 in main.
> +set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile]
> +gdb_breakpoint $srcfile:$bp_LEP_test temporary
> +
> +# Continue to break point at function1 call in main.
> +gdb_continue_to_breakpoint \
> +    "stopped at function1 entry point instruction to stepi into function" \
> +    ".*$srcfile:$bp_LEP_test\r\n.*"
> +
> +gdb_test "next" ".*a = 10;.*" \
> +    "next from function body function1 LEP to a = 10;"
> +
> +gdb_test "reverse-step" ".*70.*}.*" \
> +    "reverse step from a = 10, stops at last inst in function1 call"
> +
> +gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +    "reverse-finish should stop at last inst in line for function1"
> +
> +gdb_test "reverse-next" ".*b = 5;.*" \
> +    "reverse-finish should stop at b = 5, not first inst in line for function1"
> +
> +
> diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> index 1f53b649a7d..921d0051233 100644
> --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp
> @@ -80,10 +80,15 @@ repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call" "100"
>   # instruction should then stop at the first instruction in the same source
>   # code line.  Another revers-next instruction stops at the previous source
>   # code line.
> +
> +## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
> +## stopped at the call, which is the last instruction in the line, the
> +## reverse next should take us directly to the previous line, not stop at
> +## the first instruction in the same line.
>   gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
>       "reverse-finish function1 LEP call from LEP "
> -gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
> -    "reverse next 1 LEP entry point function call from LEP"
> +##gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP" \
> +##    "reverse next 1 LEP entry point function call from LEP"
>   gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call from LEP"
>   
>   
> @@ -113,10 +118,14 @@ gdb_test "step" ".*int ret = 0;.*" "step test 1"
>   # instruction should then stop at the first instruction in the same source
>   # code line.  Another revers-next instruction stops at the previous source
>   # code line.
> +## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
> +## stopped at the call, which is the last instruction in the line, the
> +## reverse next should take us directly to the previous line, not stop at
> +## the first instruction in the same line.
>   gdb_test "reverse-finish" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
>       "reverse-finish function1 LEP call from function body"
> -gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> -    "reverse next 1 LEP from function body"
> +## gdb_test "reverse-next" ".*function1 \\(a, b\\);   // CALL VIA LEP.*" \
> +##     "reverse next 1 LEP from function body"
>   gdb_test "reverse-next" ".*b = 5;.*" \
>       "reverse next 2 at b = 5, from function body"
>   
> @@ -148,10 +157,15 @@ repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call"
>   # instruction should then stop at the first instruction in the same source
>   # code line.  Another revers-next instruction stops at the previous source
>   # code line.
> +## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
> +## stopped at the call, which is the last instruction in the line, the
> +## reverse next should take us directly to the previous line, not stop at
> +## the first instruction in the same line.
> +
>   gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
>       "function1 GEP call call from GEP"
> -gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> -    "reverse next 1 GEP entry point function call from GEP"
> +## gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +##    "reverse next 1 GEP entry point function call from GEP"
>   gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, call from GEP"
>   
>   gdb_test "reverse-continue" ".*" "setup for test 4"
> @@ -184,10 +198,15 @@ gdb_test "stepi" "{" "stepi to between GEP and LEP"
>   # instruction should then stop at the first instruction in the same source
>   # code line.  Another revers-next instruction stops at the previous source
>   # code line.
> +## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
> +## stopped at the call, which is the last instruction in the line, the
> +## reverse next should take us directly to the previous line, not stop at
> +## the first instruction in the same line.
> +
>   gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
>       "function1 GEP call call from GEP again"
> -gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> -    "reverse next 1 GEP entry point function call from GEP again"
> +##gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +##    "reverse next 1 GEP entry point function call from GEP again"
>   gdb_test "reverse-next" ".*b = 50;.*" \
>       "reverse next 2 at b = 50, call from GEP again"
>   
> @@ -216,9 +235,14 @@ gdb_test "step" ".*int ret = 0;.*" "step test 2"
>   # instruction should then stop at the first instruction in the same source
>   # code line.  Another revers-next instruction stops at the previous source
>   # code line.
> +## I BELIEVE Bruno is arguing this part of the test is wrong.  When we are
> +## stopped at the call, which is the last instruction in the line, the
> +## reverse next should take us directly to the previous line, not stop at
> +## the first instruction in the same line.
> +
>   gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \
>       "reverse-finish function1 GEP call, from function body  "
> -gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> -    "reverse next 1 GEP call from function body"
> +## gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \
> +##    "reverse next 1 GEP call from function body"
>   gdb_test "reverse-next" ".*b = 50;.*" \
>       "reverse next 2 at b = 50 from function body"


^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH 2/2 ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
  2023-08-02  9:29                                                                                                                 ` Bruno Larsen
@ 2023-08-02 15:11                                                                                                                   ` Carl Love
  0 siblings, 0 replies; 105+ messages in thread
From: Carl Love @ 2023-08-02 15:11 UTC (permalink / raw)
  To: Bruno Larsen, Simon Marchi, Tom de Vries, Ulrich Weigand,
	gdb-patches, pedro
  Cc: cel


Bruno:


On Wed, 2023-08-02 at 11:29 +0200, Bruno Larsen wrote:
> Hi Carl!
> 
> Thanks for the thorough explanation and test. You did understood what
> I 
> meant perfectly :)
> 
> This is a little besides the point, but I don't see any other
> patches 
> that touch this area and haven't been committed yet. Am I missing 
> something obvious?

The patch that I was talking about is patch 2/2 for the reverse
execution that I posted a few weeks ago.  Patch 1 was for checking the
gcc version.  But yea, the discussion thread is getting long enough
that some of this is getting lost.  
> 
> Regardless, I feel like this one change can propagate enough that it 
> should be its own commit anyway.
> 
> > If you were to apply the following patch on top of the currently
> > proposed patch, does gdb then execute as you expect on your
> > system?  I
> > have tested the change on IBM Power 10.  It would be good to make
> > sure
> > it works on your X86 system as well.  I also ran the full gdb
> > regression tests on Power 10 with no additional regression
> > failures.
> > Thanks for looking at the patch, proposed fix and the additional
> > testing.
> 
> The patch didn't apply on current master, but I added the changes 
> manually and tested it. It does fix the issue, and adds no
> regressions.

I think this little fix needs to be added to patch 2/2 for fixing the
reverse execution as this fix and the patch are trying to fix the same
things.  I was also thinking this fix needs to be inside a if (reverse-
execution) statement as it is really for the reverse execution.
> 
> I feel like it could be worth sending an official version this patch
> as 
> a new thread, instead of a reply to this one, to get people who
> might 
> not be interested in reverse debugging but may have thoughts on this 
> patch, but maybe wait a bit to see if someone in here says anything
> :)

I have been thinking it is time to start a fresh thread for the patches
as I think the length of this thread is losing people.  Lets see if
anyone else responds to this thread in a week or so.  I will add the if
(reverse execution) to the little fix as mentioned, update the tests,
refresh the patch and then send out a new version in a new thread.

Thanks for the help.

                            Carl 


^ permalink raw reply	[flat|nested] 105+ messages in thread

end of thread, other threads:[~2023-08-02 15:11 UTC | newest]

Thread overview: 105+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <f594ec0070a6c585e83a6d6c8b29481a86778c0f.camel@us.ibm.com>
     [not found] ` <bc6bb459f153c0c5850d4a3e5d80bbf957ec36cc.camel@de.ibm.com>
     [not found]   ` <8bce850fa1e03e798506dc170d9b57f52034a18a.camel@us.ibm.com>
     [not found]     ` <cb5875db4e1ac60475877c685e5f172770314523.camel@de.ibm.com>
     [not found]       ` <adeeeae47c4ca79b32d79aea632ff8b2a24dd93d.camel@us.ibm.com>
     [not found]         ` <86c5e9c47945894f21b1d8bf6089c730a9f0e1a5.camel@de.ibm.com>
     [not found]           ` <b1d7ea600d6bb7af487968d938566fae9d5e1745.camel@us.ibm.com>
     [not found]             ` <5f9047b9582403561d7cce998cab9184167366a1.camel@de.ibm.com>
     [not found]               ` <e7c8093c350ad475277154014a4f0bb9b472b7af.camel@us.ibm.com>
     [not found]                 ` <f8d6379aff7af076d9edcee7d2981d052b2161ee.camel@de.ibm.com>
     [not found]                   ` <5b50668cbe882c57b8c0e9dcf5be0a253713c4c6.camel@us.ibm.com>
     [not found]                     ` <51c4bfc82ac72e475e10577dc60e4d75fa48767e.camel@de.ibm.com>
     [not found]                       ` <3ea97a8aa9cccb39299adde682f92055d1986ab3.camel@us.ibm.com>
     [not found]                         ` <f5ea8da12631f2496ba0e2263e65a0adc7ac56ca.camel@de.ibm.com>
     [not found]                           ` <53878e37c6e57de1d04d9c9960c5d0a74324ee6e.camel@us.ibm.com>
     [not found]                             ` <a5300b64533fdc753c1d50fa0e6efc21b5457547.camel@de.ibm.com>
     [not found]                               ` <50474aa92ba82eff05cdc8f49001eae56be29670.camel@us.ibm.com>
     [not found]                                 ` <f3ef4486c4ba051024602928acdfe5ddf6942b82.camel@de.ibm.com>
     [not found]                                   ` <dae6c9790b23a90d5f1494f5b6798346444f257e.camel@us.ibm.com>
     [not found]                                     ` <89331c26795e3f7743e1e068dce43b3c2dd53008.camel@us.ibm.com>
     [not found]                                       ` <c10a008e441666e4edb0916842d8eefe83f5b2f9.camel@de.ibm.com>
     [not found]                                         ` <071f24ecf9b3a2bbbe8fee7db77492eb55c5f3ff.camel@us.ibm.com>
     [not found]                                           ` <1d9b21914354bef6a290ac30673741e722e11757.camel@de.ibm.com>
2023-01-11 18:27                                             ` [PATCH 0/2] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp Carl Love
2023-01-11 18:27                                             ` [PATCH 1/2] " Carl Love
2023-01-12 16:56                                               ` Tom de Vries
2023-01-12 18:54                                                 ` Carl Love
2023-01-13 13:33                                               ` Bruno Larsen
2023-01-13 16:43                                                 ` Carl Love
2023-01-13 17:04                                                   ` Bruno Larsen
2023-01-13 19:10                                                     ` Carl Love
2023-01-14 18:08                                                 ` Carl Love
2023-01-16 12:31                                                   ` Bruno Larsen
2023-01-16 16:37                                                     ` [PATCH 0/2 version 2] " Carl Love
2023-01-16 16:37                                                     ` [PATCH 1/2 " Carl Love
2023-01-17 12:35                                                       ` Bruno Larsen
2023-01-20  0:03                                                         ` [PATCH 1/2 version 3] " Carl Love
2023-01-23 19:17                                                           ` Pedro Alves
2023-01-23 21:13                                                             ` Carl Love
2023-01-24 14:08                                                               ` Pedro Alves
2023-01-24 14:23                                                                 ` Bruno Larsen
2023-01-24 15:06                                                                   ` Pedro Alves
2023-01-24 16:04                                                                     ` Bruno Larsen
2023-01-24 19:12                                                                       ` Pedro Alves
2023-01-25  9:49                                                                         ` Bruno Larsen
2023-01-25 14:11                                                                         ` Ulrich Weigand
2023-01-25 16:42                                                                           ` Pedro Alves
2023-01-25 17:13                                                                             ` Ulrich Weigand
2023-01-25 17:24                                                                               ` Pedro Alves
2023-01-25 19:38                                                                                 ` Carl Love
2023-01-24 15:51                                                                 ` Carl Love
2023-01-24 18:37                                                                   ` Pedro Alves
2023-01-24 18:25                                                                 ` Carl Love
2023-01-24 19:21                                                                   ` Pedro Alves
2023-01-24 19:26                                                                     ` Pedro Alves
2023-01-31  0:17                                                                 ` Reverse-next bug test case Carl Love
2023-02-01 14:37                                                                   ` Pedro Alves
2023-02-01 18:40                                                                     ` Carl Love
2023-01-24 15:53                                                             ` [PATCH 1/2 version 3] fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp Tom de Vries
2023-01-24 18:48                                                               ` Pedro Alves
2023-01-16 16:37                                                     ` [PATCH 2/2 version 2] " Carl Love
2023-01-17 14:29                                                       ` Bruno Larsen
2023-01-17 16:36                                                         ` Carl Love
2023-01-17 16:55                                                           ` Tom de Vries
2023-01-17 17:03                                                             ` Carl Love
2023-01-17 17:14                                                               ` Tom de Vries
2023-01-17 19:31                                                                 ` Carl Love
2023-01-18 10:55                                                                   ` Tom de Vries
2023-01-18 16:16                                                                     ` Carl Love
2023-01-18 22:26                                                                     ` Carl Love
2023-01-19  8:04                                                                       ` Bruno Larsen
2023-01-19 16:56                                                                         ` Carl Love
2023-01-19 23:57                                                                           ` Carl Love
2023-01-20 20:04                                                                             ` Carl Love
2023-01-23 16:42                                                                               ` [PATCH 1/2 version 3] " Carl Love
2023-01-23 16:42                                                                               ` [PATCH 2/2 " Carl Love
2023-02-10 20:55                                                                               ` [PATCH ] PowerPC: " Carl Love
2023-02-17 12:24                                                                                 ` Ulrich Weigand
2023-02-20 16:34                                                                                   ` Carl Love
2023-02-20 16:48                                                                                     ` Bruno Larsen
2023-02-20 20:24                                                                                   ` Carl Love
2023-02-27 16:09                                                                                     ` [PING] " Carl Love
2023-02-28 13:39                                                                                     ` Bruno Larsen
2023-02-28 16:19                                                                                       ` Carl Love
2023-03-01 13:43                                                                                     ` Tom de Vries
2023-03-01 16:26                                                                                       ` Carl Love
2023-03-01 14:03                                                                                     ` Tom de Vries
2023-03-01 16:43                                                                                       ` Carl Love
2023-03-01 14:34                                                                                     ` Tom de Vries
2023-03-01 20:39                                                                                       ` Carl Love
2023-03-01 20:59                                                                                         ` [PATCH 0/2 " Carl Love
2023-03-01 20:59                                                                                         ` [PATCH 1/2] " Carl Love
2023-03-03 11:56                                                                                           ` Bruno Larsen
2023-03-08 16:19                                                                                             ` [PING] " Carl Love
2023-03-09 16:09                                                                                               ` Carl Love
2023-03-09 19:03                                                                                           ` Tom Tromey
2023-03-09 21:42                                                                                             ` Carl Love
2023-03-09 21:54                                                                                             ` [PATCH 1/2 ver 2] " Carl Love
2023-03-10  3:53                                                                                               ` Tom Tromey
2023-03-01 20:59                                                                                         ` [PATCH 2/2 ] " Carl Love
2023-03-08 16:19                                                                                           ` [PING] " Carl Love
2023-03-09 16:09                                                                                             ` Carl Love
2023-03-13 14:16                                                                                           ` Ulrich Weigand
2023-03-13 17:31                                                                                             ` Carl Love
2023-03-13 17:38                                                                                             ` [PATCH 2/2 ver2] " Carl Love
2023-03-17 17:19                                                                                               ` Ulrich Weigand
2023-03-17 23:05                                                                                                 ` Tom de Vries
2023-03-20 15:04                                                                                                   ` Carl Love
2023-03-20 23:21                                                                                                   ` Carl Love
2023-03-21  3:17                                                                                                     ` Carl Love
2023-03-21  6:52                                                                                                       ` Ulrich Weigand
2023-03-24 17:23                                                                                           ` [PATCH 2/2 ] " Simon Marchi
2023-03-24 22:16                                                                                             ` Carl Love
2023-03-25 12:39                                                                                               ` Simon Marchi
2023-03-27 23:59                                                                                                 ` Carl Love
2023-03-28  1:19                                                                                                   ` Simon Marchi
2023-03-28 15:17                                                                                                     ` Carl Love
2023-03-28 15:38                                                                                                       ` Simon Marchi
2023-07-20 12:01                                                                                                         ` Bruno Larsen
2023-07-20 14:45                                                                                                           ` Carl Love
2023-07-21  7:24                                                                                                             ` Bruno Larsen
2023-07-31 22:59                                                                                                               ` Carl Love
2023-08-02  9:29                                                                                                                 ` Bruno Larsen
2023-08-02 15:11                                                                                                                   ` Carl Love
2023-01-13 15:42                                               ` [PATCH 1/2] " Bruno Larsen
2023-01-11 18:27                                             ` [PATCH 2/2] " Carl Love
2023-01-13 15:55                                               ` Bruno Larsen
2023-01-14 18:08                                                 ` Carl Love

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).