* linux-low.c (sys/dir.h, sys/user.h): Remove includes.
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-low.c
index e5cb5282da74f9731f92763734c9dcdea26e7e36..fe4cd97cc8e7a90fe80910ebde0e5d2bcbf8a84f 100644 (file)
@@ -23,9 +23,7 @@
 #include <sys/wait.h>
 #include <stdio.h>
 #include <sys/param.h>
-#include <sys/dir.h>
 #include <sys/ptrace.h>
-#include <sys/user.h>
 #include <signal.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
@@ -107,6 +105,11 @@ static int thread_db_active;
 
 static int must_set_ptrace_flags;
 
+/* This flag is true iff we've just created or attached to a new inferior
+   but it has not stopped yet.  As soon as it does, we need to call the
+   low target's arch_setup callback.  */
+static int new_inferior;
+
 static void linux_resume_one_process (struct inferior_list_entry *entry,
                                      int step, int signal, siginfo_t *info);
 static void linux_resume (struct thread_resume *resume_info);
@@ -126,7 +129,8 @@ struct pending_signals
 #define PTRACE_XFER_TYPE long
 
 #ifdef HAVE_LINUX_REGSETS
-static int use_regsets_p = 1;
+static char *disabled_regsets;
+static int num_regsets;
 #endif
 
 #define pid_of(proc) ((proc)->head.id)
@@ -143,7 +147,7 @@ handle_extended_wait (struct process_info *event_child, int wstat)
   if (event == PTRACE_EVENT_CLONE)
     {
       unsigned long new_pid;
-      int ret, status;
+      int ret, status = W_STOPCODE (SIGSTOP);
 
       ptrace (PTRACE_GETEVENTMSG, inferior_pid, 0, &new_pid);
 
@@ -291,6 +295,7 @@ linux_create_inferior (char *program, char **allargs)
   new_process = add_process (pid);
   add_thread (pid, new_process, pid);
   must_set_ptrace_flags = 1;
+  new_inferior = 1;
 
   return pid;
 }
@@ -304,14 +309,18 @@ linux_attach_lwp (unsigned long pid)
 
   if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
     {
-      fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
+      if (all_threads.head != NULL)
+       {
+         /* If we fail to attach to an LWP, just warn.  */
+         fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
+                  strerror (errno), errno);
+         fflush (stderr);
+         return;
+       }
+      else
+       /* If we fail to attach to a process, report an error.  */
+       error ("Cannot attach to process %ld: %s (%d)\n", pid,
               strerror (errno), errno);
-      fflush (stderr);
-
-      /* If we fail to attach to an LWP, just return.  */
-      if (all_threads.head == NULL)
-       _exit (0177);
-      return;
     }
 
   ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACECLONE);
@@ -346,6 +355,8 @@ linux_attach (unsigned long pid)
   process = (struct process_info *) find_inferior_id (&all_processes, pid);
   process->stop_expected = 0;
 
+  new_inferior = 1;
+
   return 0;
 }
 
@@ -396,6 +407,10 @@ linux_kill (void)
       /* Make sure it died.  The loop is most likely unnecessary.  */
       wstat = linux_wait_for_event (thread);
     } while (WIFSTOPPED (wstat));
+
+  clear_inferiors ();
+  free (all_processes.head);
+  all_processes.head = all_processes.tail = NULL;
 }
 
 static void
@@ -434,6 +449,8 @@ linux_detach (void)
   delete_all_breakpoints ();
   for_each_inferior (&all_threads, linux_detach_one_process);
   clear_inferiors ();
+  free (all_processes.head);
+  all_processes.head = all_processes.tail = NULL;
   return 0;
 }
 
@@ -606,6 +623,19 @@ retry:
 
   (*childp)->last_status = *wstatp;
 
+  /* 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.  */
+  if (new_inferior)
+    {
+      the_low_target.arch_setup ();
+#ifdef HAVE_LINUX_REGSETS
+      memset (disabled_regsets, 0, num_regsets);
+#endif
+      new_inferior = 0;
+    }
+
   if (debug_threads
       && WIFSTOPPED (*wstatp))
     {
@@ -1373,10 +1403,9 @@ fetch_register (int regno)
          goto error_exit;
        }
     }
-  if (the_low_target.left_pad_xfer
-      && register_size (regno) < sizeof (PTRACE_XFER_TYPE))
-    supply_register (regno, (buf + sizeof (PTRACE_XFER_TYPE)
-                            - register_size (regno)));
+
+  if (the_low_target.supply_ptrace_register)
+    the_low_target.supply_ptrace_register (regno, buf);
   else
     supply_register (regno, buf);
 
