Initialise target descrption after skipping extra traps for --wrapper
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-low.c
index e53e0fc187d39cf5996e6c6e16de01485721f778..ac1ad6f2147eb971336c714ceeb519a1b1ffe4ec 100644 (file)
@@ -20,6 +20,8 @@
 #include "linux-low.h"
 #include "nat/linux-osdata.h"
 #include "agent.h"
+#include "tdesc.h"
+#include "rsp-low.h"
 
 #include "nat/linux-nat.h"
 #include "nat/linux-waitpid.h"
@@ -51,6 +53,7 @@
    definition of elf_fpregset_t.  */
 #include <elf.h>
 #endif
+#include "nat/linux-namespaces.h"
 
 #ifndef SPUFS_MAGIC
 #define SPUFS_MAGIC 0x23c9b64e
@@ -136,6 +139,49 @@ typedef struct
 } Elf64_auxv_t;
 #endif
 
+/* LWP accessors.  */
+
+/* See nat/linux-nat.h.  */
+
+ptid_t
+ptid_of_lwp (struct lwp_info *lwp)
+{
+  return ptid_of (get_lwp_thread (lwp));
+}
+
+/* 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;
+}
+
 /* A list of all unknown processes which receive stop signals.  Some
    other process will presumably claim each of these as forked
    children momentarily.  */
@@ -359,9 +405,6 @@ linux_add_process (int pid, int attached)
   proc = add_process (pid, attached);
   proc->priv = xcalloc (1, sizeof (*proc->priv));
 
-  /* Set the arch when the first LWP stops.  */
-  proc->priv->new_inferior = 1;
-
   if (the_low_target.new_process != NULL)
     proc->priv->arch_private = the_low_target.new_process ();
 
@@ -371,22 +414,24 @@ linux_add_process (int pid, int attached)
 static CORE_ADDR get_pc (struct lwp_info *lwp);
 
 /* Handle a GNU/Linux extended wait response.  If we see a clone
-   event, we need to add the new LWP to our list (and not report the
-   trap to higher layers).  */
+   event, we need to add the new LWP to our list (and return 0 so as
+   not to report the trap to higher layers).  */
 
-static void
-handle_extended_wait (struct lwp_info *event_child, int wstat)
+static int
+handle_extended_wait (struct lwp_info *event_lwp, int wstat)
 {
   int event = linux_ptrace_get_extended_event (wstat);
-  struct thread_info *event_thr = get_lwp_thread (event_child);
+  struct thread_info *event_thr = get_lwp_thread (event_lwp);
   struct lwp_info *new_lwp;
 
-  if (event == PTRACE_EVENT_CLONE)
+  if ((event == PTRACE_EVENT_FORK) || (event == PTRACE_EVENT_VFORK)
+      || (event == PTRACE_EVENT_CLONE))
     {
       ptid_t ptid;
       unsigned long new_pid;
       int ret, status;
 
+      /* Get the pid of the new lwp.  */
       ptrace (PTRACE_GETEVENTMSG, lwpid_of (event_thr), (PTRACE_TYPE_ARG3) 0,
              &new_pid);
 
@@ -406,6 +451,70 @@ handle_extended_wait (struct lwp_info *event_child, int wstat)
            warning ("wait returned unexpected status 0x%x", status);
        }
 
+      if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK)
+       {
+         struct process_info *parent_proc;
+         struct process_info *child_proc;
+         struct lwp_info *child_lwp;
+         struct thread_info *child_thr;
+         struct target_desc *tdesc;
+
+         ptid = ptid_build (new_pid, new_pid, 0);
+
+         if (debug_threads)
+           {
+             debug_printf ("HEW: Got fork event from LWP %ld, "
+                           "new child is %d\n",
+                           ptid_get_lwp (ptid_of (event_thr)),
+                           ptid_get_pid (ptid));
+           }
+
+         /* Add the new process to the tables and clone the breakpoint
+            lists of the parent.  We need to do this even if the new process
+            will be detached, since we will need the process object and the
+            breakpoints to remove any breakpoints from memory when we
+            detach, and the client side will access registers.  */
+         child_proc = linux_add_process (new_pid, 0);
+         gdb_assert (child_proc != NULL);
+         child_lwp = add_lwp (ptid);
+         gdb_assert (child_lwp != NULL);
+         child_lwp->stopped = 1;
+         child_lwp->must_set_ptrace_flags = 1;
+         child_lwp->status_pending_p = 0;
+         child_thr = get_lwp_thread (child_lwp);
+         child_thr->last_resume_kind = resume_stop;
+         parent_proc = get_thread_process (event_thr);
+         child_proc->attached = parent_proc->attached;
+         clone_all_breakpoints (&child_proc->breakpoints,
+                                &child_proc->raw_breakpoints,
+                                parent_proc->breakpoints);
+
+         tdesc = xmalloc (sizeof (struct target_desc));
+         copy_target_description (tdesc, parent_proc->tdesc);
+         child_proc->tdesc = tdesc;
+
+         /* Clone arch-specific process data.  */
+         if (the_low_target.new_fork != NULL)
+           the_low_target.new_fork (parent_proc, child_proc);
+
+         /* Save fork info in the parent thread.  */
+         if (event == PTRACE_EVENT_FORK)
+           event_lwp->waitstatus.kind = TARGET_WAITKIND_FORKED;
+         else if (event == PTRACE_EVENT_VFORK)
+           event_lwp->waitstatus.kind = TARGET_WAITKIND_VFORKED;
+
+         event_lwp->waitstatus.value.related_pid = ptid;
+
+         /* The status_pending field contains bits denoting the
+            extended event, so when the pending event is handled,
+            the handler will look at lwp->waitstatus.  */
+         event_lwp->status_pending_p = 1;
+         event_lwp->status_pending = wstat;
+
+         /* Report the event.  */
+         return 0;
+       }
+
       if (debug_threads)
        debug_printf ("HEW: Got clone event "
                      "from LWP %ld, new child is LWP %ld\n",
@@ -434,7 +543,19 @@ handle_extended_wait (struct lwp_info *event_child, int wstat)
          new_lwp->status_pending_p = 1;
          new_lwp->status_pending = status;
        }
