Add set/show debug dwarf-line.
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index cb10e2c6556a90bbb8efa1d6c43e776b440fa054..f95e76c601084ecd67abbed02890ff14aea4a6df 100644 (file)
@@ -281,6 +281,50 @@ static int check_stopped_by_breakpoint (struct lwp_info *lp);
 static int sigtrap_is_event (int status);
 static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event;
 
+\f
+/* LWP accessors.  */
+
+/* See nat/linux-nat.h.  */
+
+ptid_t
+ptid_of_lwp (struct lwp_info *lwp)
+{
+  return lwp->ptid;
+}
+
+/* See nat/linux-nat.h.  */
+
+void
+lwp_set_arch_private_info (struct lwp_info *lwp,
+                          struct arch_lwp_info *info)
+{
+  lwp->arch_private = info;
+}
+
+/* See nat/linux-nat.h.  */
+
+struct arch_lwp_info *
+lwp_arch_private_info (struct lwp_info *lwp)
+{
+  return lwp->arch_private;
+}
+
+/* See nat/linux-nat.h.  */
+
+int
+lwp_is_stopped (struct lwp_info *lwp)
+{
+  return lwp->stopped;
+}
+
+/* See nat/linux-nat.h.  */
+
+enum target_stop_reason
+lwp_stop_reason (struct lwp_info *lwp)
+{
+  return lwp->stop_reason;
+}
+
 \f
 /* Trivial list manipulation functions to keep track of a list of
    new stopped processes.  */
@@ -324,6 +368,25 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
   return 0;
 }
 
+/* Return the ptrace options that we want to try to enable.  */
+
+static int
+linux_nat_ptrace_options (int attached)
+{
+  int options = 0;
+
+  if (!attached)
+    options |= PTRACE_O_EXITKILL;
+
+  options |= (PTRACE_O_TRACESYSGOOD
+             | PTRACE_O_TRACEVFORKDONE
+             | PTRACE_O_TRACEVFORK
+             | PTRACE_O_TRACEFORK
+             | PTRACE_O_TRACEEXEC);
+
+  return options;
+}
+
 /* Initialize ptrace warnings and check for supported ptrace
    features given PID.
 
@@ -332,7 +395,9 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
 static void
 linux_init_ptrace (pid_t pid, int attached)
 {
-  linux_enable_event_reporting (pid, attached);
+  int options = linux_nat_ptrace_options (attached);
+
+  linux_enable_event_reporting (pid, options);
   linux_ptrace_init_warnings ();
 }
 
@@ -387,20 +452,19 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child,
       int status = W_STOPCODE (0);
       struct cleanup *old_chain;
       int has_vforked;
+      ptid_t parent_ptid, child_ptid;
       int parent_pid, child_pid;
 
       has_vforked = (inferior_thread ()->pending_follow.kind
                     == TARGET_WAITKIND_VFORKED);
-      parent_pid = ptid_get_lwp (inferior_ptid);
-      if (parent_pid == 0)
-       parent_pid = ptid_get_pid (inferior_ptid);
-      child_pid
-       = ptid_get_pid (inferior_thread ()->pending_follow.value.related_pid);
-
+      parent_ptid = inferior_ptid;
+      child_ptid = inferior_thread ()->pending_follow.value.related_pid;
+      parent_pid = ptid_get_lwp (parent_ptid);
+      child_pid = ptid_get_lwp (child_ptid);
 
       /* We're already attached to the parent, by default.  */
       old_chain = save_inferior_ptid ();
-      inferior_ptid = ptid_build (child_pid, child_pid, 0);
+      inferior_ptid = child_ptid;
       child_lp = add_lwp (inferior_ptid);
       child_lp->stopped = 1;
       child_lp->last_resume_kind = resume_stop;
