Remove deprecated_throw_reason.
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 1cf30feff2c1d290fd9e00fd3046d25c8f22d2a1..dc1036d76114f8687fe948716e5ddbd78f4cd98c 100644 (file)
@@ -49,6 +49,7 @@
 #include "mi/mi-common.h"
 #include "event-top.h"
 #include "record.h"
+#include "record-full.h"
 #include "inline-frame.h"
 #include "jit.h"
 #include "tracepoint.h"
@@ -180,64 +181,37 @@ set_disable_randomization (char *args, int from_tty,
             "this platform."));
 }
 
+/* User interface for non-stop mode.  */
 
-/* If the program uses ELF-style shared libraries, then calls to
-   functions in shared libraries go through stubs, which live in a
-   table called the PLT (Procedure Linkage Table).  The first time the
-   function is called, the stub sends control to the dynamic linker,
-   which looks up the function's real address, patches the stub so
-   that future calls will go directly to the function, and then passes
-   control to the function.
-
-   If we are stepping at the source level, we don't want to see any of
-   this --- we just want to skip over the stub and the dynamic linker.
-   The simple approach is to single-step until control leaves the
-   dynamic linker.
-
-   However, on some systems (e.g., Red Hat's 5.2 distribution) the
-   dynamic linker calls functions in the shared C library, so you
-   can't tell from the PC alone whether the dynamic linker is still
-   running.  In this case, we use a step-resume breakpoint to get us
-   past the dynamic linker, as if we were using "next" to step over a
-   function call.
-
-   in_solib_dynsym_resolve_code() says whether we're in the dynamic
-   linker code or not.  Normally, this means we single-step.  However,
-   if SKIP_SOLIB_RESOLVER then returns non-zero, then its value is an
-   address where we can place a step-resume breakpoint to get past the
-   linker's symbol resolution function.
-
-   in_solib_dynsym_resolve_code() can generally be implemented in a
-   pretty portable way, by comparing the PC against the address ranges
-   of the dynamic linker's sections.
-
-   SKIP_SOLIB_RESOLVER is generally going to be system-specific, since
-   it depends on internal details of the dynamic linker.  It's usually
-   not too hard to figure out where to put a breakpoint, but it
-   certainly isn't portable.  SKIP_SOLIB_RESOLVER should do plenty of
-   sanity checking.  If it can't figure things out, returning zero and
-   getting the (possibly confusing) stepping behavior is better than
-   signalling an error, which will obscure the change in the
-   inferior's state.  */
-
-/* This function returns TRUE if pc is the address of an instruction
-   that lies within the dynamic linker (such as the event hook, or the
-   dld itself).
-
-   This function must be used only when a dynamic linker event has
-   been caught, and the inferior is being stepped out of the hook, or
-   undefined results are guaranteed.  */
-
-#ifndef SOLIB_IN_DYNAMIC_LINKER
-#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
-#endif
+int non_stop = 0;
+static int non_stop_1 = 0;
+
+static void
+set_non_stop (char *args, int from_tty,
+             struct cmd_list_element *c)
+{
+  if (target_has_execution)
+    {
+      non_stop_1 = non_stop;
+      error (_("Cannot change this setting while the inferior is running."));
+    }
+
+  non_stop = non_stop_1;
+}
+
+static void
+show_non_stop (struct ui_file *file, int from_tty,
+              struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file,
+                   _("Controlling the inferior in non-stop mode is %s.\n"),
+                   value);
+}
 
 /* "Observer mode" is somewhat like a more extreme version of
    non-stop, in which all GDB operations that might affect the
    target's execution have been disabled.  */
 
-static int non_stop_1 = 0;
-
 int observer_mode = 0;
 static int observer_mode_1 = 0;
 
@@ -245,8 +219,6 @@ static void
 set_observer_mode (char *args, int from_tty,
                   struct cmd_list_element *c)
 {
-  extern int pagination_enabled;
-
   if (target_has_execution)
     {
       observer_mode_1 = observer_mode;
@@ -369,6 +341,16 @@ static struct symbol *step_start_function;
 /* Nonzero if we want to give control to the user when we're notified
    of shared library events by the dynamic linker.  */
 int stop_on_solib_events;
+
+/* Enable or disable optional shared library event breakpoints
+   as appropriate when the above flag is changed.  */
+
+static void
+set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
+{
+  update_solib_breakpoints ();
+}
+
 static void
 show_stop_on_solib_events (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c, const char *value)
@@ -805,7 +787,7 @@ handle_vfork_child_exec_or_exit (int exec)
     }
 }
 
-/* Enum strings for "set|show displaced-stepping".  */
+/* Enum strings for "set|show follow-exec-mode".  */
 
 static const char follow_exec_mode_new[] = "new";
 static const char follow_exec_mode_same[] = "same";
@@ -957,11 +939,7 @@ follow_exec (ptid_t pid, char *execd_pathname)
      registers.  */
   target_find_description ();
 
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
-  SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
-#else
   solib_create_inferior_hook (0);