+
+      /* Don't report the event.  */
+      return 1;
+    }
+  else if (event == PTRACE_EVENT_VFORK_DONE)
+    {
+      event_lwp->waitstatus.kind = TARGET_WAITKIND_VFORK_DONE;
+
+      /* Report the event.  */
+      return 0;
     }
+
+  internal_error (__FILE__, __LINE__, _("unknown ptrace event %d"), event);
 }
 
 /* Return the PC as read from the regcache of LWP, without any
@@ -519,7 +640,7 @@ check_stopped_by_breakpoint (struct lwp_info *lwp)
                {
                  struct thread_info *thr = get_lwp_thread (lwp);
 
-                 debug_printf ("CSBB: Push back software breakpoint for %s\n",
+                 debug_printf ("CSBB: %s stopped by software breakpoint\n",
                                target_pid_to_str (ptid_of (thr)));
                }
 
@@ -542,8 +663,8 @@ check_stopped_by_breakpoint (struct lwp_info *lwp)
                {
                  struct thread_info *thr = get_lwp_thread (lwp);
 
-                 debug_printf ("CSBB: Push back hardware "
-                               "breakpoint/watchpoint for %s\n",
+                 debug_printf ("CSBB: %s stopped by hardware "
+                               "breakpoint/watchpoint\n",
                                target_pid_to_str (ptid_of (thr)));
                }
 
@@ -552,6 +673,16 @@ check_stopped_by_breakpoint (struct lwp_info *lwp)
              current_thread = saved_thread;
              return 1;
            }
+         else if (siginfo.si_code == TRAP_TRACE)
+           {
+             if (debug_threads)
+               {
+                 struct thread_info *thr = get_lwp_thread (lwp);
+
+                 debug_printf ("CSBB: %s stopped by trace\n",
+                               target_pid_to_str (ptid_of (thr)));
+               }
+           }
        }
     }
 #else
@@ -614,7 +745,7 @@ add_lwp (ptid_t ptid)
   memset (lwp, 0, sizeof (*lwp));
 
   if (the_low_target.new_thread != NULL)
-    lwp->arch_private = the_low_target.new_thread ();
+    the_low_target.new_thread (lwp);
 
   lwp->thread = add_thread (ptid, lwp);
 
@@ -632,6 +763,7 @@ linux_create_inferior (char *program, char **allargs)
   ptid_t ptid;
   struct cleanup *restore_personality
     = maybe_disable_address_space_randomization (disable_randomization);
+  struct process_info *proc;
 
 #if defined(__UCLIBC__) && defined(HAS_NOMMU)
   pid = vfork ();
@@ -679,7 +811,9 @@ linux_create_inferior (char *program, char **allargs)
 
   do_cleanups (restore_personality);
 
-  linux_add_process (pid, 0);
+  proc = linux_add_process (pid, 0);
+  /* Set the arch when the first LWP stops.  */
+  proc->priv->new_inferior = 1;
 
   ptid = ptid_build (pid, pid, 0);
   new_lwp = add_lwp (ptid);
