This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

user breakpoints on top of step-resume breakpoints


step-resume breakpoints currently have the highest priority
over all breakpoints, even user breakpoints.  This is
causing trouble for reverse execution.

In e.g., reverse-next, we set a step-resume breakpoint
at the function's entry, and once that's reached, we
do an extra step.  Trouble is, if there's a user breakpoint
that should cause a stop, set at the same address as
the step-resume breakpoint ends up, it gets ignored,
because step-resume breakpoints always have higher priority.
See a new test pasted at the end, along with a patch.

(gdb) b *callee
Breakpoint 2 at 0x400574: file ../../../src/gdb/testsuite/gdb.reverse/step-reverse.c, line 25.
(gdb) reverse-next
infrun: clear_proceed_status_thread (process 4071)
infrun: proceed (addr=0xffffffffffffffff, signal=144, step=1)
infrun: resume (step=1, signal=0), trap_expected=0, current thread [process 4071] at 0x4005ea
infrun: wait_for_inferior ()
infrun: target_wait (-1, status) =
infrun:   4071 [process 4071],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x40058d
infrun: stepped into subroutine
infrun: inserting step-resume breakpoint at 0x400574
infrun: resume (step=0, signal=0), trap_expected=0, current thread [process 4071] at 0x40058d
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   4071 [process 4071],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x400574
infrun: BPSTAT_WHAT_STEP_RESUME
infrun: resume (step=1, signal=0), trap_expected=1, current thread [process 4071] at 0x400574
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   4071 [process 4071],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x4005e5
infrun: keep going
infrun: resume (step=1, signal=0), trap_expected=0, current thread [process 4071] at 0x4005e5
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   4071 [process 4071],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x4005e0
infrun: stepping inside range [0x4005e0-0x4005ea]
infrun: stop_stepping
55         callee();    /* NEXT OVER THIS CALL */
(gdb) 

Notice that breakpoint 2 didn't trigger, although
it is set at the same address as the step-resume
breakpoint.  The program should have stopped at
the "calleed" entry point (breakpoint 2), rather
than at the caller, but we ignored the breakpoint,
and issued a step anyway.

The reason this works in forward execution, is that
after hitting the step resume breakpoint, we'll either
detect we've stepped to a different line, and stop,
or we keep going, and do another step with the user
breakpoint in place, which ends up re-hitting that same
breakpoint, and eventually causing a stop.  In both these
cases the user breakpoint ends up in the bpstat chain, so
we do end up reporting the hit to the CLI.

(gdb) n
infrun: clear_proceed_status_thread (Thread 0x7ffff7028700 (LWP 697))
infrun: clear_proceed_status_thread (Thread 0x7ffff7829700 (LWP 696))
infrun: clear_proceed_status_thread (Thread 0x7ffff7fce720 (LWP 693))
infrun: proceed (addr=0xffffffffffffffff, signal=144, step=1)
infrun: resume (step=1, signal=0), trap_expected=0, current thread [Thread 0x7ffff7028700 (LWP 697)] at 0x400676
infrun: wait_for_inferior ()
infrun: target_wait (-1, status) =
infrun:   693 [Thread 0x7ffff7028700 (LWP 697)],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x40062a
infrun: stepped into subroutine
infrun: inserting step-resume breakpoint at 0x40067b
infrun: resume (step=0, signal=0), trap_expected=0, current thread [Thread 0x7ffff7028700 (LWP 697)] at 0x40062a
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   693 [Thread 0x7ffff7028700 (LWP 697)],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x40067b
infrun: BPSTAT_WHAT_STEP_RESUME
infrun: stepped to a different line
infrun: stop_stepping

Breakpoint 3, thread1 (arg=0x1) at loop.c:75
75            }
(gdb) 

In MI, that translates into a "end-stepping-range"
*stopped notification rather than a "breakpoint-hit".

Even it is weren't for the reverse execution troubles,
this looks a bit fragile, and unnecessary.  If we hit
a breakpoint that should cause a stop at the same time
as a step-resume, we should just stop for the stopping
breakpoint.  This suggests lowering step-resume's priority
below BPSTAT_WHAT_STOP_SILENT/BPSTAT_WHAT_STOP_NOISY.

