2013-06-04 Gary Benson <gbenson@redhat.com>
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 54794867260197338644707dd1aa3ee67f4e87b7..51a032b8ae5aba39ab7ba6c8ad5edca138c0244a 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-struct-independent code to start (run) and stop an inferior
    process.
 
 /* Target-struct-independent code to start (run) and stop an inferior
    process.
 
-   Copyright (C) 1986-2012 Free Software Foundation, Inc.
+   Copyright (C) 1986-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    This file is part of GDB.
 
@@ -49,6 +49,7 @@
 #include "mi/mi-common.h"
 #include "event-top.h"
 #include "record.h"
 #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"
 #include "inline-frame.h"
 #include "jit.h"
 #include "tracepoint.h"
@@ -58,6 +59,7 @@
 #include "probe.h"
 #include "objfiles.h"
 #include "completer.h"
 #include "probe.h"
 #include "objfiles.h"
 #include "completer.h"
+#include "target-descriptions.h"
 
 /* Prototypes for local functions */
 
 
 /* Prototypes for local functions */
 
@@ -317,6 +319,12 @@ static unsigned char *signal_stop;
 static unsigned char *signal_print;
 static unsigned char *signal_program;
 
 static unsigned char *signal_print;
 static unsigned char *signal_program;
 
+/* Table of signals that are registered with "catch signal".  A
+   non-zero entry indicates that the signal is caught by some "catch
+   signal" command.  This has size GDB_SIGNAL_LAST, to accommodate all
+   signals.  */
+static unsigned char *signal_catch;
+
 /* Table of signals that the target may silently handle.
    This is automatically determined from the flags above,
    and simply cached here.  */
 /* Table of signals that the target may silently handle.
    This is automatically determined from the flags above,
    and simply cached here.  */
@@ -362,6 +370,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;
 /* 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)
 static void
 show_stop_on_solib_events (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c, const char *value)
@@ -396,7 +414,7 @@ static void context_switch (ptid_t ptid);
 
 void init_thread_stepping_state (struct thread_info *tss);
 
 
 void init_thread_stepping_state (struct thread_info *tss);
 
-void init_infwait_state (void);
+static void init_infwait_state (void);
 
 static const char follow_fork_mode_child[] = "child";
 static const char follow_fork_mode_parent[] = "parent";
 
 static const char follow_fork_mode_child[] = "child";
 static const char follow_fork_mode_parent[] = "parent";
@@ -663,7 +681,18 @@ handle_vfork_child_exec_or_exit (int exec)
 
          /* follow-fork child, detach-on-fork on.  */
 
 
          /* follow-fork child, detach-on-fork on.  */
 
-         old_chain = make_cleanup_restore_current_thread ();
+         inf->vfork_parent->pending_detach = 0;
+
+         if (!exec)
+           {
+             /* If we're handling a child exit, then inferior_ptid
+                points at the inferior's pid, not to a thread.  */
+             old_chain = save_inferior_ptid ();
+             save_current_program_space ();
+             save_current_inferior ();
+           }
+         else
+           old_chain = save_current_space_and_thread ();
 
          /* We're letting loose of the parent.  */
          tp = any_live_thread_of_process (inf->vfork_parent->pid);
 
          /* We're letting loose of the parent.  */
          tp = any_live_thread_of_process (inf->vfork_parent->pid);
@@ -787,7 +816,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";
 
 static const char follow_exec_mode_new[] = "new";
 static const char follow_exec_mode_same[] = "same";
@@ -902,6 +931,16 @@ follow_exec (ptid_t pid, char *execd_pathname)
       set_current_inferior (inf);
       set_current_program_space (pspace);
     }
       set_current_inferior (inf);
       set_current_program_space (pspace);
     }
+  else
+    {
+      /* The old description may no longer be fit for the new image.
+        E.g, a 64-bit process exec'ed a 32-bit process.  Clear the
+        old description; we'll read a new one below.  No need to do
+        this on "follow-exec-mode new", as the old inferior stays
+        around (its description is later cleared/refetched on
+        restart).  */
+      target_clear_description ();
+    }
 
   gdb_assert (current_program_space == inf->pspace);
 
 
   gdb_assert (current_program_space == inf->pspace);
 
