2011-05-26 Pedro Alves <pedro@codesourcery.com>
authorPedro Alves <palves@redhat.com>
Thu, 26 May 2011 14:59:18 +0000 (14:59 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 26 May 2011 14:59:18 +0000 (14:59 +0000)
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/ChangeLog
gdb/breakpoint.c
gdb/breakpoint.h
gdb/infrun.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp [new file with mode: 0644]

index bc5620c..fe40345 100644 (file)
@@ -1,5 +1,34 @@
 2011-05-26  Pedro Alves  <pedro@codesourcery.com>
 
+       * 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.
+
+2011-05-26  Pedro Alves  <pedro@codesourcery.com>
+
        * breakpoint.c (iterate_over_related_breakpoints): New.
        (do_map_delete_breakpoint): New.
        (delete_command): Pass do_map_delete_breakpoint to
index 5995c64..fc30d26 100644 (file)
@@ -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 breakpoint *b,
       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 *bpt)
     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 0cbd9dd..2050c6d 100644 (file)
@@ -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 1d8932a..e8ea53a 100644 (file)
@@ -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 continue execution."));
         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 (struct gdbarch *gdbarch,
    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 (struct gdbarch *gdbarch,
                        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 (struct frame_info *return_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 (struct frame_info *return_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 a710243..975a15d 100644 (file)
@@ -1,3 +1,7 @@
+2011-05-26  Pedro Alves  <pedro@codesourcery.com>
+
+       * gdb.reverse/next-reverse-bkpt-over-sr.exp: New test.
+
 2011-05-24  Keith Seitz  <keiths@redhat.com>
 
        PR breakpoint/12803
diff --git a/gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp b/gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp
new file mode 100644 (file)
index 0000000..9a95dca
--- /dev/null
@@ -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"