@@ -457,7 +521,7 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child,
        {
          struct lwp_info *parent_lp;
 
-         parent_lp = find_lwp_pid (pid_to_ptid (parent_pid));
+         parent_lp = find_lwp_pid (parent_ptid);
          gdb_assert (linux_supports_tracefork () >= 0);
 
          if (linux_supports_tracevforkdone ())
@@ -835,14 +899,11 @@ find_lwp_pid (ptid_t ptid)
   return NULL;
 }
 
-/* Call CALLBACK with its second argument set to DATA for every LWP in
-   the list.  If CALLBACK returns 1 for a particular LWP, return a
-   pointer to the structure describing that LWP immediately.
-   Otherwise return NULL.  */
+/* See nat/linux-nat.h.  */
 
 struct lwp_info *
 iterate_over_lwps (ptid_t filter,
-                  int (*callback) (struct lwp_info *, void *),
+                  iterate_over_lwps_ftype callback,
                   void *data)
 {
   struct lwp_info *lp, *lpnext;
@@ -853,7 +914,7 @@ iterate_over_lwps (ptid_t filter,
 
       if (ptid_match (lp->ptid, filter))
        {
-         if ((*callback) (lp, data))
+         if ((*callback) (lp, data) != 0)
            return lp;
        }
     }
@@ -1203,16 +1264,15 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
   struct lwp_info *lp;
   int status;
   ptid_t ptid;
-  volatile struct gdb_exception ex;
 
   /* Make sure we report all signals during attach.  */
   linux_nat_pass_signals (ops, 0, NULL);
 
-  TRY_CATCH (ex, RETURN_MASK_ERROR)
+  TRY
     {
       linux_ops->to_attach (ops, args, from_tty);
     }
-  if (ex.reason < 0)
+  CATCH (ex, RETURN_MASK_ERROR)
     {
       pid_t pid = parse_pid_to_attach (args);
       struct buffer buffer;
@@ -1233,6 +1293,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
       else
        throw_error (ex.error, "%s", message);
     }
+  END_CATCH
 
   /* The ptrace base target adds the main thread with (pid,0,0)
      format.  Decorate it with lwp info.  */
@@ -1301,7 +1362,7 @@ linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
                                  attach_proc_task_lwp_callback);
 
   if (target_can_async_p ())
-    target_async (inferior_event_handler, 0);
+    target_async (1);
 }
 
 /* Get pending status of LP.  */
@@ -1504,7 +1565,8 @@ linux_nat_detach (struct target_ops *ops, const char *args, int from_tty)
    single-step it.  If SIGNAL is nonzero, give it that signal.  */
 
 static void
-linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
+linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
+                           enum gdb_signal signo)
 {
   lp->step = step;
 
@@ -1523,11 +1585,68 @@ linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
   if (linux_nat_prepare_to_resume != NULL)
     linux_nat_prepare_to_resume (lp);
   linux_ops->to_resume (linux_ops, lp->ptid, step, signo);
-  lp->stop_reason = LWP_STOPPED_BY_NO_REASON;
+
+  /* Successfully resumed.  Clear state that no longer makes sense,
+     and mark the LWP as running.  Must not do this before resuming
+     otherwise if that fails other code will be confused.  E.g., we'd
+     later try to stop the LWP and hang forever waiting for a stop
+     status.  Note that we must not throw after this is cleared,
+     otherwise handle_zombie_lwp_error would get confused.  */
   lp->stopped = 0;
+  lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
   registers_changed_ptid (lp->ptid);
 }
 