@@ -921,11 +960,15 @@ follow_exec (ptid_t pid, char *execd_pathname)
   if ((inf->symfile_flags & SYMFILE_NO_READ) == 0)
     set_initial_language ();
 
   if ((inf->symfile_flags & SYMFILE_NO_READ) == 0)
     set_initial_language ();
 
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
-  SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
-#else
+  /* If the target can specify a description, read it.  Must do this
+     after flipping to the new executable (because the target supplied
+     description must be compatible with the executable's
+     architecture, and the old executable may e.g., be 32-bit, while
+     the new one 64-bit), and before anything involving memory or
+     registers.  */
+  target_find_description ();
+
   solib_create_inferior_hook (0);
   solib_create_inferior_hook (0);
-#endif
 
   jit_inferior_created_hook ();
 
 
   jit_inferior_created_hook ();
 
@@ -1278,6 +1321,7 @@ static int
 displaced_step_prepare (ptid_t ptid)
 {
   struct cleanup *old_cleanups, *ignore_cleanups;
 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;
   struct regcache *regcache = get_thread_regcache (ptid);
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   CORE_ADDR original, copy;
@@ -1290,6 +1334,12 @@ displaced_step_prepare (ptid_t ptid)
      support displaced stepping.  */
   gdb_assert (gdbarch_displaced_step_copy_insn_p (gdbarch));
 
      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.  */
 
   /* We have to displaced step one thread at a time, as we only have
      access to a single scratch space per inferior.  */
 
@@ -1745,6 +1795,11 @@ how to step past a permanent breakpoint on this architecture.  Try using\n\
 a command like `return' or `jump' to continue execution."));
     }
 
 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.
 
   /* If enabled, step over breakpoints by executing a copy of the
      instruction at a different address.
 
@@ -1906,6 +1961,16 @@ a command like `return' or `jump' to continue execution."));
           displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
         }
 
           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 ();
 
       /* Install inferior's terminal modes.  */
       target_terminal_inferior ();
 
@@ -1947,6 +2012,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.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;
   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;
@@ -2103,7 +2169,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
   struct thread_info *tp;
   CORE_ADDR pc;
   struct address_space *aspace;
   struct thread_info *tp;
   CORE_ADDR pc;
   struct address_space *aspace;
-  int oneproc = 0;
+  /* GDB may force the inferior to step due to various reasons.  */
+  int force_step = 0;
 
   /* If we're stopped at a fork/vfork, follow the branch set by the
      "set follow-fork-mode" command; otherwise, we'll just proceed
 
   /* If we're stopped at a fork/vfork, follow the branch set by the
      "set follow-fork-mode" command; otherwise, we'll just proceed
@@ -2143,13 +2210,13 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
           actually be executing the breakpoint insn anyway.
           We'll be (un-)executing the previous instruction.  */
 
           actually be executing the breakpoint insn anyway.
           We'll be (un-)executing the previous instruction.  */
 
-       oneproc = 1;
+       force_step = 1;
       else if (gdbarch_single_step_through_delay_p (gdbarch)
               && gdbarch_single_step_through_delay (gdbarch,
                                                     get_current_frame ()))
        /* We stepped onto an instruction that needs to be stepped
           again before re-inserting the breakpoint, do so.  */
       else if (gdbarch_single_step_through_delay_p (gdbarch)
               && gdbarch_single_step_through_delay (gdbarch,
                                                     get_current_frame ()))
        /* We stepped onto an instruction that needs to be stepped
           again before re-inserting the breakpoint, do so.  */
