gdbserver: fix killed-outside.exp
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-low.c
index 3a1a6ae57ea3ddab3fd38ca80d326faebc363310..07cb83120d310570cbbef4c7d409426c00f3f034 100644 (file)
 #define O_LARGEFILE 0
 #endif
 
-#ifndef W_STOPCODE
-#define W_STOPCODE(sig) ((sig) << 8 | 0x7f)
-#endif
-
-/* This is the kernel's hard limit.  Not to be confused with
-   SIGRTMIN.  */
-#ifndef __SIGRTMIN
-#define __SIGRTMIN 32
-#endif
-
 /* Some targets did not define these ptrace constants from the start,
    so gdbserver defines them locally here.  In the future, these may
    be removed after they are added to asm/ptrace.h.  */
@@ -457,6 +447,8 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
   struct thread_info *event_thr = get_lwp_thread (event_lwp);
   struct lwp_info *new_lwp;
 
+  gdb_assert (event_lwp->waitstatus.kind == TARGET_WAITKIND_IGNORE);
+
   if ((event == PTRACE_EVENT_FORK) || (event == PTRACE_EVENT_VFORK)
       || (event == PTRACE_EVENT_CLONE))
     {
@@ -587,6 +579,12 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
          new_lwp->status_pending_p = 1;
          new_lwp->status_pending = status;
        }
+      else if (report_thread_events)
+       {
+         new_lwp->waitstatus.kind = TARGET_WAITKIND_THREAD_CREATED;
+         new_lwp->status_pending_p = 1;
+         new_lwp->status_pending = status;
+       }
 
       /* Don't report the event.  */
       return 1;
@@ -1039,12 +1037,16 @@ attach_proc_task_lwp_callback (ptid_t ptid)
   return 0;
 }
 
+static void async_file_mark (void);
+
 /* Attach to PID.  If PID is the tgid, attach to it and all
    of its threads.  */
 
 static int
 linux_attach (unsigned long pid)
 {
+  struct process_info *proc;
+  struct thread_info *initial_thread;
   ptid_t ptid = ptid_build (pid, pid, 0);
   int err;
 
@@ -1055,17 +1057,12 @@ 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);
 
-  if (!non_stop)
-    {
-      struct thread_info *thread;
-
-     /* Don't ignore the initial SIGSTOP if we just attached to this
-       process.  It will be collected by wait shortly.  */
-      thread = find_thread_ptid (ptid_build (pid, pid, 0));
-      thread->last_resume_kind = resume_stop;
-    }
+  /* Don't ignore the initial SIGSTOP if we just attached to this
+     process.  It will be collected by wait shortly.  */
+  initial_thread = find_thread_ptid (ptid_build (pid, pid, 0));
+  initial_thread->last_resume_kind = resume_stop;
 
   /* We must attach to every LWP.  If /proc is mounted, use that to
      find them now.  On the one hand, the inferior may be using raw
@@ -1077,6 +1074,38 @@ linux_attach (unsigned long pid)
      that once thread_db is loaded, we'll still use it to list threads
      and associate pthread info with each LWP.  */
   linux_proc_attach_tgid_threads (pid, attach_proc_task_lwp_callback);
+
+  /* GDB will shortly read the xml target description for this
+     process, to figure out the process' architecture.  But the target
+     description is only filled in when the first process/thread in
+     the thread group reports its initial PTRACE_ATTACH SIGSTOP.  Do
+     that now, otherwise, if GDB is fast enough, it could read the
+     target description _before_ that initial stop.  */
+  if (non_stop)
+    {
+      struct lwp_info *lwp;
+      int wstat, lwpid;
+      ptid_t pid_ptid = pid_to_ptid (pid);
+
+      lwpid = linux_wait_for_event_filtered (pid_ptid, pid_ptid,
+                                            &wstat, __WALL);
+      gdb_assert (lwpid > 0);
+
+      lwp = find_lwp_pid (pid_to_ptid (lwpid));
+
+      if (!WIFSTOPPED (wstat) || WSTOPSIG (wstat) != SIGSTOP)
+       {
+         lwp->status_pending_p = 1;
+         lwp->status_pending = wstat;
+       }
+
+      initial_thread->last_resume_kind = resume_continue;
+
+      async_file_mark ();
+
+      gdb_assert (proc->tdesc != NULL);
+    }
+
   return 0;
 }
 
@@ -1496,12 +1525,6 @@ thread_still_has_status_pending_p (struct thread_info *thread)
   if (!lp->status_pending_p)
     return 0;
 