-#endif
 
   jit_inferior_created_hook ();
 
@@ -1314,6 +1292,7 @@ static int
 displaced_step_prepare (ptid_t ptid)
 {
   struct cleanup *old_cleanups, *ignore_cleanups;
+  struct thread_info *tp = find_thread_ptid (ptid);
   struct regcache *regcache = get_thread_regcache (ptid);
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   CORE_ADDR original, copy;
@@ -1326,6 +1305,12 @@ displaced_step_prepare (ptid_t ptid)
      support displaced stepping.  */
   gdb_assert (gdbarch_displaced_step_copy_insn_p (gdbarch));
 
+  /* Disable range stepping while executing in the scratch pad.  We
+     want a single-step even if executing the displaced instruction in
+     the scratch buffer lands within the stepping range (e.g., a
+     jump/branch).  */
+  tp->control.may_range_step = 0;
+
   /* We have to displaced step one thread at a time, as we only have
      access to a single scratch space per inferior.  */
 
@@ -1781,6 +1766,11 @@ how to step past a permanent breakpoint on this architecture.  Try using\n\
 a command like `return' or `jump' to continue execution."));
     }
 
+  /* If we have a breakpoint to step over, make sure to do a single
+     step only.  Same if we have software watchpoints.  */
+  if (tp->control.trap_expected || bpstat_should_step ())
+    tp->control.may_range_step = 0;
+
   /* If enabled, step over breakpoints by executing a copy of the
      instruction at a different address.
 
@@ -1942,6 +1932,16 @@ a command like `return' or `jump' to continue execution."));
           displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
         }
 
+      if (tp->control.may_range_step)
+       {
+         /* If we're resuming a thread with the PC out of the step
+            range, then we're doing some nested/finer run control
+            operation, like stepping the thread out of the dynamic
+            linker or the displaced stepping scratch pad.  We
+            shouldn't have allowed a range step then.  */
+         gdb_assert (pc_in_thread_step_range (pc, tp));
+       }
+
       /* Install inferior's terminal modes.  */
       target_terminal_inferior ();
 
@@ -1983,6 +1983,7 @@ clear_proceed_status_thread (struct thread_info *tp)
   tp->control.trap_expected = 0;
   tp->control.step_range_start = 0;
   tp->control.step_range_end = 0;
+  tp->control.may_range_step = 0;
   tp->control.step_frame_id = null_frame_id;
   tp->control.step_stack_frame_id = null_frame_id;
   tp->control.step_over_calls = STEP_OVER_UNDEBUGGABLE;
@@ -3007,10 +3008,10 @@ adjust_pc_after_break (struct execution_control_state *ecs)
   if (software_breakpoint_inserted_here_p (aspace, breakpoint_pc)
       || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
-      struct cleanup *old_cleanups = NULL;
+      struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
 
       if (RECORD_IS_USED)
-       old_cleanups = record_gdb_operation_disable_set ();
+       record_full_gdb_operation_disable_set ();
 
       /* When using hardware single-step, a SIGTRAP is reported for both
         a completed single-step and a software breakpoint.  Need to
@@ -3036,8 +3037,7 @@ adjust_pc_after_break (struct execution_control_state *ecs)
          || ecs->event_thread->prev_pc == breakpoint_pc)
        regcache_write_pc (regcache, breakpoint_pc);
 
-      if (RECORD_IS_USED)
-       do_cleanups (old_cleanups);
+      do_cleanups (old_cleanups);
     }
 }
 
@@ -3095,7 +3095,8 @@ handle_syscall_event (struct execution_control_state *ecs)
        = bpstat_stop_status (get_regcache_aspace (regcache),
                              stop_pc, ecs->ptid, &ecs->ws);
 
-      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                    GDB_SIGNAL_TRAP);
       ecs->random_signal = sval == BPSTAT_SIGNAL_NO;
 
       if (!ecs->random_signal)
@@ -3226,6 +3227,10 @@ handle_inferior_event (struct execution_control_state *ecs)
       /* If it's a new thread, add it to the thread database.  */
       if (ecs->event_thread == NULL)
        ecs->event_thread = add_thread (ecs->ptid);
+
+      /* Disable range stepping.  If the next step request could use a
+        range, this will be end up re-enabled then.  */
+      ecs->event_thread->control.may_range_step = 0;
     }
 
   /* Dependent on valid ECS->EVENT_THREAD.  */
@@ -3341,7 +3346,8 @@ handle_inferior_event (struct execution_control_state *ecs)
                                  stop_pc, ecs->ptid, &ecs->ws);
 
          sval
-           = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+           = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                     GDB_SIGNAL_TRAP);
          ecs->random_signal = sval == BPSTAT_SIGNAL_NO;
 
          if (!ecs->random_signal)
@@ -3640,7 +3646,8 @@ handle_inferior_event (struct execution_control_state *ecs)
        = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
                              stop_pc, ecs->ptid, &ecs->ws);
       ecs->random_signal
