PR gdb/11321
[deliverable/binutils-gdb.git] / gdb / infrun.c
index a657026b8b895972cb735381f5d6abaa149e0b15..83cfe3c124be228d6df9f59858fa61ef469dbd43 100644 (file)
@@ -51,6 +51,7 @@
 #include "record.h"
 #include "inline-frame.h"
 #include "jit.h"
+#include "tracepoint.h"
 
 /* Prototypes for local functions */
 
@@ -68,8 +69,6 @@ static int hook_stop_stub (void *);
 
 static int restore_selected_frame (void *);
 
-static void build_infrun (void);
-
 static int follow_fork (void);
 
 static void set_schedlock_func (char *args, int from_tty,
@@ -764,7 +763,7 @@ follow_exec (ptid_t pid, char *execd_pathname)
 #ifdef SOLIB_CREATE_INFERIOR_HOOK
   SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
 #else
-  solib_create_inferior_hook ();
+  solib_create_inferior_hook (0);
 #endif
 
   jit_inferior_created_hook ();
@@ -893,32 +892,118 @@ static ptid_t deferred_step_ptid;
    displaced step operation on it.  See displaced_step_prepare and
    displaced_step_fixup for details.  */
 
-/* If this is not null_ptid, this is the thread carrying out a
-   displaced single-step.  This thread's state will require fixing up
-   once it has completed its step.  */
-static ptid_t displaced_step_ptid;
-
 struct displaced_step_request
 {
   ptid_t ptid;
   struct displaced_step_request *next;
 };
 
-/* A queue of pending displaced stepping requests.  */
-struct displaced_step_request *displaced_step_request_queue;
+/* Per-inferior displaced stepping state.  */
+struct displaced_step_inferior_state
+{
+  /* Pointer to next in linked list.  */
+  struct displaced_step_inferior_state *next;
+
+  /* The process this displaced step state refers to.  */
+  int pid;
+
+  /* A queue of pending displaced stepping requests.  One entry per
+     thread that needs to do a displaced step.  */
+  struct displaced_step_request *step_request_queue;
 
-/* The architecture the thread had when we stepped it.  */
-static struct gdbarch *displaced_step_gdbarch;
+  /* If this is not null_ptid, this is the thread carrying out a
+     displaced single-step in process PID.  This thread's state will
+     require fixing up once it has completed its step.  */
+  ptid_t step_ptid;
+
+  /* The architecture the thread had when we stepped it.  */
+  struct gdbarch *step_gdbarch;
+
+  /* The closure provided gdbarch_displaced_step_copy_insn, to be used
+     for post-step cleanup.  */
+  struct displaced_step_closure *step_closure;
+
+  /* The address of the original instruction, and the copy we
+     made.  */
+  CORE_ADDR step_original, step_copy;
+
+  /* Saved contents of copy area.  */
+  gdb_byte *step_saved_copy;
+};
 
-/* The closure provided gdbarch_displaced_step_copy_insn, to be used
-   for post-step cleanup.  */
-static struct displaced_step_closure *displaced_step_closure;
+/* The list of states of processes involved in displaced stepping
+   presently.  */
+static struct displaced_step_inferior_state *displaced_step_inferior_states;
+
+/* Get the displaced stepping state of process PID.  */
+
+static struct displaced_step_inferior_state *
+get_displaced_stepping_state (int pid)
+{
+  struct displaced_step_inferior_state *state;
+
+  for (state = displaced_step_inferior_states;
+       state != NULL;
+       state = state->next)
+    if (state->pid == pid)
+      return state;
+
+  return NULL;
+}
+
+/* Add a new displaced stepping state for process PID to the displaced
+   stepping state list, or return a pointer to an already existing
+   entry, if it already exists.  Never returns NULL.  */
+
+static struct displaced_step_inferior_state *
+add_displaced_stepping_state (int pid)
+{
+  struct displaced_step_inferior_state *state;
 
-/* The address of the original instruction, and the copy we made.  */
-static CORE_ADDR displaced_step_original, displaced_step_copy;
+  for (state = displaced_step_inferior_states;
+       state != NULL;
+       state = state->next)
+    if (state->pid == pid)
+      return state;
 
-/* Saved contents of copy area.  */
-static gdb_byte *displaced_step_saved_copy;
+  state = xcalloc (1, sizeof (*state));
+  state->pid = pid;
+  state->next = displaced_step_inferior_states;
+  displaced_step_inferior_states = state;
+
+  return state;
+}
+
+/* Remove the displaced stepping state of process PID.  */
+
+static void
+remove_displaced_stepping_state (int pid)
+{
+  struct displaced_step_inferior_state *it, **prev_next_p;
+
+  gdb_assert (pid != 0);
+
+  it = displaced_step_inferior_states;
+  prev_next_p = &displaced_step_inferior_states;
+  while (it)
+    {
+      if (it->pid == pid)
+       {
+         *prev_next_p = it->next;
+         xfree (it);
+         return;
+       }
+
+      prev_next_p = &it->next;
+      it = *prev_next_p;
+    }
+}
+
+static void
+infrun_inferior_exit (struct inferior *inf)
+{
+  remove_displaced_stepping_state (inf->pid);
+}
 
 /* Enum strings for "set|show displaced-stepping".  */
 
@@ -975,23 +1060,25 @@ use_displaced_stepping (struct gdbarch *gdbarch)
 
 /* Clean out any stray displaced stepping state.  */
 static void
-displaced_step_clear (void)
+displaced_step_clear (struct displaced_step_inferior_state *displaced)
 {
   /* Indicate that there is no cleanup pending.  */
-  displaced_step_ptid = null_ptid;
+  displaced->step_ptid = null_ptid;
 
-  if (displaced_step_closure)
+  if (displaced->step_closure)
     {
-      gdbarch_displaced_step_free_closure (displaced_step_gdbarch,
-                                           displaced_step_closure);
-      displaced_step_closure = NULL;
+      gdbarch_displaced_step_free_closure (displaced->step_gdbarch,
+                                           displaced->step_closure);
+      displaced->step_closure = NULL;
     }
 }
 
 static void
-displaced_step_clear_cleanup (void *ignore)
+displaced_step_clear_cleanup (void *arg)
 {
-  displaced_step_clear ();
+  struct displaced_step_inferior_state *state = arg;
+
+  displaced_step_clear (state);
 }
 
 /* Dump LEN bytes at BUF in hex to FILE, followed by a newline.  */
@@ -1030,15 +1117,18 @@ displaced_step_prepare (ptid_t ptid)
   CORE_ADDR original, copy;
   ULONGEST len;
   struct displaced_step_closure *closure;
+  struct displaced_step_inferior_state *displaced;
 
   /* We should never reach this function if the architecture does not
      support displaced stepping.  */
   gdb_assert (gdbarch_displaced_step_copy_insn_p (gdbarch));
 
-  /* For the first cut, we're displaced stepping one thread at a
-     time.  */
+  /* We have to displaced step one thread at a time, as we only have
+     access to a single scratch space per inferior.  */
 
-  if (!ptid_equal (displaced_step_ptid, null_ptid))
+  displaced = add_displaced_stepping_state (ptid_get_pid (ptid));
+
+  if (!ptid_equal (displaced->step_ptid, null_ptid))
     {
       /* Already waiting for a displaced step to finish.  Defer this
         request and place in queue.  */
@@ -1053,16 +1143,16 @@ displaced_step_prepare (ptid_t ptid)
       new_req->ptid = ptid;
       new_req->next = NULL;
 
-      if (displaced_step_request_queue)
+      if (displaced->step_request_queue)
        {
-         for (req = displaced_step_request_queue;
+         for (req = displaced->step_request_queue;
               req && req->next;
               req = req->next)
            ;
          req->next = new_req;
        }
       else
-       displaced_step_request_queue = new_req;
+       displaced->step_request_queue = new_req;
 
       return 0;
     }
@@ -1074,7 +1164,7 @@ displaced_step_prepare (ptid_t ptid)
                            target_pid_to_str (ptid));
     }
 