-  /* If we got a `vCont;t', but we haven't reported a stop yet, do
-     report any status pending the LWP may have.  */
-  if (thread->last_resume_kind == resume_stop
-      && thread->last_status.kind != TARGET_WAITKIND_IGNORE)
-    return 0;
-
   if (thread->last_resume_kind != resume_stop
       && (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
          || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT))
@@ -1558,6 +1581,26 @@ thread_still_has_status_pending_p (struct thread_info *thread)
   return 1;
 }
 
+/* Returns true if LWP is resumed from the client's perspective.  */
+
+static int
+lwp_resumed (struct lwp_info *lwp)
+{
+  struct thread_info *thread = get_lwp_thread (lwp);
+
+  if (thread->last_resume_kind != resume_stop)
+    return 1;
+
+  /* Did gdb send us a `vCont;t', but we haven't reported the
+     corresponding stop to gdb yet?  If so, the thread is still
+     resumed/running from gdb's perspective.  */
+  if (thread->last_resume_kind == resume_stop
+      && thread->last_status.kind == TARGET_WAITKIND_IGNORE)
+    return 1;
+
+  return 0;
+}
+
 /* Return 1 if this lwp has an interesting status pending.  */
 static int
 status_pending_p_callback (struct inferior_list_entry *entry, void *arg)
@@ -1571,6 +1614,9 @@ status_pending_p_callback (struct inferior_list_entry *entry, void *arg)
   if (!ptid_match (ptid_of (thread), ptid))
     return 0;
 
+  if (!lwp_resumed (lp))
+    return 0;
+
   if (lp->status_pending_p
       && !thread_still_has_status_pending_p (thread))
     {
@@ -2235,25 +2281,22 @@ linux_low_filter_event (int lwpid, int wstat)
     {
       if (debug_threads)
        debug_printf ("LLFE: %d exited.\n", lwpid);
-      if (num_lwps (pid_of (thread)) > 1)
+      /* If there is at least one more LWP, then the exit signal was
+        not the end of the debugged application and should be
+        ignored, unless GDB wants to hear about thread exits.  */
+      if (report_thread_events
+         || last_thread_of_process_p (pid_of (thread)))
        {
-
-         /* If there is at least one more LWP, then the exit signal was
-            not the end of the debugged application and should be
-            ignored.  */
-         delete_lwp (child);
-         return NULL;
+         /* Since events are serialized to GDB core, and we can't
+            report this one right now.  Leave the status pending for
+            the next time we're able to report it.  */
+         mark_lwp_dead (child, wstat);
+         return child;
        }
       else
        {
-         /* This was the last lwp in the process.  Since events are
-            serialized to GDB core, and we can't report this one
-            right now, but GDB core and the other target layers will
-            want to be notified about the exit code/signal, leave the
-            status pending for the next time we're able to report
-            it.  */
-         mark_lwp_dead (child, wstat);
-         return child;
+         delete_lwp (child);
+         return NULL;
        }
     }
 
@@ -2388,7 +2431,6 @@ resume_stopped_resumed_lwps (struct inferior_list_entry *entry)
   if (lp->stopped
       && !lp->suspended
       && !lp->status_pending_p
-      && thread->last_resume_kind != resume_stop
       && thread->last_status.kind == TARGET_WAITKIND_IGNORE)
     {
       int step = thread->last_resume_kind == resume_step;
@@ -2597,18 +2639,6 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
 
   current_thread = event_thread;
 
-  /* Check for thread exit.  */
-  if (! WIFSTOPPED (*wstatp))
-    {
-      gdb_assert (last_thread_of_process_p (pid_of (event_thread)));
-
-      if (debug_threads)
-       debug_printf ("LWP %d is the last lwp of process.  "
-                     "Process %ld exiting.\n",
-                     pid_of (event_thread), lwpid_of (event_thread));
-      return lwpid_of (event_thread);
-    }
-
   return lwpid_of (event_thread);
 }
 
@@ -2878,8 +2908,6 @@ linux_stabilize_threads (void)
     }
 }
 
-static void async_file_mark (void);
-
 /* Convenience function that is called when the kernel reports an
    event that is not passed out to GDB.  */
 
@@ -2895,6 +2923,30 @@ ignore_event (struct target_waitstatus *ourstatus)
   return null_ptid;
 }
 