-       oneproc = 1;
+       force_step = 1;
     }
   else
     {
     }
   else
     {
@@ -2180,13 +2247,13 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
         is required it returns TRUE and sets the current thread to
         the old thread.  */
       if (prepare_to_proceed (step))
         is required it returns TRUE and sets the current thread to
         the old thread.  */
       if (prepare_to_proceed (step))
-       oneproc = 1;
+       force_step = 1;
     }
 
   /* prepare_to_proceed may change the current thread.  */
   tp = inferior_thread ();
 
     }
 
   /* prepare_to_proceed may change the current thread.  */
   tp = inferior_thread ();
 
-  if (oneproc)
+  if (force_step)
     {
       tp->control.trap_expected = 1;
       /* If displaced stepping is enabled, we can step over the
     {
       tp->control.trap_expected = 1;
       /* If displaced stepping is enabled, we can step over the
@@ -2274,7 +2341,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
   init_infwait_state ();
 
   /* Resume inferior.  */
   init_infwait_state ();
 
   /* Resume inferior.  */
-  resume (oneproc || step || bpstat_should_step (), tp->suspend.stop_signal);
+  resume (force_step || step || bpstat_should_step (),
+         tp->suspend.stop_signal);
 
   /* Wait for it to stop (if not standalone)
      and in any case decode why it stopped, and act accordingly.  */
 
   /* Wait for it to stop (if not standalone)
      and in any case decode why it stopped, and act accordingly.  */
@@ -2362,7 +2430,7 @@ enum infwait_states
 ptid_t waiton_ptid;
 
 /* Current inferior wait state.  */
 ptid_t waiton_ptid;
 
 /* Current inferior wait state.  */
-enum infwait_states infwait_state;
+static enum infwait_states infwait_state;
 
 /* Data to be passed around while handling an event.  This data is
    discarded between events.  */
 
 /* Data to be passed around while handling an event.  This data is
    discarded between events.  */
@@ -2969,10 +3037,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)))
     {
   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)
 
       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
 
       /* When using hardware single-step, a SIGTRAP is reported for both
         a completed single-step and a software breakpoint.  Need to
@@ -2998,32 +3066,17 @@ adjust_pc_after_break (struct execution_control_state *ecs)
          || ecs->event_thread->prev_pc == breakpoint_pc)
        regcache_write_pc (regcache, breakpoint_pc);
 
          || 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);
     }
 }
 
     }
 }
 
-void
+static void
 init_infwait_state (void)
 {
   waiton_ptid = pid_to_ptid (-1);
   infwait_state = infwait_normal_state;
 }
 
 init_infwait_state (void)
 {
   waiton_ptid = pid_to_ptid (-1);
   infwait_state = infwait_normal_state;
 }
 
-void
-error_is_running (void)
-{
-  error (_("Cannot execute this command while "
-          "the selected thread is running."));
-}
-
-void
-ensure_not_running (void)
-{
-  if (is_running (inferior_ptid))
-    error_is_running ();
-}
-
 static int
 stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id)
 {
 static int
 stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id)
 {
@@ -3049,20 +3102,20 @@ static int
 handle_syscall_event (struct execution_control_state *ecs)
 {
   struct regcache *regcache;
 handle_syscall_event (struct execution_control_state *ecs)
 {
   struct regcache *regcache;
-  struct gdbarch *gdbarch;
   int syscall_number;
 
   if (!ptid_equal (ecs->ptid, inferior_ptid))
     context_switch (ecs->ptid);
 
   regcache = get_thread_regcache (ecs->ptid);
   int syscall_number;
 
   if (!ptid_equal (ecs->ptid, inferior_ptid))
     context_switch (ecs->ptid);
 
   regcache = get_thread_regcache (ecs->ptid);
-  gdbarch = get_regcache_arch (regcache);
   syscall_number = ecs->ws.value.syscall_number;
   stop_pc = regcache_read_pc (regcache);
 
   if (catch_syscall_enabled () > 0
       && catching_syscall_number (syscall_number) > 0)
     {
   syscall_number = ecs->ws.value.syscall_number;
   stop_pc = regcache_read_pc (regcache);
 
   if (catch_syscall_enabled () > 0
       && catching_syscall_number (syscall_number) > 0)
     {
+      enum bpstat_signal_value sval;
+
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: syscall number = '%d'\n",
                             syscall_number);
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: syscall number = '%d'\n",
                             syscall_number);
@@ -3070,8 +3123,9 @@ handle_syscall_event (struct execution_control_state *ecs)
       ecs->event_thread->control.stop_bpstat
        = bpstat_stop_status (get_regcache_aspace (regcache),
                              stop_pc, ecs->ptid, &ecs->ws);
       ecs->event_thread->control.stop_bpstat
        = bpstat_stop_status (get_regcache_aspace (regcache),
                              stop_pc, ecs->ptid, &ecs->ws);
-      ecs->random_signal
-       = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+
+      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+      ecs->random_signal = sval == BPSTAT_SIGNAL_NO;
 
       if (!ecs->random_signal)
        {
 
       if (!ecs->random_signal)
        {
@@ -3201,6 +3255,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);
       /* 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.  */
     }
 
   /* Dependent on valid ECS->EVENT_THREAD.  */
