make "permanent breakpoints" per location and disableable
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 0f30a623f25fdab174c69ccea4688b5d90f829eb..f57920fd3594e5ab2d531a00ba43cdeb91736140 100644 (file)
@@ -458,10 +458,11 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
          if (info_verbose || debug_infrun)
            {
-             target_terminal_ours ();
+             target_terminal_ours_for_output ();
              fprintf_filtered (gdb_stdlog,
-                               "Detaching after fork from "
-                               "child process %d.\n",
+                               _("Detaching after %s from "
+                                 "child process %d.\n"),
+                               has_vforked ? "vfork" : "fork",
                                child_pid);
            }
        }
@@ -546,17 +547,13 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
       if (info_verbose || debug_infrun)
        {
-         target_terminal_ours ();
-         if (has_vforked)
-           fprintf_filtered (gdb_stdlog,
-                             _("Attaching after process %d "
-                               "vfork to child process %d.\n"),
-                             parent_pid, child_pid);
-         else
-           fprintf_filtered (gdb_stdlog,
-                             _("Attaching after process %d "
-                               "fork to child process %d.\n"),
-                             parent_pid, child_pid);
+         target_terminal_ours_for_output ();
+         fprintf_filtered (gdb_stdlog,
+                           _("Attaching after process %d "
+                             "%s to child process %d.\n"),
+                           parent_pid,
+                           has_vforked ? "vfork" : "fork",
+                           child_pid);
        }
 
       /* Add the new inferior first, so that the target_detach below
@@ -593,7 +590,18 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          parent_inf->waiting_for_vfork_done = 0;
        }
       else if (detach_fork)
-       target_detach (NULL, 0);
+       {
+         if (info_verbose || debug_infrun)
+           {
+             target_terminal_ours_for_output ();
+             fprintf_filtered (gdb_stdlog,
+                               _("Detaching after fork from "
+                                 "child process %d.\n"),
+                               child_pid);
+           }
+
+         target_detach (NULL, 0);
+       }
 
       /* Note that the detach above makes PARENT_INF dangling.  */
 
@@ -927,18 +935,22 @@ handle_vfork_child_exec_or_exit (int exec)
 
          if (debug_infrun || info_verbose)
            {
-             target_terminal_ours ();
+             target_terminal_ours_for_output ();
 
              if (exec)
-               fprintf_filtered (gdb_stdlog,
-                                 "Detaching vfork parent process "
-                                 "%d after child exec.\n",
-                                 inf->vfork_parent->pid);
+               {
+                 fprintf_filtered (gdb_stdlog,
+                                   _("Detaching vfork parent process "
+                                     "%d after child exec.\n"),
+                                   inf->vfork_parent->pid);
+               }
              else
-               fprintf_filtered (gdb_stdlog,
-                                 "Detaching vfork parent process "
-                                 "%d after child exit.\n",
-                                 inf->vfork_parent->pid);
+               {
+                 fprintf_filtered (gdb_stdlog,
+                                   _("Detaching vfork parent process "
+                                     "%d after child exit.\n"),
+                                   inf->vfork_parent->pid);
+               }
            }
 
          target_detach (NULL, 0);
@@ -2063,13 +2075,7 @@ resume (int step, enum gdb_signal sig)
      breakpoints can't be removed.  So we have to test for it here.  */
   if (breakpoint_here_p (aspace, pc) == permanent_breakpoint_here)
     {
-      if (gdbarch_skip_permanent_breakpoint_p (gdbarch))
-       gdbarch_skip_permanent_breakpoint (gdbarch, regcache);
-      else
-       error (_("\
-The program is stopped at a permanent breakpoint, but GDB does not know\n\
-how to step past a permanent breakpoint on this architecture.  Try using\n\
-a command like `return' or `jump' to continue execution."));
+      gdbarch_skip_permanent_breakpoint (gdbarch, regcache);
     }
 
   /* If we have a breakpoint to step over, make sure to do a single
@@ -2089,8 +2095,7 @@ a command like `return' or `jump' to continue execution."));
      event, displaced stepping breaks the vfork child similarly as single
      step software breakpoint.  */
   if (use_displaced_stepping (gdbarch)
-      && (tp->control.trap_expected
-         || (step && gdbarch_software_single_step_p (gdbarch)))
+      && tp->control.trap_expected
       && sig == GDB_SIGNAL_0
       && !current_inferior ()->waiting_for_vfork_done)
     {
@@ -2202,12 +2207,35 @@ a command like `return' or `jump' to continue execution."));
       resume_ptid = inferior_ptid;
     }
 
-  if (gdbarch_cannot_step_breakpoint (gdbarch))
-    {
+  if (execution_direction != EXEC_REVERSE
+      && step && breakpoint_inserted_here_p (aspace, pc))
+    {
+      /* The only case we currently need to step a breakpoint
+        instruction is when we have a signal to deliver.  See
+        handle_signal_stop where we handle random signals that could
+        take out us out of the stepping range.  Normally, in that
+        case we end up continuing (instead of stepping) over the
+        signal handler with a breakpoint at PC, but there are cases
+        where we should _always_ single-step, even if we have a
+        step-resume breakpoint, like when a software watchpoint is
+        set.  Assuming single-stepping and delivering a signal at the
+        same time would takes us to the signal handler, then we could
+        have removed the breakpoint at PC to step over it.  However,
+        some hardware step targets (like e.g., Mac OS) can't step
+        into signal handlers, and for those, we need to leave the
+        breakpoint at PC inserted, as otherwise if the handler
+        recurses and executes PC again, it'll miss the breakpoint.
+        So we leave the breakpoint inserted anyway, but we need to
+        record that we tried to step a breakpoint instruction, so
+        that adjust_pc_after_break doesn't end up confused.  */
+      gdb_assert (sig != GDB_SIGNAL_0);
+
+      tp->stepped_breakpoint = 1;
+
       /* Most targets can step a breakpoint instruction, thus
         executing it normally.  But if this one cannot, just
         continue and we will hit it anyway.  */
-      if (step && breakpoint_inserted_here_p (aspace, pc))
+      if (gdbarch_cannot_step_breakpoint (gdbarch))
        step = 0;
     }
 
@@ -3073,6 +3101,23 @@ wait_for_inferior (void)
   do_cleanups (old_cleanups);
 }
 