@@ -1420,12 +1449,12 @@ usr_store_inferior_registers (int regno)
             & - sizeof (PTRACE_XFER_TYPE);
       buf = alloca (size);
       memset (buf, 0, size);
-      if (the_low_target.left_pad_xfer
-         && register_size (regno) < sizeof (PTRACE_XFER_TYPE))
-       collect_register (regno, (buf + sizeof (PTRACE_XFER_TYPE)
-                                 - register_size (regno)));
+
+      if (the_low_target.collect_ptrace_register)
+       the_low_target.collect_ptrace_register (regno, buf);
       else
        collect_register (regno, buf);
+
       for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
        {
          errno = 0;
@@ -1469,7 +1498,7 @@ regsets_fetch_inferior_registers ()
       void *buf;
       int res;
 
-      if (regset->size == 0)
+      if (regset->size == 0 || disabled_regsets[regset - target_regsets])
        {
          regset ++;
          continue;
@@ -1481,18 +1510,10 @@ regsets_fetch_inferior_registers ()
        {
          if (errno == EIO)
            {
-             /* If we get EIO on the first regset, do not try regsets again.
-                If we get EIO on a later regset, disable that regset.  */
-             if (regset == target_regsets)
-               {
-                 use_regsets_p = 0;
-                 return -1;
-               }
-             else
-               {
-                 regset->size = 0;
-                 continue;
-               }
+             /* If we get EIO on a regset, do not try it again for
+                this process.  */
+             disabled_regsets[regset - target_regsets] = 1;
+             continue;
            }
          else
            {
@@ -1526,7 +1547,7 @@ regsets_store_inferior_registers ()
       void *buf;
       int res;
 
-      if (regset->size == 0)
+      if (regset->size == 0 || disabled_regsets[regset - target_regsets])
        {
          regset ++;
          continue;
@@ -1552,18 +1573,10 @@ regsets_store_inferior_registers ()
        {
          if (errno == EIO)
            {
-             /* If we get EIO on the first regset, do not try regsets again.
-                If we get EIO on a later regset, disable that regset.  */
-             if (regset == target_regsets)
-               {
-                 use_regsets_p = 0;
-                 return -1;
-               }
-             else
-               {
-                 regset->size = 0;
-                 continue;
-               }
+             /* If we get EIO on a regset, do not try it again for
+                this process.  */
+             disabled_regsets[regset - target_regsets] = 1;
+             continue;
            }
          else
            {
@@ -1589,11 +1602,8 @@ void
 linux_fetch_registers (int regno)
 {
 #ifdef HAVE_LINUX_REGSETS
-  if (use_regsets_p)
-    {
-      if (regsets_fetch_inferior_registers () == 0)
-       return;
-    }
+  if (regsets_fetch_inferior_registers () == 0)
+    return;
 #endif
 #ifdef HAVE_LINUX_USRREGS
   usr_fetch_inferior_registers (regno);
@@ -1604,11 +1614,8 @@ void
 linux_store_registers (int regno)
 {
 #ifdef HAVE_LINUX_REGSETS
-  if (use_regsets_p)
-    {
-      if (regsets_store_inferior_registers () == 0)
-       return;
-    }
+  if (regsets_store_inferior_registers () == 0)
+    return;
 #endif
 #ifdef HAVE_LINUX_USRREGS
   usr_store_inferior_registers (regno);
@@ -1695,7 +1702,6 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
   = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) / sizeof (PTRACE_XFER_TYPE);
   /* Allocate buffer of that many longwords.  */
   register PTRACE_XFER_TYPE *buffer = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
-  extern int errno;
 
   if (debug_threads)
     {
@@ -2006,12 +2012,6 @@ linux_read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p)
 }
 #endif
 
-static const char *
-linux_arch_string (void)
-{
-  return the_low_target.arch_string;
-}
-
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_attach,
@@ -2042,7 +2042,8 @@ static struct target_ops linux_target_ops = {
 #else
   NULL,
 #endif
-  linux_arch_string,
+  NULL,
+  hostio_last_error_from_errno,
 };
 
 static void
@@ -2060,7 +2061,11 @@ initialize_low (void)
   set_target_ops (&linux_target_ops);
   set_breakpoint_data (the_low_target.breakpoint,
                       the_low_target.breakpoint_len);
-  init_registers ();
   linux_init_signals ();
   linux_test_for_tracefork ();
+#ifdef HAVE_LINUX_REGSETS
+  for (num_regsets = 0; target_regsets[num_regsets].size >= 0; num_regsets++)
+    ;
+  disabled_regsets = malloc (num_regsets);
+#endif
 }
This page took 0.054394 seconds and 4 git commands to generate.