@@ -3303,6 +3361,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       if (stop_soon == NO_STOP_QUIETLY)
        {
          struct regcache *regcache;
       if (stop_soon == NO_STOP_QUIETLY)
        {
          struct regcache *regcache;
+         enum bpstat_signal_value sval;
 
          if (!ptid_equal (ecs->ptid, inferior_ptid))
            context_switch (ecs->ptid);
 
          if (!ptid_equal (ecs->ptid, inferior_ptid))
            context_switch (ecs->ptid);
@@ -3313,8 +3372,10 @@ handle_inferior_event (struct execution_control_state *ecs)
          ecs->event_thread->control.stop_bpstat
            = bpstat_stop_status (get_regcache_aspace (regcache),
                                  stop_pc, ecs->ptid, &ecs->ws);
          ecs->event_thread->control.stop_bpstat
            = bpstat_stop_status (get_regcache_aspace (regcache),
                                  stop_pc, ecs->ptid, &ecs->ws);
-         ecs->random_signal
-           = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+
+         sval
+           = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+         ecs->random_signal = sval == BPSTAT_SIGNAL_NO;
 
          if (!ecs->random_signal)
            {
 
          if (!ecs->random_signal)
            {
@@ -3370,23 +3431,38 @@ handle_inferior_event (struct execution_control_state *ecs)
       return;
 
     case TARGET_WAITKIND_EXITED:
       return;
 
     case TARGET_WAITKIND_EXITED:
+    case TARGET_WAITKIND_SIGNALLED:
       if (debug_infrun)
       if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\n");
+       {
+         if (ecs->ws.kind == TARGET_WAITKIND_EXITED)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: TARGET_WAITKIND_EXITED\n");
+         else
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: TARGET_WAITKIND_SIGNALLED\n");
+       }
+
       inferior_ptid = ecs->ptid;
       set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid)));
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
       target_terminal_ours (); /* Must do this before mourn anyway.  */
       inferior_ptid = ecs->ptid;
       set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid)));
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
       target_terminal_ours (); /* Must do this before mourn anyway.  */
-      print_exited_reason (ecs->ws.value.integer);
 
 
-      /* Record the exit code in the convenience variable $_exitcode, so
-         that the user can inspect this again later.  */
-      set_internalvar_integer (lookup_internalvar ("_exitcode"),
-                              (LONGEST) ecs->ws.value.integer);
+      if (ecs->ws.kind == TARGET_WAITKIND_EXITED)
+       {
+         /* Record the exit code in the convenience variable $_exitcode, so
+            that the user can inspect this again later.  */
+         set_internalvar_integer (lookup_internalvar ("_exitcode"),
+                                  (LONGEST) ecs->ws.value.integer);
+
+         /* Also record this in the inferior itself.  */
+         current_inferior ()->has_exit_code = 1;
+         current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer;
 
 
-      /* Also record this in the inferior itself.  */
-      current_inferior ()->has_exit_code = 1;
-      current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer;
+         print_exited_reason (ecs->ws.value.integer);
+       }
+      else
+       print_signal_exited_reason (ecs->ws.value.sig);
 
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
 
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
@@ -3396,24 +3472,6 @@ handle_inferior_event (struct execution_control_state *ecs)
       stop_stepping (ecs);
       return;
 
       stop_stepping (ecs);
       return;
 