@@ -688,6 +822,14 @@ linux_create_inferior (char *program, char **allargs)
   return pid;
 }
 
+/* Implement the arch_setup target_ops method.  */
+
+static void
+linux_arch_setup (void)
+{
+  the_low_target.arch_setup ();
+}
+
 /* Attach to an inferior process.  Returns 0 on success, ERRNO on
    error.  */
 
@@ -825,6 +967,7 @@ linux_attach (unsigned long pid)
 {
   ptid_t ptid = ptid_build (pid, pid, 0);
   int err;
+  struct process_info *proc;
 
   /* Attach to PID.  We will check for other threads
      soon.  */
@@ -833,7 +976,9 @@ linux_attach (unsigned long pid)
     error ("Cannot attach to process %ld: %s",
           pid, linux_ptrace_attach_fail_reason_string (ptid, err));
 
-  linux_add_process (pid, 1);
+  proc = linux_add_process (pid, 1);
+  /* Set the arch when the first LWP stops.  */
+  proc->priv->new_inferior = 1;
 
   if (!non_stop)
     {
@@ -969,7 +1114,10 @@ kill_wait_lwp (struct lwp_info *lwp)
        res = my_waitpid (lwpid, &wstat, __WCLONE);
     } while (res > 0 && WIFSTOPPED (wstat));
 
-  gdb_assert (res > 0);
+  /* Even if it was stopped, the child may have already disappeared.
+     E.g., if it was killed by SIGKILL.  */
+  if (res < 0 && errno != ECHILD)
+    perror_with_name ("kill_wait_lwp");
 }
 
 /* Callback for `find_inferior'.  Kills an lwp of a given process,
@@ -1397,6 +1545,60 @@ num_lwps (int pid)
   return count;
 }
 
+/* The arguments passed to iterate_over_lwps.  */
+
+struct iterate_over_lwps_args
+{
+  /* The FILTER argument passed to iterate_over_lwps.  */
+  ptid_t filter;
+
+  /* The CALLBACK argument passed to iterate_over_lwps.  */
+  iterate_over_lwps_ftype *callback;
+
+  /* The DATA argument passed to iterate_over_lwps.  */
+  void *data;
+};
+
+/* Callback for find_inferior used by iterate_over_lwps to filter
+   calls to the callback supplied to that function.  Returning a
+   nonzero value causes find_inferiors to stop iterating and return
+   the current inferior_list_entry.  Returning zero indicates that
+   find_inferiors should continue iterating.  */
+
+static int
+iterate_over_lwps_filter (struct inferior_list_entry *entry, void *args_p)
+{
+  struct iterate_over_lwps_args *args
+    = (struct iterate_over_lwps_args *) args_p;
+
+  if (ptid_match (entry->id, args->filter))
+    {
+      struct thread_info *thr = (struct thread_info *) entry;
+      struct lwp_info *lwp = get_thread_lwp (thr);
+
+      return (*args->callback) (lwp, args->data);
+    }
+
+  return 0;
+}
+
+/* See nat/linux-nat.h.  */
+
+struct lwp_info *
+iterate_over_lwps (ptid_t filter,
+                  iterate_over_lwps_ftype callback,
+                  void *data)
+{
+  struct iterate_over_lwps_args args = {filter, callback, data};
+  struct inferior_list_entry *entry;
+
+  entry = find_inferior (&all_threads, iterate_over_lwps_filter, &args);
+  if (entry == NULL)
+    return NULL;
+
+  return get_thread_lwp ((struct thread_info *) entry);
+}
+
 /* Detect zombie thread group leaders, and "exit" them.  We can't reap
    their exits until all other threads in the group have exited.  */
 
@@ -1828,6 +2030,25 @@ check_stopped_by_watchpoint (struct lwp_info *child)
   return child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
 }
 