-  displaced_step_clear ();
+  displaced_step_clear (displaced);
 
   old_cleanups = save_inferior_ptid ();
   inferior_ptid = ptid;
@@ -1085,15 +1175,17 @@ displaced_step_prepare (ptid_t ptid)
   len = gdbarch_max_insn_length (gdbarch);
 
   /* Save the original contents of the copy area.  */
-  displaced_step_saved_copy = xmalloc (len);
+  displaced->step_saved_copy = xmalloc (len);
   ignore_cleanups = make_cleanup (free_current_contents,
-                                 &displaced_step_saved_copy);
-  read_memory (copy, displaced_step_saved_copy, len);
+                                 &displaced->step_saved_copy);
+  read_memory (copy, displaced->step_saved_copy, len);
   if (debug_displaced)
     {
       fprintf_unfiltered (gdb_stdlog, "displaced: saved %s: ",
                          paddress (gdbarch, copy));
-      displaced_step_dump_bytes (gdb_stdlog, displaced_step_saved_copy, len);
+      displaced_step_dump_bytes (gdb_stdlog,
+                                displaced->step_saved_copy,
+                                len);
     };
 
   closure = gdbarch_displaced_step_copy_insn (gdbarch,
@@ -1104,13 +1196,13 @@ displaced_step_prepare (ptid_t ptid)
 
   /* Save the information we need to fix things up if the step
      succeeds.  */
-  displaced_step_ptid = ptid;
-  displaced_step_gdbarch = gdbarch;
-  displaced_step_closure = closure;
-  displaced_step_original = original;
-  displaced_step_copy = copy;
+  displaced->step_ptid = ptid;
+  displaced->step_gdbarch = gdbarch;
+  displaced->step_closure = closure;
+  displaced->step_original = original;
+  displaced->step_copy = copy;
 
-  make_cleanup (displaced_step_clear_cleanup, 0);
+  make_cleanup (displaced_step_clear_cleanup, displaced);
 
   /* Resume execution at the copy.  */
   regcache_write_pc (regcache, copy);
@@ -1139,34 +1231,40 @@ static void
 displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
 {
   struct cleanup *old_cleanups;
+  struct displaced_step_inferior_state *displaced
+    = get_displaced_stepping_state (ptid_get_pid (event_ptid));
+
+  /* Was any thread of this process doing a displaced step?  */
+  if (displaced == NULL)
+    return;
 
   /* Was this event for the pid we displaced?  */
-  if (ptid_equal (displaced_step_ptid, null_ptid)
-      || ! ptid_equal (displaced_step_ptid, event_ptid))
+  if (ptid_equal (displaced->step_ptid, null_ptid)
+      || ! ptid_equal (displaced->step_ptid, event_ptid))
     return;
 
-  old_cleanups = make_cleanup (displaced_step_clear_cleanup, 0);
+  old_cleanups = make_cleanup (displaced_step_clear_cleanup, displaced);
 
   /* Restore the contents of the copy area.  */
   {
-    ULONGEST len = gdbarch_max_insn_length (displaced_step_gdbarch);
-    write_memory_ptid (displaced_step_ptid, displaced_step_copy,
-                      displaced_step_saved_copy, len);
+    ULONGEST len = gdbarch_max_insn_length (displaced->step_gdbarch);
+    write_memory_ptid (displaced->step_ptid, displaced->step_copy,
+                      displaced->step_saved_copy, len);
     if (debug_displaced)
       fprintf_unfiltered (gdb_stdlog, "displaced: restored %s\n",
-                          paddress (displaced_step_gdbarch,
-                                   displaced_step_copy));
+                          paddress (displaced->step_gdbarch,
+                                   displaced->step_copy));
   }
 
   /* Did the instruction complete successfully?  */
   if (signal == TARGET_SIGNAL_TRAP)
     {
       /* Fix up the resulting state.  */
-      gdbarch_displaced_step_fixup (displaced_step_gdbarch,
-                                    displaced_step_closure,
-                                    displaced_step_original,
-                                    displaced_step_copy,
-                                    get_thread_regcache (displaced_step_ptid));
+      gdbarch_displaced_step_fixup (displaced->step_gdbarch,
+                                    displaced->step_closure,
+                                    displaced->step_original,
+                                    displaced->step_copy,
+                                    get_thread_regcache (displaced->step_ptid));
     }
   else
     {
@@ -1174,17 +1272,18 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
          relocate the PC.  */
       struct regcache *regcache = get_thread_regcache (event_ptid);
       CORE_ADDR pc = regcache_read_pc (regcache);
-      pc = displaced_step_original + (pc - displaced_step_copy);
+      pc = displaced->step_original + (pc - displaced->step_copy);
       regcache_write_pc (regcache, pc);
     }
 
   do_cleanups (old_cleanups);
 
-  displaced_step_ptid = null_ptid;
+  displaced->step_ptid = null_ptid;
 
   /* Are there any pending displaced stepping requests?  If so, run
-     one now.  */
-  while (displaced_step_request_queue)
+     one now.  Leave the state object around, since we're likely to
+     need it again soon.  */
+  while (displaced->step_request_queue)
     {
       struct displaced_step_request *head;
       ptid_t ptid;
@@ -1193,9 +1292,9 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
       CORE_ADDR actual_pc;
       struct address_space *aspace;
 
-      head = displaced_step_request_queue;
+      head = displaced->step_request_queue;
       ptid = head->ptid;
-      displaced_step_request_queue = head->next;
+      displaced->step_request_queue = head->next;
       xfree (head);
 
       context_switch (ptid);
@@ -1226,8 +1325,8 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
              displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
            }
 
-         if (gdbarch_displaced_step_hw_singlestep
-               (gdbarch, displaced_step_closure))
+         if (gdbarch_displaced_step_hw_singlestep (gdbarch,
+                                                   displaced->step_closure))
            target_resume (ptid, 1, TARGET_SIGNAL_0);
          else
            target_resume (ptid, 0, TARGET_SIGNAL_0);
@@ -1266,6 +1365,7 @@ static void
 infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
 {
   struct displaced_step_request *it;
+  struct displaced_step_inferior_state *displaced;
 
   if (ptid_equal (inferior_ptid, old_ptid))
     inferior_ptid = new_ptid;
@@ -1273,15 +1373,20 @@ infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
   if (ptid_equal (singlestep_ptid, old_ptid))
     singlestep_ptid = new_ptid;
 
-  if (ptid_equal (displaced_step_ptid, old_ptid))
-    displaced_step_ptid = new_ptid;
-
   if (ptid_equal (deferred_step_ptid, old_ptid))
     deferred_step_ptid = new_ptid;
 
-  for (it = displaced_step_request_queue; it; it = it->next)
-    if (ptid_equal (it->ptid, old_ptid))
-      it->ptid = new_ptid;
+  for (displaced = displaced_step_inferior_states;
+       displaced;
+       displaced = displaced->next)
+    {
+      if (ptid_equal (displaced->step_ptid, old_ptid))
+       displaced->step_ptid = new_ptid;
+
+      for (it = displaced->step_request_queue; it; it = it->next)
+       if (ptid_equal (it->ptid, old_ptid))
+         it->ptid = new_ptid;
+    }
 }
 
 \f
@@ -1418,6 +1523,8 @@ a command like `return' or `jump' to continue execution."));
          || (step && gdbarch_software_single_step_p (gdbarch)))
       && sig == TARGET_SIGNAL_0)
     {
+      struct displaced_step_inferior_state *displaced;
+
       if (!displaced_step_prepare (inferior_ptid))
        {
          /* Got placed in displaced stepping queue.  Will be resumed
@@ -1431,8 +1538,9 @@ a command like `return' or `jump' to continue execution."));
          return;
        }
 
-      step = gdbarch_displaced_step_hw_singlestep
-              (gdbarch, displaced_step_closure);
+      displaced = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
+      step = gdbarch_displaced_step_hw_singlestep (gdbarch,
+                                                  displaced->step_closure);
     }
 
   /* Do we need to do it the hard way, w/temp breakpoints?  */
@@ -1642,7 +1750,10 @@ prepare_to_proceed (int step)
 
   /* Make sure we were stopped at a breakpoint.  */
   if (wait_status.kind != TARGET_WAITKIND_STOPPED
-      || wait_status.value.sig != TARGET_SIGNAL_TRAP)
+      || (wait_status.value.sig != TARGET_SIGNAL_TRAP
+         && wait_status.value.sig != TARGET_SIGNAL_ILL
+         && wait_status.value.sig != TARGET_SIGNAL_SEGV
+         && wait_status.value.sig != TARGET_SIGNAL_EMT))
     {
       return 0;
     }
@@ -1760,6 +1871,16 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
                        "infrun: proceed (addr=%s, signal=%d, step=%d)\n",
                        paddress (gdbarch, addr), siggnal, step);
 