There's one case where we do need to ignore other
breakpoints set at the step-resume location, and give
the step-resume the highest priority.  That is when
a signal arrives while stepping, and we need to skip
over a signal handler.  We set a step-resume at the
current PC, and set the inferior running until it gets
back to PC.  In this case, we don't want to consider
a breakpoint at PC as a new hit, we just want to move
the inferior past it.

So this leads to the patch below.  It lowers the regular
step-resume breakpoint's priority, and adds a new
high-priority step-resume breakpoint kind, along
with a new corresponding bpstat_what_main_action to be
used in the skip-signal-handler's case.

It also adds a reverse-next testcase that would
fail without the patch.  We now get the expected:

(gdb) b *callee
Breakpoint 2 at 0x400574: file ../../../src/gdb/testsuite/gdb.reverse/step-reverse.c, line 25.
(gdb) reverse-next
infrun: clear_proceed_status_thread (process 5058)
infrun: proceed (addr=0xffffffffffffffff, signal=144, step=1)
infrun: resume (step=1, signal=0), trap_expected=0, current thread [process 5058] at 0x4005ea
infrun: wait_for_inferior ()
infrun: target_wait (-1, status) =
infrun:   5058 [process 5058],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x40058d
infrun: stepped into subroutine
infrun: inserting step-resume breakpoint at 0x400574
infrun: resume (step=0, signal=0), trap_expected=0, current thread [process 5058] at 0x40058d
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   5058 [process 5058],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x400574
infrun: BPSTAT_WHAT_STOP_NOISY
infrun: stop_stepping

Breakpoint 2, callee () at ../../../src/gdb/testsuite/gdb.reverse/step-reverse.c:25
25      int callee() {          /* ENTER CALLEE */
(gdb) 

Tested on x86_64-linux, and applied.

Pedro Alves

2011-05-26  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* breakpoint.h (enum bptype) <bp_hp_step_resume>: New.
	(enum bpstat_what_main_action): Move BPSTAT_WHAT_STEP_RESUME
	before BPSTAT_WHAT_STOP_SILENT.  Add BPSTAT_WHAT_HP_STEP_RESUME
	at the end.
	* breakpoint.c (update_breakpoints_after_exec): Also delete hp
	step-resume breakpoints.
	(print_it_typical): Handle bp_hp_step_resume.
	(bpstat_what): Ditto.
	(bptype_string): Ditto.
	(print_one_breakpoint_location): Ditto.
	(allocate_bp_location): Ditto.
	(mention): Ditto.
	(breakpoint_re_set_one): Ditto.
	* infrun.c (handle_inferior_event): Adjust.  Split
	BPSTAT_WHAT_STEP_RESUME handling in BPSTAT_WHAT_STEP_RESUME and
	BPSTAT_WHAT_HP_STEP_RESUME.
	(insert_step_resume_breakpoint_at_sal): Rename to ...
	(insert_step_resume_breakpoint_at_sal_1): ... this.  Add bptype
	parameter.  Handle it.
	(insert_step_resume_breakpoint_at_sal): Reimplement on top of
	insert_step_resume_breakpoint_at_sal_1.
	(insert_step_resume_breakpoint_at_frame): Rename to ...
	(insert_hp_step_resume_breakpoint_at_frame): ... this.  Adjust to
	set a high-priority step-resume breakpoint.
	(insert_step_resume_breakpoint_at_frame): Adjust comment.
	(insert_step_resume_breakpoint_at_caller): Ditto.

	gdb/testsuite/
	* gdb.reverse/next-reverse-bkpt-over-sr.exp: New test.

---
 gdb/breakpoint.c                                        |   17 +++
 gdb/breakpoint.h                                        |   20 +++
 gdb/infrun.c                                            |   81 +++++++++-------
 gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp |   58 +++++++++++
 4 files changed, 140 insertions(+), 36 deletions(-)

Index: src/gdb/breakpoint.h
===================================================================
--- src.orig/gdb/breakpoint.h	2011-05-26 15:50:30.641255579 +0100
+++ src/gdb/breakpoint.h	2011-05-26 15:51:33.001255558 +0100
@@ -68,10 +68,13 @@ enum bptype
     bp_exception_resume,
 
     /* Used by wait_for_inferior for stepping over subroutine calls,
-       for stepping over signal handlers, and for skipping
-       prologues.  */
+       and for skipping prologues.  */
     bp_step_resume,
 
+    /* Used by wait_for_inferior for stepping over signal
+       handlers.  */
+    bp_hp_step_resume,
+
     /* Used to detect when a watchpoint expression has gone out of
        scope.  These breakpoints are usually not visible to the user.
 
@@ -721,6 +724,9 @@ enum bpstat_what_main_action
        BPSTAT_WHAT_KEEP_CHECKING.  */
     BPSTAT_WHAT_CLEAR_LONGJMP_RESUME,
 
+    /* Clear step resume breakpoint, and keep checking.  */
+    BPSTAT_WHAT_STEP_RESUME,
+
     /* Rather than distinguish between noisy and silent stops here, it
        might be cleaner to have bpstat_print make that decision (also
        taking into account stop_print_frame and source_only).  But the
@@ -733,8 +739,14 @@ enum bpstat_what_main_action
     /* Stop and print.  */
     BPSTAT_WHAT_STOP_NOISY,
 
-    /* Clear step resume breakpoint, and keep checking.  */
-    BPSTAT_WHAT_STEP_RESUME,
+    /* Clear step resume breakpoint, and keep checking.  High-priority
+       step-resume breakpoints are used when even if there's a user
+       breakpoint at the current PC when we set the step-resume
+       breakpoint, we don't want to re-handle any breakpoint other
+       than the step-resume when it's hit; instead we want to move
+       past the breakpoint.  This is used in the case of skipping
+       signal handlers.  */
+    BPSTAT_WHAT_HP_STEP_RESUME,
   };
 
 /* An enum indicating the kind of "stack dummy" stop.  This is a bit
Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c	2011-05-26 15:50:59.101255569 +0100
+++ src/gdb/breakpoint.c	2011-05-26 15:51:33.001255558 +0100
@@ -2415,7 +2415,7 @@ update_breakpoints_after_exec (void)
       }
 
     /* Step-resume breakpoints are meaningless after an exec().  */