+/* Return the ptrace options that we want to try to enable.  */
+
+static int
+linux_low_ptrace_options (int attached)
+{
+  int options = 0;
+
+  if (!attached)
+    options |= PTRACE_O_EXITKILL;
+
+  if (report_fork_events)
+    options |= PTRACE_O_TRACEFORK;
+
+  if (report_vfork_events)
+    options |= (PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE);
+
+  return options;
+}
+
 /* Do low-level handling of the event, and check if we should go on
    and pass it to caller code.  Return the affected lwp if we are, or
    NULL otherwise.  */
@@ -1892,31 +2113,44 @@ linux_low_filter_event (int lwpid, int wstat)
     {
       struct process_info *proc;
 
-      /* Architecture-specific setup after inferior is running.  This
-        needs to happen after we have attached to the inferior and it
-        is stopped for the first time, but before we access any
-        inferior registers.  */
+      /* Architecture-specific setup after inferior is running.  */
       proc = find_process_pid (pid_of (thread));
-      if (proc->priv->new_inferior)
+      if (proc->tdesc == NULL)
        {
-         struct thread_info *saved_thread;
+         if (proc->attached)
+           {
+             struct thread_info *saved_thread;
 
-         saved_thread = current_thread;
-         current_thread = thread;
+             /* This needs to happen after we have attached to the
+                inferior and it is stopped for the first time, but
+                before we access any inferior registers.  */
+             saved_thread = current_thread;
+             current_thread = thread;
 
-         the_low_target.arch_setup ();
+             the_low_target.arch_setup ();
 
-         current_thread = saved_thread;
+             current_thread = saved_thread;
 
-         proc->priv->new_inferior = 0;
+             proc->priv->new_inferior = 0;
+           }
+         else
+           {
+             /* The process is started, but GDBserver will do
+                architecture-specific setup after the program stops at
+                the first instruction.  */
+             child->status_pending_p = 1;
+             child->status_pending = wstat;
+             return child;
+           }
        }
     }
 
   if (WIFSTOPPED (wstat) && child->must_set_ptrace_flags)
     {
       struct process_info *proc = find_process_pid (pid_of (thread));
+      int options = linux_low_ptrace_options (proc->attached);
 
-      linux_enable_event_reporting (lwpid, proc->attached);
+      linux_enable_event_reporting (lwpid, options);
       child->must_set_ptrace_flags = 0;
     }
 
@@ -1926,8 +2160,12 @@ linux_low_filter_event (int lwpid, int wstat)
       && linux_is_extended_waitstatus (wstat))
     {
       child->stop_pc = get_pc (child);
-      handle_extended_wait (child, wstat);
-      return NULL;
+      if (handle_extended_wait (child, wstat))
+       {
+         /* The event has been handled, so just return without
+            reporting it.  */
+         return NULL;
+       }
     }
 
   /* Check first whether this was a SW/HW breakpoint before checking
@@ -1962,16 +2200,28 @@ linux_low_filter_event (int lwpid, int wstat)
        {
          /* We want to report the stop to the core.  Treat the
             SIGSTOP as a normal event.  */
+         if (debug_threads)
+           debug_printf ("LLW: resume_stop SIGSTOP caught for %s.\n",
+                         target_pid_to_str (ptid_of (thread)));
        }
       else if (stopping_threads != NOT_STOPPING_THREADS)
        {
          /* Stopping threads.  We don't want this SIGSTOP to end up
             pending.  */
+         if (debug_threads)
+           debug_printf ("LLW: SIGSTOP caught for %s "
+                         "while stopping threads.\n",
+                         target_pid_to_str (ptid_of (thread)));
          return NULL;
        }
       else
        {
-         /* Filter out the event.  */
+         /* This is a delayed SIGSTOP.  Filter out the event.  */
+         if (debug_threads)
+           debug_printf ("LLW: %s %s, 0, 0 (discard delayed SIGSTOP)\n",
+                         child->stepping ? "step" : "continue",
+                         target_pid_to_str (ptid_of (thread)));
+
          linux_resume_one_lwp (child, child->stepping, 0, NULL);
          return NULL;
        }
@@ -2245,7 +2495,6 @@ count_events_callback (struct inferior_list_entry *entry, void *data)
 
   /* Count only resumed LWPs that have an event pending. */
   if (thread->last_status.kind == TARGET_WAITKIND_IGNORE
-      && thread->last_resume_kind != resume_stop
       && lp->status_pending_p)
     (*count)++;
 
@@ -2280,8 +2529,7 @@ select_event_lwp_callback (struct inferior_list_entry *entry, void *data)
   gdb_assert (selector != NULL);
 
   /* Select only resumed LWPs that have an event pending. */