+  /* 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
+     handling the event.  */
+  if (non_stop)
+    {
+      make_cleanup_restore_current_traceframe ();
+      set_traceframe_number (-1);
+    }
+
   if (non_stop)
     /* In non-stop, each thread is handled individually.  The context
        must already be set to the right thread here.  */
@@ -1856,13 +1977,14 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
      or a return command, we often end up a few instructions forward, still 
      within the original line we started.
 
-     An attempt was made to have init_execution_control_state () refresh
-     the prev_pc value before calculating the line number.  This approach
-     did not work because on platforms that use ptrace, the pc register
-     cannot be read unless the inferior is stopped.  At that point, we
-     are not guaranteed the inferior is stopped and so the regcache_read_pc ()
-     call can fail.  Setting the prev_pc value here ensures the value is 
-     updated correctly when the inferior is stopped.  */
+     An attempt was made to refresh the prev_pc at the same time the
+     execution_control_state is initialized (for instance, just before
+     waiting for an inferior event).  But this approach did not work
+     because of platforms that use ptrace, where the pc register cannot
+     be read unless the inferior is stopped.  At that point, we are not
+     guaranteed the inferior is stopped and so the regcache_read_pc() call
+     can fail.  Setting the prev_pc value here ensures the value is updated
+     correctly when the inferior is stopped.  */
   tp->prev_pc = regcache_read_pc (get_current_regcache ());
 
   /* Fill in with reasonable starting values.  */