+/* Called when we try to resume a stopped LWP and that errors out.  If
+   the LWP is no longer in ptrace-stopped state (meaning it's zombie,
+   or about to become), discard the error, clear any pending status
+   the LWP may have, and return true (we'll collect the exit status
+   soon enough).  Otherwise, return false.  */
+
+static int
+check_ptrace_stopped_lwp_gone (struct lwp_info *lp)
+{
+  /* If we get an error after resuming the LWP successfully, we'd
+     confuse !T state for the LWP being gone.  */
+  gdb_assert (lp->stopped);
+
+  /* We can't just check whether the LWP is in 'Z (Zombie)' state,
+     because even if ptrace failed with ESRCH, the tracee may be "not
+     yet fully dead", but already refusing ptrace requests.  In that
+     case the tracee has 'R (Running)' state for a little bit
+     (observed in Linux 3.18).  See also the note on ESRCH in the
+     ptrace(2) man page.  Instead, check whether the LWP has any state
+     other than ptrace-stopped.  */
+
+  /* Don't assume anything if /proc/PID/status can't be read.  */
+  if (linux_proc_pid_is_trace_stopped_nowarn (ptid_get_lwp (lp->ptid)) == 0)
+    {
+      lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+      lp->status = 0;
+      lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
+      return 1;
+    }
+  return 0;
+}
+
+/* Like linux_resume_one_lwp_throw, but no error is thrown if the LWP
+   disappears while we try to resume it.  */
+
+static void
+linux_resume_one_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
+{
+  TRY
+    {
+      linux_resume_one_lwp_throw (lp, step, signo);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (!check_ptrace_stopped_lwp_gone (lp))
+       throw_exception (ex);
+    }
+  END_CATCH
+}
+
 /* Resume LP.  */
 
 static void
@@ -1691,7 +1810,7 @@ linux_nat_resume (struct target_ops *ops,
 
       if (target_can_async_p ())
        {
-         target_async (inferior_event_handler, 0);
+         target_async (1);
          /* Tell the event loop we have something to process.  */
          async_file_mark ();
        }
@@ -1701,18 +1820,18 @@ linux_nat_resume (struct target_ops *ops,
   if (resume_many)
     iterate_over_lwps (ptid, linux_nat_resume_callback, lp);
 
-  linux_resume_one_lwp (lp, step, signo);
-
   if (debug_linux_nat)
     fprintf_unfiltered (gdb_stdlog,
                        "LLR: %s %s, %s (resume event thread)\n",
                        step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
-                       target_pid_to_str (ptid),
+                       target_pid_to_str (lp->ptid),
                        (signo != GDB_SIGNAL_0
                         ? strsignal (gdb_signal_to_host (signo)) : "0"));
 
+  linux_resume_one_lwp (lp, step, signo);
+
   if (target_can_async_p ())
-    target_async (inferior_event_handler, 0);
+    target_async (1);
 }
 
 /* Send a signal to an LWP.  */
@@ -2011,9 +2130,12 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
              add_thread (new_lp->ptid);
            }
 
+         /* Even if we're stopping the thread for some reason
+            internal to this module, from the user/frontend's
+            perspective, this new thread is running.  */
+         set_running (new_lp->ptid, 1);
          if (!stopping)
            {
-             set_running (new_lp->ptid, 1);
              set_executing (new_lp->ptid, 1);
              /* thread_db_attach_lwp -> lin_lwp_attach_lwp forced
                 resume_stop.  */
@@ -2200,8 +2322,9 @@ wait_lwp (struct lwp_info *lp)
   if (lp->must_set_ptrace_flags)
     {
       struct inferior *inf = find_inferior_pid (ptid_get_pid (lp->ptid));
+      int options = linux_nat_ptrace_options (inf->attach_flag);
 
-      linux_enable_event_reporting (ptid_get_lwp (lp->ptid), inf->attach_flag);
+      linux_enable_event_reporting (ptid_get_lwp (lp->ptid), options);
       lp->must_set_ptrace_flags = 0;
     }
 
@@ -2376,7 +2499,7 @@ check_stopped_by_watchpoint (struct lwp_info *lp)
 
   if (linux_ops->to_stopped_by_watchpoint (linux_ops))
     {
-      lp->stop_reason = LWP_STOPPED_BY_WATCHPOINT;
+      lp->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
 
       if (linux_ops->to_stopped_data_address != NULL)
        lp->stopped_data_address_p =
@@ -2388,7 +2511,7 @@ check_stopped_by_watchpoint (struct lwp_info *lp)
 
   do_cleanups (old_chain);
 
-  return lp->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
+  return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
 }
 
 /* Called when the LWP stopped for a trap that could be explained by a
@@ -2397,14 +2520,22 @@ check_stopped_by_watchpoint (struct lwp_info *lp)
 static void
 save_sigtrap (struct lwp_info *lp)
 {
-  gdb_assert (lp->stop_reason == LWP_STOPPED_BY_NO_REASON);
+  gdb_assert (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON);
   gdb_assert (lp->status != 0);
 
-  if (check_stopped_by_watchpoint (lp))
-    return;
-
+  /* Check first if this was a SW/HW breakpoint before checking
+     watchpoints, because at least s390 can't tell the data address of
+     hardware watchpoint hits, and the kernel returns
+     stopped-by-watchpoint as long as there's a watchpoint set.  */
   if (linux_nat_status_is_event (lp->status))
     check_stopped_by_breakpoint (lp);
+
+  /* Note that TRAP_HWBKPT can indicate either a hardware breakpoint
+     or hardware watchpoint.  Check which is which if we got
+     TARGET_STOPPED_BY_HW_BREAKPOINT.  */
+  if (lp->stop_reason == TARGET_STOPPED_BY_NO_REASON
+      || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT)
+    check_stopped_by_watchpoint (lp);
 }
 
 /* Returns true if the LWP had stopped for a watchpoint.  */