-    if (b->type == bp_step_resume)
+    if (b->type == bp_step_resume || b->type == bp_hp_step_resume)
       {
 	delete_breakpoint (b);
 	continue;
@@ -3503,6 +3503,7 @@ print_it_typical (bpstat bs)
     case bp_exception:
     case bp_exception_resume:
     case bp_step_resume:
+    case bp_hp_step_resume:
     case bp_watchpoint_scope:
     case bp_call_dummy:
     case bp_std_terminate:
@@ -4489,6 +4490,15 @@ bpstat_what (bpstat bs_head)
 	      this_action = BPSTAT_WHAT_SINGLE;
 	    }
 	  break;
+	case bp_hp_step_resume:
+	  if (bs->stop)
+	    this_action = BPSTAT_WHAT_HP_STEP_RESUME;
+	  else
+	    {
+	      /* It is for the wrong frame.  */
+	      this_action = BPSTAT_WHAT_SINGLE;
+	    }
+	  break;
 	case bp_watchpoint_scope:
 	case bp_thread_event:
 	case bp_overlay_event:
@@ -4757,6 +4767,7 @@ bptype_string (enum bptype type)
     {bp_exception, "exception"},
     {bp_exception_resume, "exception resume"},
     {bp_step_resume, "step resume"},
+    {bp_hp_step_resume, "high-priority step resume"},
     {bp_watchpoint_scope, "watchpoint scope"},
     {bp_call_dummy, "call dummy"},
     {bp_std_terminate, "std::terminate"},