@@ -1940,8 +2062,6 @@ init_wait_for_inferior (void)
   previous_inferior_ptid = null_ptid;
   init_infwait_state ();
 
-  displaced_step_clear ();
-
   /* Discard any skipped inlined frames.  */
   clear_inline_frame_state (minus_one_ptid);
 }
@@ -1999,8 +2119,6 @@ struct execution_control_state
   int wait_some_more;
 };
 
-static void init_execution_control_state (struct execution_control_state *ecs);
-
 static void handle_inferior_event (struct execution_control_state *ecs);
 
 static void handle_step_into_function (struct gdbarch *gdbarch,
@@ -2087,28 +2205,34 @@ infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
 static void
 infrun_thread_stop_requested (ptid_t ptid)
 {
-  struct displaced_step_request *it, *next, *prev = NULL;
+  struct displaced_step_inferior_state *displaced;
 
   /* PTID was requested to stop.  Remove it from the displaced
      stepping queue, so we don't try to resume it automatically.  */
-  for (it = displaced_step_request_queue; it; it = next)
+
+  for (displaced = displaced_step_inferior_states;
+       displaced;
+       displaced = displaced->next)
     {
-      next = it->next;
+      struct displaced_step_request *it, **prev_next_p;
 
-      if (ptid_equal (it->ptid, ptid)
-         || ptid_equal (minus_one_ptid, ptid)
-         || (ptid_is_pid (ptid)
-             && ptid_get_pid (ptid) == ptid_get_pid (it->ptid)))
+      it = displaced->step_request_queue;
+      prev_next_p = &displaced->step_request_queue;
+      while (it)
        {
-         if (displaced_step_request_queue == it)
-           displaced_step_request_queue = it->next;
+         if (ptid_match (it->ptid, ptid))
+           {
+             *prev_next_p = it->next;
+             it->next = NULL;
+             xfree (it);
+           }
          else
-           prev->next = it->next;
+           {
+             prev_next_p = &it->next;
+           }
 
-         xfree (it);
+         it = *prev_next_p;
        }
-      else
-       prev = it;
     }
 
   iterate_over_threads (infrun_thread_stop_requested_callback, &ptid);
@@ -2207,6 +2331,84 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
   ui_file_delete (tmp_stream);
 }
 
+/* Prepare and stabilize the inferior for detaching it.  E.g.,
+   detaching while a thread is displaced stepping is a recipe for
+   crashing it, as nothing would readjust the PC out of the scratch
+   pad.  */
+
+void
+prepare_for_detach (void)
+{
+  struct inferior *inf = current_inferior ();
+  ptid_t pid_ptid = pid_to_ptid (inf->pid);
+  struct cleanup *old_chain_1;
+  struct displaced_step_inferior_state *displaced;
+
+  displaced = get_displaced_stepping_state (inf->pid);
+
+  /* Is any thread of this process displaced stepping?  If not,
+     there's nothing else to do.  */
+  if (displaced == NULL || ptid_equal (displaced->step_ptid, null_ptid))
+    return;
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+                       "displaced-stepping in-process while detaching");
+
+  old_chain_1 = make_cleanup_restore_integer (&inf->detaching);
+  inf->detaching = 1;
+
+  while (!ptid_equal (displaced->step_ptid, null_ptid))
+    {
+      struct cleanup *old_chain_2;
+      struct execution_control_state ecss;
+      struct execution_control_state *ecs;
+
+      ecs = &ecss;
+      memset (ecs, 0, sizeof (*ecs));
+
+      overlay_cache_invalid = 1;
+
+      /* We have to invalidate the registers BEFORE calling
+        target_wait because they can be loaded from the target while
+        in target_wait.  This makes remote debugging a bit more
+        efficient for those targets that provide critical registers
+        as part of their normal status mechanism. */
+
+      registers_changed ();
+
+      if (deprecated_target_wait_hook)
+       ecs->ptid = deprecated_target_wait_hook (pid_ptid, &ecs->ws, 0);
+      else
+       ecs->ptid = target_wait (pid_ptid, &ecs->ws, 0);
+
+      if (debug_infrun)
+       print_target_wait_results (pid_ptid, ecs->ptid, &ecs->ws);
+
+      /* If an error happens while handling the event, propagate GDB's
+        knowledge of the executing state to the frontend/user running
+        state.  */
+      old_chain_2 = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+
+      /* Now figure out what to do with the result of the result.  */
+      handle_inferior_event (ecs);
+
+      /* No error, don't finish the state yet.  */
+      discard_cleanups (old_chain_2);
+
+      /* Breakpoints and watchpoints are not installed on the target
+        at this point, and signals are passed directly to the
+        inferior, so this must mean the process is gone.  */
+      if (!ecs->wait_some_more)
+       {
+         discard_cleanups (old_chain_1);
+         error (_("Program exited while detaching"));
+       }
+    }
+
+  discard_cleanups (old_chain_1);
+}
+
 /* Wait for control to return from inferior to debugger.
 
    If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals
@@ -2403,15 +2605,6 @@ set_step_info (struct frame_info *frame, struct symtab_and_line sal)
   tp->current_line = sal.line;
 }
 
-/* Prepare an execution control state for looping through a
-   wait_for_inferior-type loop.  */
-
-static void
-init_execution_control_state (struct execution_control_state *ecs)
-{
-  ecs->random_signal = 0;
-}
-
 /* Clear context switchable stepping state.  */
 
 void