@@ -2416,7 +2547,7 @@ linux_nat_stopped_by_watchpoint (struct target_ops *ops)
 
   gdb_assert (lp != NULL);
 
-  return lp->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
+  return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
 }
 
 static int
@@ -2512,7 +2643,7 @@ stop_wait_callback (struct lwp_info *lp, void *data)
 
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
-                               "SWC: Delayed SIGSTOP caught for %s.\n",
+                               "SWC: Expected SIGSTOP caught for %s.\n",
                                target_pid_to_str (lp->ptid));
 
          /* Reset SIGNALLED only after the stop_wait_callback call
@@ -2536,16 +2667,17 @@ status_callback (struct lwp_info *lp, void *data)
   if (!lp->resumed)
     return 0;
 
-  if (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT
-      || lp->stop_reason == LWP_STOPPED_BY_HW_BREAKPOINT)
+  if (!lwp_status_pending_p (lp))
+    return 0;
+
+  if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+      || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT)
     {
       struct regcache *regcache = get_thread_regcache (lp->ptid);
       struct gdbarch *gdbarch = get_regcache_arch (regcache);
       CORE_ADDR pc;
       int discard = 0;
 
-      gdb_assert (lp->status != 0);
-
       pc = regcache_read_pc (regcache);
 
       if (pc != lp->stop_pc)
@@ -2558,6 +2690,8 @@ status_callback (struct lwp_info *lp, void *data)
                                paddress (target_gdbarch (), pc));
          discard = 1;
        }
+
+#if !USE_SIGTRAP_SIGINFO
       else if (!breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
        {
          if (debug_linux_nat)
@@ -2568,6 +2702,7 @@ status_callback (struct lwp_info *lp, void *data)
 
          discard = 1;
        }
+#endif
 
       if (discard)
        {
@@ -2580,10 +2715,9 @@ status_callback (struct lwp_info *lp, void *data)
          linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
          return 0;
        }
-      return 1;
     }
 
-  return lwp_status_pending_p (lp);
+  return 1;
 }
 
 /* Return non-zero if LP isn't stopped.  */
@@ -2634,7 +2768,7 @@ lwp_status_pending_p (struct lwp_info *lp)
   return lp->status != 0 || lp->waitstatus.kind != TARGET_WAITKIND_IGNORE;
 }
 
-/* Select the Nth LWP that has had a SIGTRAP event.  */
+/* Select the Nth LWP that has had an event.  */
 
 static int
 select_event_lwp_callback (struct lwp_info *lp, void *data)