+/* Convenience function that is called when the kernel reports an exit
+   event.  This decides whether to report the event to GDB as a
+   process exit event, a thread exit event, or to suppress the
+   event.  */
+
+static ptid_t
+filter_exit_event (struct lwp_info *event_child,
+                  struct target_waitstatus *ourstatus)
+{
+  struct thread_info *thread = get_lwp_thread (event_child);
+  ptid_t ptid = ptid_of (thread);
+
+  if (!last_thread_of_process_p (pid_of (thread)))
+    {
+      if (report_thread_events)
+       ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
+      else
+       ourstatus->kind = TARGET_WAITKIND_IGNORE;
+
+      delete_lwp (event_child);
+    }
+  return ptid;
+}
+
 /* Wait for process, returns status.  */
 
 static ptid_t
@@ -3000,6 +3052,9 @@ linux_wait_1 (ptid_t ptid,
            }
        }
 
+      if (ourstatus->kind == TARGET_WAITKIND_EXITED)
+       return filter_exit_event (event_child, ourstatus);
+
       return ptid_of (current_thread);
     }
 
@@ -3012,7 +3067,12 @@ linux_wait_1 (ptid_t ptid,
   if (!ptid_equal (step_over_bkpt, null_ptid)
       && event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT)
     {
-      unsigned int increment_pc = the_low_target.breakpoint_len;
+      int increment_pc = 0;
+      int breakpoint_kind = 0;
+      CORE_ADDR stop_pc = event_child->stop_pc;
+
+      breakpoint_kind = the_target->breakpoint_kind_from_pc (&stop_pc);
+      the_target->sw_breakpoint_from_kind (breakpoint_kind, &increment_pc);
 
       if (debug_threads)
        {
@@ -3484,6 +3544,9 @@ linux_wait_1 (ptid_t ptid,
       debug_exit ();
     }
 
+  if (ourstatus->kind == TARGET_WAITKIND_EXITED)
+    return filter_exit_event (event_child, ourstatus);
+
   return ptid_of (current_thread);
 }
 
@@ -3884,6 +3947,8 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
   if (lwp->stopped == 0)
     return;
 
+  gdb_assert (lwp->waitstatus.kind == TARGET_WAITKIND_IGNORE);
+
   fast_tp_collecting = lwp->collecting_fast_tracepoint;
 
   gdb_assert (!stabilizing_threads || fast_tp_collecting);
@@ -6133,10 +6198,10 @@ linux_read_loadmap (const char *annex, CORE_ADDR offset,
 #endif /* defined PT_GETDSBT || defined PTRACE_GETFDPIC */
 
 static void
-linux_process_qsupported (const char *query)
+linux_process_qsupported (char **features, int count)
 {
   if (the_low_target.process_qsupported != NULL)
-    the_low_target.process_qsupported (query);
+    the_low_target.process_qsupported (features, count);
 }
 
 static int
@@ -6820,7 +6885,7 @@ linux_low_encode_raw (struct buffer *buffer, const gdb_byte *data,
 
 static int
 linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
-                      int type)
+                      enum btrace_read_type type)
 {
   struct btrace_data btrace;
   struct btrace_block *block;
@@ -6932,6 +6997,27 @@ current_lwp_ptid (void)
   return ptid_of (current_thread);
 }
 
+/* Implementation of the target_ops method "breakpoint_kind_from_pc".  */
+
+static int
+linux_breakpoint_kind_from_pc (CORE_ADDR *pcptr)
+{
+  if (the_low_target.breakpoint_kind_from_pc != NULL)
+    return (*the_low_target.breakpoint_kind_from_pc) (pcptr);
+  else
+    return default_breakpoint_kind_from_pc (pcptr);
+}
+
+/* Implementation of the target_ops method "sw_breakpoint_from_kind".  */
+
+static const gdb_byte *
+linux_sw_breakpoint_from_kind (int kind, int *size)
+{
+  gdb_assert (the_low_target.sw_breakpoint_from_kind != NULL);
+
+  return (*the_low_target.sw_breakpoint_from_kind) (kind, size);
+}
+
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_arch_setup,
@@ -7026,6 +7112,9 @@ static struct target_ops linux_target_ops = {
   linux_mntns_open_cloexec,
   linux_mntns_unlink,
   linux_mntns_readlink,
+  linux_breakpoint_kind_from_pc,
+  linux_sw_breakpoint_from_kind,
+  linux_proc_tid_get_name,
 };
 
 static void
@@ -7053,10 +7142,10 @@ void
 initialize_low (void)
 {
   struct sigaction sigchld_action;
+
   memset (&sigchld_action, 0, sizeof (sigchld_action));
   set_target_ops (&linux_target_ops);
-  set_breakpoint_data (the_low_target.breakpoint,
-                      the_low_target.breakpoint_len);
+
   linux_init_signals ();
   linux_ptrace_init_warnings ();
 
This page took 0.027173 seconds and 4 git commands to generate.