@@ -2733,6 +2926,33 @@ handle_inferior_event (struct execution_control_state *ecs)
 
   breakpoint_retire_moribund ();
 
+  /* First, distinguish signals caused by the debugger from signals
+     that have to do with the program's own actions.  Note that
+     breakpoint insns may cause SIGTRAP or SIGILL or SIGEMT, depending
+     on the operating system version.  Here we detect when a SIGILL or
+     SIGEMT is really a breakpoint and change it to SIGTRAP.  We do
+     something similar for SIGSEGV, since a SIGSEGV will be generated
+     when we're trying to execute a breakpoint instruction on a
+     non-executable stack.  This happens for call dummy breakpoints
+     for architectures like SPARC that place call dummies on the
+     stack.  */
+  if (ecs->ws.kind == TARGET_WAITKIND_STOPPED
+      && (ecs->ws.value.sig == TARGET_SIGNAL_ILL
+         || ecs->ws.value.sig == TARGET_SIGNAL_SEGV
+         || ecs->ws.value.sig == TARGET_SIGNAL_EMT))
+    {
+      struct regcache *regcache = get_thread_regcache (ecs->ptid);
+
+      if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
+                                     regcache_read_pc (regcache)))
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: Treating signal as SIGTRAP\n");
+         ecs->ws.value.sig = TARGET_SIGNAL_TRAP;
+       }
+    }
+
   /* Mark the non-executing threads accordingly.  In all-stop, all
      threads of all processes are stopped when we get any event
      reported.  In non-stop mode, only the event thread stops.  If
@@ -3232,7 +3452,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
   if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
     {
       int thread_hop_needed = 0;
-      struct address_space *aspace = get_regcache_aspace (get_current_regcache ());
+      struct address_space *aspace = 
+       get_regcache_aspace (get_thread_regcache (ecs->ptid));
 
       /* Check if a regular breakpoint has been hit before checking
          for a potential single step breakpoint. Otherwise, GDB will
@@ -3511,27 +3732,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
      3) set ecs->random_signal to 1, and the decision between 1 and 2
      will be made according to the signal handling tables.  */
 