@@ -2670,10 +2804,56 @@ check_stopped_by_breakpoint (struct lwp_info *lp)
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   CORE_ADDR pc;
   CORE_ADDR sw_bp_pc;
+#if USE_SIGTRAP_SIGINFO
+  siginfo_t siginfo;
+#endif
 
   pc = regcache_read_pc (regcache);
-  sw_bp_pc = pc - target_decr_pc_after_break (gdbarch);
+  sw_bp_pc = pc - gdbarch_decr_pc_after_break (gdbarch);
 
+#if USE_SIGTRAP_SIGINFO
+  if (linux_nat_get_siginfo (lp->ptid, &siginfo))
+    {
+      if (siginfo.si_signo == SIGTRAP)
+       {
+         if (siginfo.si_code == GDB_ARCH_TRAP_BRKPT)
+           {
+             if (debug_linux_nat)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "CSBB: %s stopped by software "
+                                   "breakpoint\n",
+                                   target_pid_to_str (lp->ptid));
+
+             /* Back up the PC if necessary.  */
+             if (pc != sw_bp_pc)
+               regcache_write_pc (regcache, sw_bp_pc);
+
+             lp->stop_pc = sw_bp_pc;
+             lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
+             return 1;
+           }
+         else if (siginfo.si_code == TRAP_HWBKPT)
+           {
+             if (debug_linux_nat)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "CSBB: %s stopped by hardware "
+                                   "breakpoint/watchpoint\n",
+                                   target_pid_to_str (lp->ptid));
+
+             lp->stop_pc = pc;
+             lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
+             return 1;
+           }
+         else if (siginfo.si_code == TRAP_TRACE)
+           {
+             if (debug_linux_nat)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "CSBB: %s stopped by trace\n",
+                                   target_pid_to_str (lp->ptid));
+           }
+       }
+    }
+#else
   if ((!lp->step || lp->stop_pc == sw_bp_pc)
       && software_breakpoint_inserted_here_p (get_regcache_aspace (regcache),
                                              sw_bp_pc))
@@ -2682,7 +2862,7 @@ check_stopped_by_breakpoint (struct lwp_info *lp)
         breakpoint instruction.  */
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
-                           "CB: Push back software breakpoint for %s\n",
+                           "CSBB: %s stopped by software breakpoint\n",
                            target_pid_to_str (lp->ptid));
 
       /* Back up the PC if necessary.  */
@@ -2690,7 +2870,7 @@ check_stopped_by_breakpoint (struct lwp_info *lp)
        regcache_write_pc (regcache, sw_bp_pc);
 
       lp->stop_pc = sw_bp_pc;
-      lp->stop_reason = LWP_STOPPED_BY_SW_BREAKPOINT;
+      lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
       return 1;
     }
 
@@ -2698,17 +2878,60 @@ check_stopped_by_breakpoint (struct lwp_info *lp)
     {
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
-                           "CB: Push back hardware breakpoint for %s\n",
+                           "CSBB: stopped by hardware breakpoint %s\n",
                            target_pid_to_str (lp->ptid));
 
       lp->stop_pc = pc;
-      lp->stop_reason = LWP_STOPPED_BY_HW_BREAKPOINT;
+      lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
       return 1;
     }
+#endif
 
   return 0;
 }
 
+
+/* Returns true if the LWP had stopped for a software breakpoint.  */
+
+static int
+linux_nat_stopped_by_sw_breakpoint (struct target_ops *ops)
+{
+  struct lwp_info *lp = find_lwp_pid (inferior_ptid);
+
+  gdb_assert (lp != NULL);
+
+  return lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
+}
+
+/* Implement the supports_stopped_by_sw_breakpoint method.  */
+
+static int
+linux_nat_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
+{
+  return USE_SIGTRAP_SIGINFO;
+}
+
+/* Returns true if the LWP had stopped for a hardware
+   breakpoint/watchpoint.  */
+
+static int
+linux_nat_stopped_by_hw_breakpoint (struct target_ops *ops)
+{
+  struct lwp_info *lp = find_lwp_pid (inferior_ptid);
+
+  gdb_assert (lp != NULL);
+
+  return lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
+}
+
+/* Implement the supports_stopped_by_hw_breakpoint method.  */
+
+static int
+linux_nat_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
+{
+  return USE_SIGTRAP_SIGINFO;
+}
+
 /* Select one LWP out of those that have events pending.  */
 
 static void