-    case TARGET_WAITKIND_SIGNALLED:
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n");
-      inferior_ptid = ecs->ptid;
-      set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid)));
-      set_current_program_space (current_inferior ()->pspace);
-      handle_vfork_child_exec_or_exit (0);
-      stop_print_frame = 0;
-      target_terminal_ours (); /* Must do this before mourn anyway.  */
-
-      target_mourn_inferior ();
-
-      print_signal_exited_reason (ecs->ws.value.sig);
-      singlestep_breakpoints_inserted_p = 0;
-      cancel_single_step_breakpoints ();
-      stop_stepping (ecs);
-      return;
-
       /* The following are the only cases in which we keep going;
          the above cases end in a continue or goto.  */
     case TARGET_WAITKIND_FORKED:
       /* The following are the only cases in which we keep going;
          the above cases end in a continue or goto.  */
     case TARGET_WAITKIND_FORKED:
@@ -3615,7 +3673,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_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)
+          == BPSTAT_SIGNAL_NO);
 
       /* Note that this may be referenced from inside
         bpstat_stop_status above, through inferior_has_execd.  */
 
       /* Note that this may be referenced from inside
         bpstat_stop_status above, through inferior_has_execd.  */
@@ -3756,7 +3815,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
          context_switch (saved_singlestep_ptid);
          if (deprecated_context_hook)
 
          context_switch (saved_singlestep_ptid);
          if (deprecated_context_hook)
-           deprecated_context_hook (pid_to_thread_id (ecs->ptid));
+           deprecated_context_hook (pid_to_thread_id (saved_singlestep_ptid));
 
          resume (1, GDB_SIGNAL_0);
          prepare_to_wait (ecs);
 
          resume (1, GDB_SIGNAL_0);
          prepare_to_wait (ecs);
@@ -4120,128 +4179,121 @@ handle_inferior_event (struct execution_control_state *ecs)
      will be made according to the signal handling tables.  */
 
   if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
      will be made according to the signal handling tables.  */
 
   if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-      || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