-  /* First, distinguish signals caused by the debugger from signals
-     that have to do with the program's own actions.  Note that
-     breakpoint insns may cause SIGTRAP or SIGILL or SIGEMT, depending
-     on the operating system version.  Here we detect when a SIGILL or
-     SIGEMT is really a breakpoint and change it to SIGTRAP.  We do
-     something similar for SIGSEGV, since a SIGSEGV will be generated
-     when we're trying to execute a breakpoint instruction on a
-     non-executable stack.  This happens for call dummy breakpoints
-     for architectures like SPARC that place call dummies on the
-     stack.
-
-     If we're doing a displaced step past a breakpoint, then the
-     breakpoint is always inserted at the original instruction;
-     non-standard signals can't be explained by the breakpoint.  */
   if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
-      || (! ecs->event_thread->trap_expected
-          && breakpoint_inserted_here_p (get_regcache_aspace (get_current_regcache ()),
-                                        stop_pc)
-         && (ecs->event_thread->stop_signal == TARGET_SIGNAL_ILL
-             || ecs->event_thread->stop_signal == TARGET_SIGNAL_SEGV
-             || ecs->event_thread->stop_signal == TARGET_SIGNAL_EMT))
       || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
       || stop_soon == STOP_QUIETLY_REMOTE)
     {
@@ -3664,6 +3865,7 @@ process_event_stop_test:
     {
       /* Signal not for debugging purposes.  */
       int printed = 0;
+      struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid));
 
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n",
@@ -3682,7 +3884,8 @@ process_event_stop_test:
         to remain stopped.  */
       if (stop_soon != NO_STOP_QUIETLY
          || ecs->event_thread->stop_requested
-         || signal_stop_state (ecs->event_thread->stop_signal))
+         || (!inf->detaching
+             && signal_stop_state (ecs->event_thread->stop_signal)))
        {
          stop_stepping (ecs);
          return;
@@ -4065,6 +4268,11 @@ infrun: not switching back to stepped thread, it has vanished\n");
       return;
     }
 