-  if (thread->last_resume_kind != resume_stop
-      && thread->last_status.kind == TARGET_WAITKIND_IGNORE
+  if (thread->last_status.kind == TARGET_WAITKIND_IGNORE
       && lp->status_pending_p)
     if ((*selector)-- == 0)
       return 1;
@@ -2505,6 +2753,20 @@ ignore_event (struct target_waitstatus *ourstatus)
   return null_ptid;
 }
 
+/* Return non-zero if WAITSTATUS reflects an extended linux
+   event.  Otherwise, return zero.  */
+
+static int
+extended_event_reported (const struct target_waitstatus *waitstatus)
+{
+  if (waitstatus == NULL)
+    return 0;
+
+  return (waitstatus->kind == TARGET_WAITKIND_FORKED
+         || waitstatus->kind == TARGET_WAITKIND_VFORKED
+         || waitstatus->kind == TARGET_WAITKIND_VFORK_DONE);
+}
+
 /* Wait for process, returns status.  */
 
 static ptid_t
@@ -2871,7 +3133,8 @@ linux_wait_1 (ptid_t ptid,
                       && !bp_explains_trap && !trace_event)
                   || (gdb_breakpoint_here (event_child->stop_pc)
                       && gdb_condition_true_at_breakpoint (event_child->stop_pc)
-                      && gdb_no_commands_at_breakpoint (event_child->stop_pc)));
+                      && gdb_no_commands_at_breakpoint (event_child->stop_pc))
+                  || extended_event_reported (&event_child->waitstatus));
 
   run_breakpoint_commands (event_child->stop_pc);
 
@@ -2893,6 +3156,13 @@ linux_wait_1 (ptid_t ptid,
                          paddress (event_child->stop_pc),
                          paddress (event_child->step_range_start),
                          paddress (event_child->step_range_end));
+         if (extended_event_reported (&event_child->waitstatus))
+           {
+             char *str = target_waitstatus_to_string (ourstatus);
+             debug_printf ("LWP %ld: extended event with waitstatus %s\n",
+                           lwpid_of (get_lwp_thread (event_child)), str);
+             xfree (str);
+           }
        }
 
       /* We're not reporting this breakpoint to GDB, so apply the
@@ -3002,7 +3272,17 @@ linux_wait_1 (ptid_t ptid,
        unstop_all_lwps (1, event_child);
     }
 
-  ourstatus->kind = TARGET_WAITKIND_STOPPED;
+  if (extended_event_reported (&event_child->waitstatus))
+    {
+      /* If the reported event is a fork, vfork or exec, let GDB know.  */
+      ourstatus->kind = event_child->waitstatus.kind;
+      ourstatus->value = event_child->waitstatus.value;
+
+      /* Clear the event lwp's waitstatus since we handled it already.  */
+      event_child->waitstatus.kind = TARGET_WAITKIND_IGNORE;
+    }
+  else
+    ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
   /* Now that we've selected our final event LWP, un-adjust its PC if
      it was a software breakpoint, and the client doesn't know we can
@@ -3035,7 +3315,7 @@ linux_wait_1 (ptid_t ptid,
         but, it stopped for other reasons.  */
       ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (w));
     }
-  else
+  else if (ourstatus->kind == TARGET_WAITKIND_STOPPED)
     {
       ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (w));
     }
@@ -3381,17 +3661,24 @@ stop_all_lwps (int suspend, struct lwp_info *except)
     }
 }
 
-/* Resume execution of the inferior process.
-   If STEP is nonzero, single-step it.
-   If SIGNAL is nonzero, give it that signal.  */
+/* Resume execution of LWP.  If STEP is nonzero, single-step it.  If
+   SIGNAL is nonzero, give it that signal.  */
 
 static void