-      || stop_soon == STOP_QUIETLY_REMOTE)
+      && stop_after_trap)
     {
     {
-      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-         && stop_after_trap)
-       {
-          if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
-         stop_print_frame = 0;
-         stop_stepping (ecs);
-         return;
-       }
-
-      /* This is originated from start_remote(), start_inferior() and
-         shared libraries hook functions.  */
-      if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
-       {
-          if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
-         stop_stepping (ecs);
-         return;
-       }
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
+      stop_print_frame = 0;
+      stop_stepping (ecs);
+      return;
+    }
 
 
-      /* This originates from attach_command().  We need to overwrite
-        the stop_signal here, because some kernels don't ignore a
-        SIGSTOP in a subsequent ptrace(PTRACE_CONT,SIGSTOP) call.
-        See more comments in inferior.h.  On the other hand, if we
-        get a non-SIGSTOP, report it to the user - assume the backend
-        will handle the SIGSTOP if it should show up later.
-
-        Also consider that the attach is complete when we see a
-        SIGTRAP.  Some systems (e.g. Windows), and stubs supporting
-        target extended-remote report it instead of a SIGSTOP
-        (e.g. gdbserver).  We already rely on SIGTRAP being our
-        signal, so this is no exception.
-
-        Also consider that the attach is complete when we see a
-        GDB_SIGNAL_0.  In non-stop mode, GDB will explicitly tell
-        the target to stop all threads of the inferior, in case the
-        low level attach operation doesn't stop them implicitly.  If
-        they weren't stopped implicitly, then the stub will report a
-        GDB_SIGNAL_0, meaning: stopped for no particular reason
-        other than GDB's request.  */
-      if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
-         && (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_STOP
-             || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-             || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_0))
-       {
-         stop_stepping (ecs);
-         ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
-         return;
-       }
+  /* This is originated from start_remote(), start_inferior() and
+     shared libraries hook functions.  */
+  if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
+      stop_stepping (ecs);
+      return;
+    }
 
 
-      /* See if there is a breakpoint/watchpoint/catchpoint/etc. that
-        handles this event.  */
-      ecs->event_thread->control.stop_bpstat
-       = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
-                             stop_pc, ecs->ptid, &ecs->ws);
+  /* This originates from attach_command().  We need to overwrite
+     the stop_signal here, because some kernels don't ignore a
+     SIGSTOP in a subsequent ptrace(PTRACE_CONT,SIGSTOP) call.
+     See more comments in inferior.h.  On the other hand, if we
+     get a non-SIGSTOP, report it to the user - assume the backend
+     will handle the SIGSTOP if it should show up later.
+
+     Also consider that the attach is complete when we see a
+     SIGTRAP.  Some systems (e.g. Windows), and stubs supporting
+     target extended-remote report it instead of a SIGSTOP
+     (e.g. gdbserver).  We already rely on SIGTRAP being our
+     signal, so this is no exception.
+
+     Also consider that the attach is complete when we see a
+     GDB_SIGNAL_0.  In non-stop mode, GDB will explicitly tell
+     the target to stop all threads of the inferior, in case the
+     low level attach operation doesn't stop them implicitly.  If
+     they weren't stopped implicitly, then the stub will report a
+     GDB_SIGNAL_0, meaning: stopped for no particular reason
+     other than GDB's request.  */
+  if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
+      && (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_STOP
+         || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
+         || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_0))
+    {
+      stop_stepping (ecs);
+      ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+      return;
+    }
 
 
-      /* Following in case break condition called a
-        function.  */
-      stop_print_frame = 1;
-
-      /* This is where we handle "moribund" watchpoints.  Unlike
-        software breakpoints traps, hardware watchpoint traps are
-        always distinguishable from random traps.  If no high-level
-        watchpoint is associated with the reported stop data address
-        anymore, then the bpstat does not explain the signal ---
-        simply make sure to ignore it if `stopped_by_watchpoint' is
-        set.  */
-
-      if (debug_infrun
-         && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-         && !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
-         && stopped_by_watchpoint)
-       fprintf_unfiltered (gdb_stdlog,
-                           "infrun: no user watchpoint explains "
-                           "watchpoint SIGTRAP, ignoring\n");
+  /* See if there is a breakpoint/watchpoint/catchpoint/etc. that
+     handles this event.  */
+  ecs->event_thread->control.stop_bpstat
+    = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
+                         stop_pc, ecs->ptid, &ecs->ws);
 
 
-      /* NOTE: cagney/2003-03-29: These two checks for a random signal
-         at one stage in the past included checks for an inferior
-         function call's call dummy's return breakpoint.  The original
-         comment, that went with the test, read:
+  /* Following in case break condition called a
+     function.  */
+  stop_print_frame = 1;
 
 
-         ``End of a stack dummy.  Some systems (e.g. Sony news) give
-         another signal besides SIGTRAP, so check here as well as
-         above.''
+  /* This is where we handle "moribund" watchpoints.  Unlike
+     software breakpoints traps, hardware watchpoint traps are
+     always distinguishable from random traps.  If no high-level
+     watchpoint is associated with the reported stop data address
+     anymore, then the bpstat does not explain the signal ---
+     simply make sure to ignore it if `stopped_by_watchpoint' is
+     set.  */
+
+  if (debug_infrun
+      && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
+      && (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
+         == BPSTAT_SIGNAL_NO)
+      && stopped_by_watchpoint)
+    fprintf_unfiltered (gdb_stdlog,
+                       "infrun: no user watchpoint explains "
+                       "watchpoint SIGTRAP, ignoring\n");
 
 
-         If someone ever tries to get call dummys on a
-         non-executable stack to work (where the target would stop
-         with something like a SIGSEGV), then those tests might need
-         to be re-instated.  Given, however, that the tests were only
-         enabled when momentary breakpoints were not being used, I
-         suspect that it won't be the case.
+  /* NOTE: cagney/2003-03-29: These two checks for a random signal
+     at one stage in the past included checks for an inferior
+     function call's call dummy's return breakpoint.  The original
+     comment, that went with the test, read:
 
 
-         NOTE: kettenis/2004-02-05: Indeed such checks don't seem to
-         be necessary for call dummies on a non-executable stack on
-         SPARC.  */
+     ``End of a stack dummy.  Some systems (e.g. Sony news) give
+     another signal besides SIGTRAP, so check here as well as
+     above.''
 
 
-      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
-       ecs->random_signal
-         = !(bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
-             || stopped_by_watchpoint
-             || ecs->event_thread->control.trap_expected
-             || (ecs->event_thread->control.step_range_end
-                 && (ecs->event_thread->control.step_resume_breakpoint
-                     == NULL)));
-      else
-       {
-         ecs->random_signal = !bpstat_explains_signal
-                                    (ecs->event_thread->control.stop_bpstat);
-         if (!ecs->random_signal)
-           ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
-       }
-    }
+     If someone ever tries to get call dummys on a
+     non-executable stack to work (where the target would stop
+     with something like a SIGSEGV), then those tests might need
+     to be re-instated.  Given, however, that the tests were only
+     enabled when momentary breakpoints were not being used, I
+     suspect that it won't be the case.
 
 
-  /* When we reach this point, we've pretty much decided
-     that the reason for stopping must've been a random
-     (unexpected) signal.  */
+     NOTE: kettenis/2004-02-05: Indeed such checks don't seem to
+     be necessary for call dummies on a non-executable stack on
+     SPARC.  */
 
 
+  if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
+    ecs->random_signal
+      = !((bpstat_explains_signal (ecs->event_thread->control.stop_bpstat)
+          != BPSTAT_SIGNAL_NO)
+         || stopped_by_watchpoint
+         || ecs->event_thread->control.trap_expected
+         || (ecs->event_thread->control.step_range_end
+             && (ecs->event_thread->control.step_resume_breakpoint
+                 == NULL)));
   else
   else