-       = (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
+       = (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                  GDB_SIGNAL_TRAP)
           == BPSTAT_SIGNAL_NO);
 
       /* Note that this may be referenced from inside
@@ -4215,7 +4222,8 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   if (debug_infrun
       && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-      && (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
+      && (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                 GDB_SIGNAL_TRAP)
          == BPSTAT_SIGNAL_NO)
       && stopped_by_watchpoint)
     fprintf_unfiltered (gdb_stdlog,
@@ -4244,7 +4252,8 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
     ecs->random_signal
-      = !((bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
+      = !((bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                  GDB_SIGNAL_TRAP)
           != BPSTAT_SIGNAL_NO)
          || stopped_by_watchpoint
          || ecs->event_thread->control.trap_expected
@@ -4255,7 +4264,8 @@ handle_inferior_event (struct execution_control_state *ecs)
     {
       enum bpstat_signal_value sval;
 
-      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
+                                    ecs->event_thread->suspend.stop_signal);
       ecs->random_signal = (sval == BPSTAT_SIGNAL_NO);
 
       if (sval == BPSTAT_SIGNAL_HIDE)
@@ -4340,8 +4350,7 @@ process_event_stop_test:
 
       if (ecs->event_thread->control.step_range_end != 0
          && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0
-         && (ecs->event_thread->control.step_range_start <= stop_pc
-             && stop_pc < ecs->event_thread->control.step_range_end)
+         && pc_in_thread_step_range (stop_pc, ecs->event_thread)
          && frame_id_eq (get_stack_frame_id (frame),
                          ecs->event_thread->control.step_stack_frame_id)
          && ecs->event_thread->control.step_resume_breakpoint == NULL)
@@ -4710,8 +4719,7 @@ process_event_stop_test:
      through a function epilogue and therefore must detect when
      the current-frame changes in the middle of a line.  */
 
-  if (stop_pc >= ecs->event_thread->control.step_range_start
-      && stop_pc < ecs->event_thread->control.step_range_end
+  if (pc_in_thread_step_range (stop_pc, ecs->event_thread)
       && (execution_direction != EXEC_REVERSE
          || frame_id_eq (get_frame_id (frame),
                          ecs->event_thread->control.step_frame_id)))
@@ -4722,6 +4730,11 @@ process_event_stop_test:
           paddress (gdbarch, ecs->event_thread->control.step_range_start),
           paddress (gdbarch, ecs->event_thread->control.step_range_end));
 
+      /* Tentatively re-enable range stepping; `resume' disables it if
+        necessary (e.g., if we're stepping over a breakpoint or we
+        have software watchpoints).  */
+      ecs->event_thread->control.may_range_step = 1;
+
       /* When stepping backward, stop at beginning of line range
         (unless it's the function entry point, in which case
         keep going back to the call point).  */
@@ -5238,6 +5251,7 @@ process_event_stop_test:
 
   ecs->event_thread->control.step_range_start = stop_pc_sal.pc;
   ecs->event_thread->control.step_range_end = stop_pc_sal.end;
+  ecs->event_thread->control.may_range_step = 1;
   set_step_info (frame, stop_pc_sal);
 
   if (debug_infrun)
@@ -6470,7 +6484,7 @@ Are you sure you want to change it? "),
 
 static VEC (char_ptr) *
 handle_completer (struct cmd_list_element *ignore,
-                 char *text, char *word)
+                 const char *text, const char *word)
 {
   VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
   static const char * const keywords[] =
@@ -7094,32 +7108,6 @@ show_exec_direction_func (struct ui_file *out, int from_tty,
   }
 }
 
-/* User interface for non-stop mode.  */
-
-int non_stop = 0;
-
-static void
-set_non_stop (char *args, int from_tty,
-             struct cmd_list_element *c)
-{
-  if (target_has_execution)
-    {
-      non_stop_1 = non_stop;
-      error (_("Cannot change this setting while the inferior is running."));
-    }
-
-  non_stop = non_stop_1;
-}
-
-static void
-show_non_stop (struct ui_file *file, int from_tty,
-              struct cmd_list_element *c, const char *value)
-{
-  fprintf_filtered (file,
-                   _("Controlling the inferior in non-stop mode is %s.\n"),
-                   value);
-}
-
 static void
 show_schedule_multiple (struct ui_file *file, int from_tty,
                        struct cmd_list_element *c, const char *value)
@@ -7306,7 +7294,7 @@ Show stopping for shared library events."), _("\
 If nonzero, gdb will give control to the user when the dynamic linker\n\
 notifies gdb of shared library events.  The most common event of interest\n\
 to the user would be loading/unloading of a new library."),
-                           NULL,
+                           set_stop_on_solib_events,
                            show_stop_on_solib_events,
                            &setlist, &showlist);
 
This page took 0.040472 seconds and 4 git commands to generate.