+  /* Re-fetch current thread's frame in case the code above caused
+     the frame cache to be re-initialized, making our FRAME variable
+     a dangling pointer.  */
+  frame = get_current_frame ();
+
   /* If stepping through a line, keep going if still within it.
 
      Note that step_range_end is the address of the first instruction
@@ -6111,6 +6319,26 @@ ptid_is_pid (ptid_t ptid)
   return (ptid_get_lwp (ptid) == 0 && ptid_get_tid (ptid) == 0);
 }
 
+int
+ptid_match (ptid_t ptid, ptid_t filter)
+{
+  /* Since both parameters have the same type, prevent easy mistakes
+     from happening.  */
+  gdb_assert (!ptid_equal (ptid, minus_one_ptid)
+             && !ptid_equal (ptid, null_ptid)
+             && !ptid_is_pid (ptid));
+
+  if (ptid_equal (filter, minus_one_ptid))
+    return 1;
+  if (ptid_is_pid (filter)
+      && ptid_get_pid (ptid) == ptid_get_pid (filter))
+    return 1;
+  else if (ptid_equal (ptid, filter))
+    return 1;
+
+  return 0;
+}
+
 /* restore_inferior_ptid() will be used by the cleanup machinery
    to restore the inferior_ptid value saved in a call to
    save_inferior_ptid().  */
@@ -6480,11 +6708,11 @@ Tells gdb whether to detach the child of a fork."),
   minus_one_ptid = ptid_build (-1, 0, 0);
   inferior_ptid = null_ptid;
   target_last_wait_ptid = minus_one_ptid;
-  displaced_step_ptid = null_ptid;
 
   observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
   observer_attach_thread_stop_requested (infrun_thread_stop_requested);
   observer_attach_thread_exit (infrun_thread_thread_exit);
+  observer_attach_inferior_exit (infrun_inferior_exit);
 
   /* Explicitly create without lookup, since that tries to create a
      value with a void typed value, and when we get here, gdbarch
This page took 0.03554 seconds and 4 git commands to generate.