-    ecs->random_signal = 1;
+    {
+      enum bpstat_signal_value sval;
+
+      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+      ecs->random_signal = (sval == BPSTAT_SIGNAL_NO);
+
+      if (sval == BPSTAT_SIGNAL_HIDE)
+       ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
+    }
 
 process_event_stop_test:
 
 
 process_event_stop_test:
 
@@ -4321,8 +4373,7 @@ process_event_stop_test:
 
       if (ecs->event_thread->control.step_range_end != 0
          && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0
 
       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)
          && frame_id_eq (get_stack_frame_id (frame),
                          ecs->event_thread->control.step_stack_frame_id)
          && ecs->event_thread->control.step_resume_breakpoint == NULL)
@@ -4691,8 +4742,7 @@ process_event_stop_test:
      through a function epilogue and therefore must detect when
      the current-frame changes in the middle of a line.  */
 
      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)))
       && (execution_direction != EXEC_REVERSE
          || frame_id_eq (get_frame_id (frame),
                          ecs->event_thread->control.step_frame_id)))
@@ -4703,6 +4753,11 @@ process_event_stop_test:
           paddress (gdbarch, ecs->event_thread->control.step_range_start),
           paddress (gdbarch, ecs->event_thread->control.step_range_end));
 
           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).  */
       /* 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).  */