-linux_resume_one_lwp (struct lwp_info *lwp,
-                     int step, int signal, siginfo_t *info)
+linux_resume_one_lwp_throw (struct lwp_info *lwp,
+                           int step, int signal, siginfo_t *info)
 {
   struct thread_info *thread = get_lwp_thread (lwp);
   struct thread_info *saved_thread;
   int fast_tp_collecting;
+  struct process_info *proc = get_thread_process (thread);
+
+  /* Note that target description may not be initialised
+     (proc->tdesc == NULL) at this point because the program hasn't
+     stopped at the first instruction yet.  It means GDBserver skips
+     the extra traps from the wrapper program (see option --wrapper).
+     Code in this function that requires register access should be
+     guarded by proc->tdesc == NULL or something else.  */
 
   if (lwp->stopped == 0)
     return;
@@ -3402,7 +3689,7 @@ linux_resume_one_lwp (struct lwp_info *lwp,
 
   /* Cancel actions that rely on GDB not changing the PC (e.g., the
      user used the "jump" command, or "set $pc = foo").  */
-  if (lwp->stop_pc != get_pc (lwp))
+  if (thread->while_stepping != NULL && lwp->stop_pc != get_pc (lwp))
     {
       /* Collecting 'while-stepping' actions doesn't make sense
         anymore.  */
@@ -3528,7 +3815,7 @@ linux_resume_one_lwp (struct lwp_info *lwp,
       step = 1;
     }
 
-  if (the_low_target.get_pc != NULL)
+  if (proc->tdesc != NULL && the_low_target.get_pc != NULL)
     {
       struct regcache *regcache = get_thread_regcache (current_thread, 1);
 
@@ -3568,8 +3855,6 @@ linux_resume_one_lwp (struct lwp_info *lwp,
 
   regcache_invalidate_thread (thread);
   errno = 0;
-  lwp->stopped = 0;
-  lwp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
   lwp->stepping = step;
   ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (thread),
          (PTRACE_TYPE_ARG3) 0,
@@ -3579,19 +3864,68 @@ linux_resume_one_lwp (struct lwp_info *lwp,
 
   current_thread = saved_thread;
   if (errno)
+    perror_with_name ("resuming thread");
+
+  /* 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.  */
+  lwp->stopped = 0;
+  lwp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+}
+
+/* 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)
+{
+  struct thread_info *thread = get_lwp_thread (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 (lwpid_of (thread)) == 0)
     {
-      /* ESRCH from ptrace either means that the thread was already
-        running (an error) or that it is gone (a race condition).  If
-        it's gone, we will get a notification the next time we wait,
-        so we can ignore the error.  We could differentiate these
-        two, but it's tricky without waiting; the thread still exists
-        as a zombie, so sending it signal 0 would succeed.  So just
-        ignore ESRCH.  */
-      if (errno == ESRCH)
-       return;
+      lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+      lp->status_pending_p = 0;
+      return 1;
+    }
+  return 0;
+}
 
-      perror_with_name ("ptrace");
+/* 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 *lwp,
+                     int step, int signal, siginfo_t *info)
+{
+  TRY
+    {
+      linux_resume_one_lwp_throw (lwp, step, signal, info);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (!check_ptrace_stopped_lwp_gone (lwp))
+       throw_exception (ex);
     }
+  END_CATCH
 }
 
 struct thread_resume_array
@@ -3708,6 +4042,12 @@ need_step_over_p (struct inferior_list_entry *entry, void *dummy)
   struct lwp_info *lwp = get_thread_lwp (thread);
   struct thread_info *saved_thread;
   CORE_ADDR pc;
+  struct process_info *proc = get_thread_process (thread);
+
+  /* GDBserver is skipping the extra traps from the wrapper program,
+     don't have to do step over.  */
+  if (proc->tdesc == NULL)
+    return 0;
 
   /* LWPs which will not be resumed are not interesting, because we
      might not wait for them next time through linux_wait.  */
@@ -4833,8 +5173,8 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
        val = val & 0xffff;
       else if (len == 3)
        val = val & 0xffffff;
-      debug_printf ("Writing %0*x to 0x%08lx\n", 2 * ((len < 4) ? len : 4),
-                   val, (long)memaddr);
+      debug_printf ("Writing %0*x to 0x%08lx in process %d\n",
+                   2 * ((len < 4) ? len : 4), val, (long)memaddr, pid);
     }
 
   /* Fill start and end extra bytes of buffer with existing memory data.  */
@@ -4952,7 +5292,9 @@ static int
 linux_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
                    int size, struct raw_breakpoint *bp)
 {
-  if (the_low_target.insert_point != NULL)
+  if (type == raw_bkpt_type_sw)
+    return insert_memory_breakpoint (bp);
+  else if (the_low_target.insert_point != NULL)
     return the_low_target.insert_point (type, addr, size, bp);
   else
     /* Unsupported (see target.h).  */
@@ -4963,7 +5305,9 @@ static int
 linux_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
                    int size, struct raw_breakpoint *bp)
 {
-  if (the_low_target.remove_point != NULL)
+  if (type == raw_bkpt_type_sw)
+    return remove_memory_breakpoint (bp);
+  else if (the_low_target.remove_point != NULL)
     return the_low_target.remove_point (type, addr, size, bp);
   else
     /* Unsupported (see target.h).  */
@@ -5010,6 +5354,19 @@ linux_supports_stopped_by_hw_breakpoint (void)
   return USE_SIGTRAP_SIGINFO;
 }
 
+/* Implement the supports_conditional_breakpoints target_ops
+   method.  */
+
+static int
+linux_supports_conditional_breakpoints (void)
+{
+  /* GDBserver needs to step over the breakpoint if the condition is
+     false.  GDBserver software single step is too simple, so disable
+     conditional breakpoints if the target doesn't have hardware single
+     step.  */
+  return can_hardware_single_step ();
+}
+
 static int
 linux_stopped_by_watchpoint (void)
 {
@@ -5042,7 +5399,7 @@ static int
 linux_read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p)
 {
   unsigned long text, text_end, data;
-  int pid = lwpid_of (get_thread_lwp (current_thread));
+  int pid = lwpid_of (current_thread);
 
   errno = 0;
 
@@ -5258,6 +5615,64 @@ linux_supports_multi_process (void)
   return 1;
 }
 
+/* Check if fork events are supported.  */
+
+static int
+linux_supports_fork_events (void)
+{
+  return linux_supports_tracefork ();
+}
+
+/* Check if vfork events are supported.  */
+
+static int
+linux_supports_vfork_events (void)
+{
+  return linux_supports_tracefork ();
+}
+
+/* Callback for 'find_inferior'.  Set the (possibly changed) ptrace
+   options for the specified lwp.  */
+
+static int
+reset_lwp_ptrace_options_callback (struct inferior_list_entry *entry,
+                                  void *args)
+{
+  struct thread_info *thread = (struct thread_info *) entry;
+  struct lwp_info *lwp = get_thread_lwp (thread);
+
+  if (!lwp->stopped)
+    {
+      /* Stop the lwp so we can modify its ptrace options.  */
+      lwp->must_set_ptrace_flags = 1;
+      linux_stop_lwp (lwp);
+    }
+  else
+    {
+      /* Already stopped; go ahead and set the ptrace options.  */
+      struct process_info *proc = find_process_pid (pid_of (thread));
+      int options = linux_low_ptrace_options (proc->attached);
+
+      linux_enable_event_reporting (lwpid_of (thread), options);
+      lwp->must_set_ptrace_flags = 0;
+    }
+
+  return 0;
+}
+
+/* Target hook for 'handle_new_gdb_connection'.  Causes a reset of the
+   ptrace flags for all inferiors.  This is in case the new GDB connection
+   doesn't support the same set of events that the previous one did.  */
+
+static void
+linux_handle_new_gdb_connection (void)
+{
+  pid_t pid;
+
+  /* Request that all the lwps reset their ptrace options.  */
+  find_inferior (&all_threads, reset_lwp_ptrace_options_callback , &pid);
+}
+
 static int
 linux_supports_disable_randomization (void)
 {
@@ -6087,6 +6502,55 @@ linux_low_disable_btrace (struct btrace_target_info *tinfo)
   return (err == BTRACE_ERR_NONE ? 0 : -1);
 }
 
+/* Encode an Intel(R) Processor Trace configuration.  */
+
+static void
+linux_low_encode_pt_config (struct buffer *buffer,
+                           const struct btrace_data_pt_config *config)
+{
+  buffer_grow_str (buffer, "<pt-config>\n");
+
+  switch (config->cpu.vendor)
+    {
+    case CV_INTEL:
+      buffer_xml_printf (buffer, "<cpu vendor=\"GenuineIntel\" family=\"%u\" "
+                        "model=\"%u\" stepping=\"%u\"/>\n",
+                        config->cpu.family, config->cpu.model,
+                        config->cpu.stepping);
+      break;
+
+    default:
+      break;
+    }
+
+  buffer_grow_str (buffer, "</pt-config>\n");
+}
+
+/* Encode a raw buffer.  */
+
+static void
+linux_low_encode_raw (struct buffer *buffer, const gdb_byte *data,
+                     unsigned int size)
+{
+  if (size == 0)
+    return;
+
+  /* We use hex encoding - see common/rsp-low.h.  */
+  buffer_grow_str (buffer, "<raw>\n");
+
+  while (size-- > 0)
+    {
+      char elem[2];
+
+      elem[0] = tohex ((*data >> 4) & 0xf);
+      elem[1] = tohex (*data++ & 0xf);
+
+      buffer_grow (buffer, elem, 2);
+    }
+
+  buffer_grow_str (buffer, "</raw>\n");
+}
+
 /* See to_read_btrace target method.  */
 
 static int
@@ -6108,15 +6572,14 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
       else
        buffer_grow_str0 (buffer, "E.Generic Error.");
 
-      btrace_data_fini (&btrace);
-      return -1;
+      goto err;
     }
 
   switch (btrace.format)
     {
     case BTRACE_FORMAT_NONE:
       buffer_grow_str0 (buffer, "E.No Trace.");
-      break;
+      goto err;
 
     case BTRACE_FORMAT_BTS:
       buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
@@ -6131,15 +6594,31 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
       buffer_grow_str0 (buffer, "</btrace>\n");
       break;
 
-    default:
-      buffer_grow_str0 (buffer, "E.Unknown Trace Format.");
+    case BTRACE_FORMAT_PT:
+      buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
+      buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+      buffer_grow_str (buffer, "<pt>\n");
+
+      linux_low_encode_pt_config (buffer, &btrace.variant.pt.config);
+
+      linux_low_encode_raw (buffer, btrace.variant.pt.data,
+                           btrace.variant.pt.size);
 
-      btrace_data_fini (&btrace);
-      return -1;
+      buffer_grow_str (buffer, "</pt>\n");
+      buffer_grow_str0 (buffer, "</btrace>\n");
+      break;
+
+    default:
+      buffer_grow_str0 (buffer, "E.Unsupported Trace Format.");
+      goto err;
     }
 
   btrace_data_fini (&btrace);
   return 0;