@@ -4892,6 +4903,7 @@ print_one_breakpoint_location (struct br
       case bp_exception:
       case bp_exception_resume:
       case bp_step_resume:
+      case bp_hp_step_resume:
       case bp_watchpoint_scope:
       case bp_call_dummy:
       case bp_std_terminate:
@@ -5701,6 +5713,7 @@ allocate_bp_location (struct breakpoint
     case bp_exception:
     case bp_exception_resume:
     case bp_step_resume:
+    case bp_hp_step_resume:
     case bp_watchpoint_scope:
     case bp_call_dummy:
     case bp_std_terminate:
@@ -7227,6 +7240,7 @@ mention (struct breakpoint *b)
       case bp_exception:
       case bp_exception_resume:
       case bp_step_resume:
+      case bp_hp_step_resume:
       case bp_call_dummy:
       case bp_std_terminate:
       case bp_watchpoint_scope:
@@ -11459,6 +11473,7 @@ breakpoint_re_set_one (void *bint)
     case bp_call_dummy:
     case bp_std_terminate:
     case bp_step_resume:
+    case bp_hp_step_resume:
     case bp_longjmp:
     case bp_longjmp_resume:
     case bp_exception:
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2011-05-26 15:50:30.641255579 +0100
+++ src/gdb/infrun.c	2011-05-26 15:51:33.011255558 +0100
@@ -99,7 +99,7 @@ void _initialize_infrun (void);
 
 void nullify_last_target_wait_ptid (void);
 
-static void insert_step_resume_breakpoint_at_frame (struct frame_info *);
+static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *);
 
 static void insert_step_resume_breakpoint_at_caller (struct frame_info *);
 
@@ -1778,7 +1778,7 @@ a command like `return' or `jump' to con
 	 original breakpoint is hit.  */
       if (tp->control.step_resume_breakpoint == NULL)
 	{
-	  insert_step_resume_breakpoint_at_frame (get_current_frame ());
+	  insert_hp_step_resume_breakpoint_at_frame (get_current_frame ());
 	  tp->step_after_step_resume_breakpoint = 1;
 	}
 
@@ -4173,7 +4173,7 @@ process_event_stop_test:
                                 "infrun: signal arrived while stepping over "
                                 "breakpoint\n");
 
-	  insert_step_resume_breakpoint_at_frame (frame);
+	  insert_hp_step_resume_breakpoint_at_frame (frame);
 	  ecs->event_thread->step_after_step_resume_breakpoint = 1;
 	  /* Reset trap_expected to ensure breakpoints are re-inserted.  */
 	  ecs->event_thread->control.trap_expected = 0;
@@ -4203,7 +4203,7 @@ process_event_stop_test:
                                 "infrun: signal may take us out of "
                                 "single-step range\n");
 
-	  insert_step_resume_breakpoint_at_frame (frame);
+	  insert_hp_step_resume_breakpoint_at_frame (frame);
 	  /* Reset trap_expected to ensure breakpoints are re-inserted.  */
 	  ecs->event_thread->control.trap_expected = 0;
 	  keep_going (ecs);
@@ -4349,6 +4349,24 @@ process_event_stop_test:
 	   where we are stepping and step out of the right range.  */
 	break;
 
+      case BPSTAT_WHAT_STEP_RESUME:
+        if (debug_infrun)
+	  fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n");
+
+	delete_step_resume_breakpoint (ecs->event_thread);
+	if (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;
+	    keep_going (ecs);
+	    return;
+	  }
+	break;
+
       case BPSTAT_WHAT_STOP_NOISY:
         if (debug_infrun)
 	  fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n");
@@ -4371,9 +4389,9 @@ process_event_stop_test:
 	stop_stepping (ecs);
 	return;
 
-      case BPSTAT_WHAT_STEP_RESUME:
+      case BPSTAT_WHAT_HP_STEP_RESUME:
         if (debug_infrun)
-	  fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n");
+	  fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_HP_STEP_RESUME\n");
 
 	delete_step_resume_breakpoint (ecs->event_thread);
 	if (ecs->event_thread->step_after_step_resume_breakpoint)
@@ -4386,17 +4404,6 @@ process_event_stop_test:
 	    keep_going (ecs);
 	    return;
 	  }
-	if (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;
-	    keep_going (ecs);
-	    return;
-	  }
 	break;
 
       case BPSTAT_WHAT_KEEP_CHECKING:
@@ -5208,14 +5215,16 @@ handle_step_into_function_backward (stru
    This is used to both functions and to skip over code.  */
 
 static void
-insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch,
-				      struct symtab_and_line sr_sal,
-				      struct frame_id sr_id)
+insert_step_resume_breakpoint_at_sal_1 (struct gdbarch *gdbarch,
+					struct symtab_and_line sr_sal,
+					struct frame_id sr_id,
+					enum bptype sr_type)
 {
   /* There should never be more than one step-resume or longjmp-resume
      breakpoint per thread, so we should never be setting a new
      step_resume_breakpoint when one is already active.  */
   gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL);