@@ -4963,7 +5018,8 @@ process_event_stop_test:
 
        tmp_sal = find_pc_line (ecs->stop_func_start, 0);
        if (tmp_sal.line != 0
 
        tmp_sal = find_pc_line (ecs->stop_func_start, 0);
        if (tmp_sal.line != 0
-           && !function_pc_is_marked_for_skip (ecs->stop_func_start))
+           && !function_name_is_marked_for_skip (ecs->stop_func_name,
+                                                 &tmp_sal))
          {
            if (execution_direction == EXEC_REVERSE)
              handle_step_into_function_backward (gdbarch, ecs);
          {
            if (execution_direction == EXEC_REVERSE)
              handle_step_into_function_backward (gdbarch, ecs);
@@ -5218,6 +5274,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.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)
   set_step_info (frame, stop_pc_sal);
 
   if (debug_infrun)
@@ -6191,7 +6248,8 @@ signal_cache_update (int signo)
 
   signal_pass[signo] = (signal_stop[signo] == 0
                        && signal_print[signo] == 0
 
   signal_pass[signo] = (signal_stop[signo] == 0
                        && signal_print[signo] == 0
-                       && signal_program[signo] == 1);
+                       && signal_program[signo] == 1
+                       && signal_catch[signo] == 0);
 }
 
 int
 }
 
 int
@@ -6224,6 +6282,20 @@ signal_pass_update (int signo, int state)
   return ret;
 }
 
   return ret;
 }
 
+/* Update the global 'signal_catch' from INFO and notify the
+   target.  */
+
+void
+signal_catch_update (const unsigned int *info)
+{
+  int i;
+
+  for (i = 0; i < GDB_SIGNAL_LAST; ++i)
+    signal_catch[i] = info[i] > 0;
+  signal_cache_update (-1);
+  target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
+}
+
 static void
 sig_print_header (void)
 {
 static void
 sig_print_header (void)
 {
@@ -6435,7 +6507,7 @@ Are you sure you want to change it? "),
 
 static VEC (char_ptr) *
 handle_completer (struct cmd_list_element *ignore,
 
 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[] =
 {
   VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
   static const char * const keywords[] =
@@ -6708,7 +6780,9 @@ save_infcall_suspend_state (void)
 {
   struct infcall_suspend_state *inf_state;
   struct thread_info *tp = inferior_thread ();
 {
   struct infcall_suspend_state *inf_state;
   struct thread_info *tp = inferior_thread ();
+#if 0
   struct inferior *inf = current_inferior ();
   struct inferior *inf = current_inferior ();
+#endif
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   gdb_byte *siginfo_data = NULL;
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   gdb_byte *siginfo_data = NULL;
@@ -6763,7 +6837,9 @@ void
 restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
   struct thread_info *tp = inferior_thread ();
 restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
   struct thread_info *tp = inferior_thread ();
+#if 0
   struct inferior *inf = current_inferior ();
   struct inferior *inf = current_inferior ();
+#endif
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
 
   struct regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
 
@@ -7209,6 +7285,8 @@ leave it stopped or free to run as needed."),
     xmalloc (sizeof (signal_print[0]) * numsigs);
   signal_program = (unsigned char *)
     xmalloc (sizeof (signal_program[0]) * numsigs);
     xmalloc (sizeof (signal_print[0]) * numsigs);
   signal_program = (unsigned char *)
     xmalloc (sizeof (signal_program[0]) * numsigs);
+  signal_catch = (unsigned char *)
+    xmalloc (sizeof (signal_catch[0]) * numsigs);
   signal_pass = (unsigned char *)
     xmalloc (sizeof (signal_program[0]) * numsigs);
   for (i = 0; i < numsigs; i++)
   signal_pass = (unsigned char *)
     xmalloc (sizeof (signal_program[0]) * numsigs);
   for (i = 0; i < numsigs; i++)
@@ -7216,6 +7294,7 @@ leave it stopped or free to run as needed."),
       signal_stop[i] = 1;
       signal_print[i] = 1;
       signal_program[i] = 1;
       signal_stop[i] = 1;
       signal_print[i] = 1;
       signal_program[i] = 1;
+      signal_catch[i] = 0;
     }
 
   /* Signals caused by debugger's own actions
     }
 
   /* Signals caused by debugger's own actions
@@ -7264,7 +7343,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."),
 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);
 
                            show_stop_on_solib_events,
                            &setlist, &showlist);
 
This page took 0.038874 seconds and 4 git commands to generate.