@@ -2749,6 +2972,7 @@ select_event_lwp (ptid_t filter, struct lwp_info **orig_lp, int *status)
 
       /* First see how many events we have.  */
       iterate_over_lwps (filter, count_events_callback, &num_events);
+      gdb_assert (num_events > 0);
 
       /* Now randomly pick a LWP out of those that have had
         events.  */
@@ -2900,8 +3124,9 @@ linux_nat_filter_event (int lwpid, int status)
   if (WIFSTOPPED (status) && lp->must_set_ptrace_flags)
     {
       struct inferior *inf = find_inferior_pid (ptid_get_pid (lp->ptid));
+      int options = linux_nat_ptrace_options (inf->attach_flag);
 
-      linux_enable_event_reporting (ptid_get_lwp (lp->ptid), inf->attach_flag);
+      linux_enable_event_reporting (ptid_get_lwp (lp->ptid), options);
       lp->must_set_ptrace_flags = 0;
     }
 
@@ -3014,28 +3239,28 @@ linux_nat_filter_event (int lwpid, int status)
   if (lp->signalled
       && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP)
     {
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "LLW: Delayed SIGSTOP caught for %s.\n",
-                           target_pid_to_str (lp->ptid));
-
       lp->signalled = 0;
 
-      if (lp->last_resume_kind != resume_stop)
+      if (lp->last_resume_kind == resume_stop)
        {
-         /* This is a delayed SIGSTOP.  */
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "LLW: resume_stop SIGSTOP caught for %s.\n",
+                               target_pid_to_str (lp->ptid));
+       }
+      else
+       {
+         /* This is a delayed SIGSTOP.  Filter out the event.  */
 
-         linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
-                               "LLW: %s %s, 0, 0 (discard SIGSTOP)\n",
+                               "LLW: %s %s, 0, 0 (discard delayed SIGSTOP)\n",
                                lp->step ?
                                "PTRACE_SINGLESTEP" : "PTRACE_CONT",
                                target_pid_to_str (lp->ptid));
 
+         linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
          gdb_assert (lp->resumed);
-
-         /* Discard the event.  */
          return NULL;
        }
     }
@@ -3361,12 +3586,14 @@ linux_nat_wait_1 (struct target_ops *ops,
   gdb_assert (lp != NULL);
 
   /* Now that we've selected our final event LWP, un-adjust its PC if
-     it was a software breakpoint.  */
-  if (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT)
+     it was a software breakpoint, and we can't reliably support the
+     "stopped by software breakpoint" stop reason.  */
+  if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+      && !USE_SIGTRAP_SIGINFO)
     {
       struct regcache *regcache = get_thread_regcache (lp->ptid);
       struct gdbarch *gdbarch = get_regcache_arch (regcache);
-      int decr_pc = target_decr_pc_after_break (gdbarch);
+      int decr_pc = gdbarch_decr_pc_after_break (gdbarch);
 
       if (decr_pc != 0)
        {
@@ -3447,24 +3674,39 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data)
     {
       struct regcache *regcache = get_thread_regcache (lp->ptid);
       struct gdbarch *gdbarch = get_regcache_arch (regcache);
-      CORE_ADDR pc = regcache_read_pc (regcache);
 
-      /* Don't bother if there's a breakpoint at PC that we'd hit
-        immediately, and we're not waiting for this LWP.  */
-      if (!ptid_match (lp->ptid, *wait_ptid_p))
+      TRY
        {
-         if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
-           return 0;
-       }
+         CORE_ADDR pc = regcache_read_pc (regcache);
+         int leave_stopped = 0;
 
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "RSRL: resuming stopped-resumed LWP %s at %s: step=%d\n",
-                           target_pid_to_str (lp->ptid),
-                           paddress (gdbarch, pc),
-                           lp->step);
+         /* Don't bother if there's a breakpoint at PC that we'd hit
+            immediately, and we're not waiting for this LWP.  */
+         if (!ptid_match (lp->ptid, *wait_ptid_p))
+           {
+             if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+               leave_stopped = 1;
+           }
 
-      linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
+         if (!leave_stopped)
+           {
+             if (debug_linux_nat)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "RSRL: resuming stopped-resumed LWP %s at "
+                                   "%s: step=%d\n",
+                                   target_pid_to_str (lp->ptid),
+                                   paddress (gdbarch, pc),
+                                   lp->step);
+
+             linux_resume_one_lwp_throw (lp, lp->step, GDB_SIGNAL_0);
+           }
+       }
+      CATCH (ex, RETURN_MASK_ERROR)
+       {
+         if (!check_ptrace_stopped_lwp_gone (lp))
+           throw_exception (ex);
+       }
+      END_CATCH
     }
 
   return 0;