+/* Cleanup that reinstalls the readline callback handler, if the
+   target is running in the background.  If while handling the target
+   event something triggered a secondary prompt, like e.g., a
+   pagination prompt, we'll have removed the callback handler (see
+   gdb_readline_wrapper_line).  Need to do this as we go back to the
+   event loop, ready to process further input.  Note this has no
+   effect if the handler hasn't actually been removed, because calling
+   rl_callback_handler_install resets the line buffer, thus losing
+   input.  */
+
+static void
+reinstall_readline_callback_handler_cleanup (void *arg)
+{
+  if (async_command_editing_p && !sync_execution)
+    gdb_rl_callback_handler_reinstall ();
+}
+
 /* Asynchronous version of wait_for_inferior.  It is called by the
    event loop whenever a change of state is detected on the file
    descriptor corresponding to the target.  It can be called more than
@@ -3095,6 +3140,9 @@ fetch_inferior_event (void *client_data)
 
   memset (ecs, 0, sizeof (*ecs));
 
+  /* End up with readline processing input, if necessary.  */
+  make_cleanup (reinstall_readline_callback_handler_cleanup, NULL);
+
   /* We're handling a live event, so make sure we're doing live
      debugging.  If we're looking at traceframes while the target is
      running, we're going to need to get back to that mode after
@@ -3210,6 +3258,7 @@ set_step_info (struct frame_info *frame, struct symtab_and_line sal)
 void
 init_thread_stepping_state (struct thread_info *tss)
 {
+  tss->stepped_breakpoint = 0;
   tss->stepping_over_breakpoint = 0;
   tss->stepping_over_watchpoint = 0;
   tss->step_after_step_resume_breakpoint = 0;
@@ -3374,7 +3423,8 @@ adjust_pc_after_break (struct execution_control_state *ecs)
       if (thread_has_single_step_breakpoints_set (ecs->event_thread)
          || !ptid_equal (ecs->ptid, inferior_ptid)
          || !currently_stepping (ecs->event_thread)
-         || ecs->event_thread->prev_pc == breakpoint_pc)
+         || (ecs->event_thread->stepped_breakpoint
+             && ecs->event_thread->prev_pc == breakpoint_pc))
        regcache_write_pc (regcache, breakpoint_pc);
 
       do_cleanups (old_cleanups);
@@ -4230,6 +4280,7 @@ handle_signal_stop (struct execution_control_state *ecs)
       return;
     }
 
+  ecs->event_thread->stepped_breakpoint = 0;
   ecs->event_thread->stepping_over_breakpoint = 0;
   ecs->event_thread->stepping_over_watchpoint = 0;
   bpstat_clear (&ecs->event_thread->control.stop_bpstat);
@@ -4452,9 +4503,9 @@ handle_signal_stop (struct execution_control_state *ecs)
          return;
        }
 
-      if (ecs->event_thread->control.step_range_end != 0
-         && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0
-         && pc_in_thread_step_range (stop_pc, ecs->event_thread)
+      if (ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0
+         && (pc_in_thread_step_range (stop_pc, ecs->event_thread)
+             || ecs->event_thread->control.step_range_end == 1)
          && frame_id_eq (get_stack_frame_id (frame),
                          ecs->event_thread->control.step_stack_frame_id)
          && ecs->event_thread->control.step_resume_breakpoint == NULL)
@@ -4474,6 +4525,7 @@ handle_signal_stop (struct execution_control_state *ecs)
                                 "single-step range\n");
 
          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;
          keep_going (ecs);
@@ -4946,17 +4998,11 @@ process_event_stop_test (struct execution_control_state *ecs)
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: stepped into subroutine\n");
 
-      if ((ecs->event_thread->control.step_over_calls == STEP_OVER_NONE)
-         || ((ecs->event_thread->control.step_range_end == 1)
-             && in_prologue (gdbarch, ecs->event_thread->prev_pc,
-                             ecs->stop_func_start)))
+      if (ecs->event_thread->control.step_over_calls == STEP_OVER_NONE)
        {
          /* I presume that step_over_calls is only 0 when we're
             supposed to be stepping at the assembly language level
             ("stepi").  Just stop.  */
-         /* Also, maybe we just did a "nexti" inside a prolog, so we
-            thought it was a subroutine call but it was not.  Stop as
-            well.  FENN */
          /* And this works the same backward as frontward.  MVS */
          end_stepping_range (ecs);
          return;
@@ -5404,7 +5450,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
                 stepping, then scheduler locking can't be in effect,
                 otherwise we wouldn't have resumed the current event
                 thread in the first place.  */
-             gdb_assert (!schedlock_applies (1));
+             gdb_assert (!schedlock_applies (currently_stepping (tp)));
 
              stepping_thread = tp;
            }
This page took 0.027979 seconds and 4 git commands to generate.