+
+err:
+  btrace_data_fini (&btrace);
+  return -1;
 }
 
 /* See to_btrace_conf target method.  */
@@ -6166,6 +6645,12 @@ linux_low_btrace_conf (const struct btrace_target_info *tinfo,
          buffer_xml_printf (buffer, " size=\"0x%x\"", conf->bts.size);
          buffer_xml_printf (buffer, " />\n");
          break;
+
+       case BTRACE_FORMAT_PT:
+         buffer_xml_printf (buffer, "<pt");
+         buffer_xml_printf (buffer, " size=\"0x%x\"", conf->pt.size);
+         buffer_xml_printf (buffer, "/>\n");
+         break;
        }
     }
 
@@ -6174,8 +6659,17 @@ linux_low_btrace_conf (const struct btrace_target_info *tinfo,
 }
 #endif /* HAVE_LINUX_BTRACE */
 
+/* See nat/linux-nat.h.  */
+
+ptid_t
+current_lwp_ptid (void)
+{
+  return ptid_of (current_thread);
+}
+
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
+  linux_arch_setup,
   linux_attach,
   linux_kill,
   linux_detach,
@@ -6200,6 +6694,7 @@ static struct target_ops linux_target_ops = {
   linux_supports_stopped_by_sw_breakpoint,
   linux_stopped_by_hw_breakpoint,
   linux_supports_stopped_by_hw_breakpoint,
+  linux_supports_conditional_breakpoints,
   linux_stopped_by_watchpoint,
   linux_stopped_data_address,
 #if defined(__UCLIBC__) && defined(HAS_NOMMU)        \
@@ -6222,6 +6717,9 @@ static struct target_ops linux_target_ops = {
   linux_async,
   linux_start_non_stop,
   linux_supports_multi_process,
+  linux_supports_fork_events,
+  linux_supports_vfork_events,
+  linux_handle_new_gdb_connection,
 #ifdef USE_THREAD_DB
   thread_db_handle_monitor_command,
 #else
@@ -6258,6 +6756,10 @@ static struct target_ops linux_target_ops = {
   NULL,
 #endif
   linux_supports_range_stepping,
+  linux_proc_pid_to_exec_file,
+  linux_mntns_open_cloexec,
+  linux_mntns_unlink,
+  linux_mntns_readlink,
 };
 
 static void
@@ -6298,4 +6800,6 @@ initialize_low (void)
   sigaction (SIGCHLD, &sigchld_action, NULL);
 
   initialize_low_arch ();
+
+  linux_check_ptrace_features ();
 }
This page took 0.035324 seconds and 4 git commands to generate.