@@ -3811,6 +4053,23 @@ linux_nat_thread_alive (struct target_ops *ops, ptid_t ptid)
   return linux_thread_alive (ptid);
 }
 
+/* Implement the to_update_thread_list target method for this
+   target.  */
+
+static void
+linux_nat_update_thread_list (struct target_ops *ops)
+{
+  if (linux_supports_traceclone ())
+    {
+      /* With support for clone events, we add/delete threads from the
+        list as clone/exit events are processed, so just try deleting
+        exited threads still in the thread list.  */
+      delete_exited_threads ();
+    }
+  else
+    prune_threads ();
+}
+
 static char *
 linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
@@ -3870,15 +4129,7 @@ linux_nat_thread_name (struct target_ops *self, struct thread_info *thr)
 static char *
 linux_child_pid_to_exec_file (struct target_ops *self, int pid)
 {
-  static char buf[PATH_MAX];
-  char name[PATH_MAX];
-
-  xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
-  memset (buf, 0, PATH_MAX);
-  if (readlink (name, buf, PATH_MAX - 1) <= 0)
-    strcpy (buf, name);
-
-  return buf;
+  return linux_proc_pid_to_exec_file (pid);
 }
 
 /* Implement the to_xfer_partial interface for memory reads using the /proc
@@ -4121,13 +4372,13 @@ linux_proc_pending_signals (int pid, sigset_t *pending,
         Unfortunately some Red Hat kernels include the shared pending
         queue but not the ShdPnd status field.  */
 
-      if (strncmp (buffer, "SigPnd:\t", 8) == 0)
+      if (startswith (buffer, "SigPnd:\t"))
        add_line_to_sigset (buffer + 8, pending);
-      else if (strncmp (buffer, "ShdPnd:\t", 8) == 0)
+      else if (startswith (buffer, "ShdPnd:\t"))
        add_line_to_sigset (buffer + 8, pending);
-      else if (strncmp (buffer, "SigBlk:\t", 8) == 0)
+      else if (startswith (buffer, "SigBlk:\t"))
        add_line_to_sigset (buffer + 8, blocked);
-      else if (strncmp (buffer, "SigIgn:\t", 8) == 0)
+      else if (startswith (buffer, "SigIgn:\t"))
        add_line_to_sigset (buffer + 8, ignored);
     }
 
@@ -4409,10 +4660,6 @@ linux_nat_terminal_ours (struct target_ops *self)
   async_terminal_is_ours = 1;
 }
 