+  gdb_assert (sr_type == bp_step_resume || sr_type == bp_hp_step_resume);
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
@@ -5223,18 +5232,28 @@ insert_step_resume_breakpoint_at_sal (st
 			paddress (gdbarch, sr_sal.pc));
 
   inferior_thread ()->control.step_resume_breakpoint
-    = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, bp_step_resume);
+    = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type);
+}
+
+static void
+insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch,
+				      struct symtab_and_line sr_sal,
+				      struct frame_id sr_id)
+{
+  insert_step_resume_breakpoint_at_sal_1 (gdbarch,
+					  sr_sal, sr_id,
+					  bp_step_resume);
 }
 
-/* Insert a "step-resume breakpoint" at RETURN_FRAME.pc.  This is used
-   to skip a potential signal handler.
+/* Insert a "high-priority step-resume breakpoint" at RETURN_FRAME.pc.
+   This is used to skip a potential signal handler.
 
    This is called with the interrupted function's frame.  The signal
    handler, when it returns, will resume the interrupted function at
    RETURN_FRAME.pc.  */
 
 static void
-insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
+insert_hp_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
 {
   struct symtab_and_line sr_sal;
   struct gdbarch *gdbarch;
@@ -5247,14 +5266,14 @@ insert_step_resume_breakpoint_at_frame (
   sr_sal.section = find_pc_overlay (sr_sal.pc);
   sr_sal.pspace = get_frame_program_space (return_frame);
 
-  insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal,
-					get_stack_frame_id (return_frame));
+  insert_step_resume_breakpoint_at_sal_1 (gdbarch, sr_sal,
+					  get_stack_frame_id (return_frame),
+					  bp_hp_step_resume);
 }
 
-/* Similar to insert_step_resume_breakpoint_at_frame, except
-   but a breakpoint at the previous frame's PC.  This is used to
-   skip a function after stepping into it (for "next" or if the called
-   function has no debugging information).
+/* Insert a "step-resume breakpoint" at the previous frame's PC.  This
+   is used to skip a function after stepping into it (for "next" or if
+   the called function has no debugging information).
 
    The current function has almost always been reached by single
    stepping a call or return instruction.  NEXT_FRAME belongs to the
@@ -5262,7 +5281,7 @@ insert_step_resume_breakpoint_at_frame (
    resume address.
 
    This is a separate function rather than reusing
-   insert_step_resume_breakpoint_at_frame in order to avoid
+   insert_hp_step_resume_breakpoint_at_frame in order to avoid
    get_prev_frame, which may stop prematurely (see the implementation
    of frame_unwind_caller_id for an example).  */
 
Index: src/gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp	2011-05-26 15:51:33.011255558 +0100
@@ -0,0 +1,58 @@
+# Copyright 2008, 2009, 2010, 2011 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".
+
+#
+# reverse-next over a function call sets a step-resume breakpoint at
+# callee's entry point, runs to it, and then does an extra single-step
+# to get at the callee's caller.  Test that a user breakpoint set at
+# the same location as the step-resume breakpoint isn't ignored.
+#
+
+if ![target_info exists gdb,can_reverse] {
+    return
+}
+
+set testfile "next-reverse-bkpt-over-sr"
+set srcfile  step-reverse.c
+
+if { [prepare_for_testing $testfile.exp $testfile $srcfile] } {
+    return -1
+}
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 0
+}
+
+if [target_info exists gdb,use_precord] {
+    # Activate process record/replay
+    gdb_test_no_output "record" "Turn on process record"
+}
+
+set lineno [gdb_get_line_number "STEP INTO THIS CALL"]
+gdb_test "advance $lineno" ".*STEP INTO THIS CALL.*" "get past callee call"
+
+gdb_test "b \*callee" "" "set breakpoint at callee's entry"
+
+gdb_test "reverse-next" \
+    "Breakpoint.*, callee.*ENTER CALLEE.*" \
+    "reverse-next over call trips user breakpoint at function entry"
+
+gdb_test "up" \
+    ".*NEXT OVER THIS CALL.*" \
+    "stopped at the right callee call"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]