-static void (*async_client_callback) (enum inferior_event_type event_type,
-                                     void *context);
-static void *async_client_context;
-
 /* SIGCHLD handler that serves two purposes: In non-stop/async mode,
    so we notice when any child changes state, and notify the
    event-loop; it allows us to use sigsuspend in linux_nat_wait_1
@@ -4440,7 +4687,7 @@ sigchld_handler (int signo)
 static void
 handle_target_event (int error, gdb_client_data client_data)
 {
-  (*async_client_callback) (INF_REG_EVENT, async_client_context);
+  inferior_event_handler (INF_REG_EVENT, NULL);
 }
 
 /* Create/destroy the target events pipe.  Returns previous state.  */
@@ -4484,15 +4731,10 @@ linux_async_pipe (int enable)
 /* target_async implementation.  */
 
 static void
-linux_nat_async (struct target_ops *ops,
-                void (*callback) (enum inferior_event_type event_type,
-                                  void *context),
-                void *context)
+linux_nat_async (struct target_ops *ops, int enable)
 {
-  if (callback != NULL)
+  if (enable)
     {
-      async_client_callback = callback;
-      async_client_context = context;
       if (!linux_async_pipe (1))
        {
          add_file_handler (linux_nat_event_pipe[0],
@@ -4504,8 +4746,6 @@ linux_nat_async (struct target_ops *ops,
     }
   else
     {
-      async_client_callback = callback;
-      async_client_context = context;
       delete_file_handler (linux_nat_event_pipe[0]);
       linux_async_pipe (0);
     }
@@ -4573,7 +4813,7 @@ linux_nat_close (struct target_ops *self)
 {
   /* Unregister from the event loop.  */
   if (linux_nat_is_async_p (self))
-    linux_nat_async (self, NULL, NULL);
+    linux_nat_async (self, 0);
 
   if (linux_ops->to_close)
     linux_ops->to_close (linux_ops);
@@ -4646,12 +4886,17 @@ linux_nat_add_target (struct target_ops *t)
   t->to_kill = linux_nat_kill;
   t->to_mourn_inferior = linux_nat_mourn_inferior;
   t->to_thread_alive = linux_nat_thread_alive;
+  t->to_update_thread_list = linux_nat_update_thread_list;
   t->to_pid_to_str = linux_nat_pid_to_str;
   t->to_thread_name = linux_nat_thread_name;
   t->to_has_thread_control = tc_schedlock;
   t->to_thread_address_space = linux_nat_thread_address_space;
   t->to_stopped_by_watchpoint = linux_nat_stopped_by_watchpoint;
   t->to_stopped_data_address = linux_nat_stopped_data_address;
+  t->to_stopped_by_sw_breakpoint = linux_nat_stopped_by_sw_breakpoint;
+  t->to_supports_stopped_by_sw_breakpoint = linux_nat_supports_stopped_by_sw_breakpoint;
+  t->to_stopped_by_hw_breakpoint = linux_nat_stopped_by_hw_breakpoint;
+  t->to_supports_stopped_by_hw_breakpoint = linux_nat_supports_stopped_by_hw_breakpoint;
 
   t->to_can_async_p = linux_nat_can_async_p;
   t->to_is_async_p = linux_nat_is_async_p;
@@ -4766,6 +5011,15 @@ linux_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo)
   return 1;
 }
 
+/* See nat/linux-nat.h.  */
+
+ptid_t
+current_lwp_ptid (void)
+{
+  gdb_assert (ptid_lwp_p (inferior_ptid));
+  return inferior_ptid;
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_linux_nat;
 
@@ -4797,14 +5051,6 @@ Enables printf debugging output."),
   sigdelset (&suspend_mask, SIGCHLD);
 
   sigemptyset (&blocked_mask);
-
-  /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to
-     support read-only process state.  */
-  linux_ptrace_set_additional_flags (PTRACE_O_TRACESYSGOOD
-                                    | PTRACE_O_TRACEVFORKDONE
-                                    | PTRACE_O_TRACEVFORK
-                                    | PTRACE_O_TRACEFORK
-                                    | PTRACE_O_TRACEEXEC);
 }
 \f
 
This page took 0.034978 seconds and 4 git commands to generate.