2010-07-13 Emmanuel Thomé <Emmanuel.Thome@gmail.com>
[binutils-gdb.git] / gdb / linux-nat.c
index 2c791dcdfe6e3c566a4fa8122af100e83ecb3c0a..93adfcd4e0df2c87927dd0b6f73be81c84ea3277 100644 (file)
@@ -368,6 +368,7 @@ static void
 add_to_pid_list (struct simple_pid_list **listp, int pid, int status)
 {
   struct simple_pid_list *new_pid = xmalloc (sizeof (struct simple_pid_list));
+
   new_pid->pid = pid;
   new_pid->status = status;
   new_pid->next = *listp;
@@ -383,6 +384,7 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *status)
     if ((*p)->pid == pid)
       {
        struct simple_pid_list *next = (*p)->next;
+
        *status = (*p)->status;
        xfree (*p);
        *p = next;
@@ -677,7 +679,7 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
         in the foreground, the user will not be able to ctrl-c to get
         back the terminal, effectively hanging the debug session.  */
       fprintf_filtered (gdb_stderr, _("\
-Can not resume the parent process over vfork in the foreground while \n\
+Can not resume the parent process over vfork in the foreground while\n\
 holding the child stopped.  Try \"set detach-on-fork\" or \
 \"set schedule-multiple\".\n"));
       return 1;
@@ -1646,6 +1648,7 @@ get_pending_status (struct lwp_info *lp, int *status)
   else if (non_stop && !is_executing (lp->ptid))
     {
       struct thread_info *tp = find_thread_ptid (lp->ptid);
+
       signo = tp->stop_signal;
     }
   else if (!non_stop)
@@ -1658,6 +1661,7 @@ get_pending_status (struct lwp_info *lp, int *status)
       if (GET_LWP (lp->ptid) == GET_LWP (last_ptid))
        {
          struct thread_info *tp = find_thread_ptid (lp->ptid);
+
          signo = tp->stop_signal;
        }
     }
@@ -3622,7 +3626,13 @@ retry:
     fprintf_unfiltered (gdb_stdlog, "LLW: exit\n");
 
   restore_child_signals_mask (&prev_mask);
-  lp->core = linux_nat_core_of_thread_1 (lp->ptid);
+
+  if (ourstatus->kind == TARGET_WAITKIND_EXITED
+      || ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
+    lp->core = -1;
+  else
+    lp->core = linux_nat_core_of_thread_1 (lp->ptid);
+
   return lp->ptid;
 }
 
@@ -3802,6 +3812,7 @@ linux_nat_kill (struct target_ops *ops)
   else
     {
       ptid_t ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
+
       /* Stop all threads before killing them, since ptrace requires
         that the thread is stopped to sucessfully PTRACE_KILL.  */
       iterate_over_lwps (ptid, stop_callback, NULL);
@@ -4123,8 +4134,6 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
                               char *note_data, int *note_size,
                               enum target_signal stop_signal)
 {
-  gdb_gregset_t gregs;
-  gdb_fpregset_t fpregs;
   unsigned long lwp = ptid_get_lwp (ptid);
   struct gdbarch *gdbarch = target_gdbarch;
   struct regcache *regcache = get_thread_arch_regcache (ptid, gdbarch);
@@ -4142,21 +4151,6 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
   core_regset_p = gdbarch_regset_from_core_section_p (gdbarch);
   sect_list = gdbarch_core_regset_sections (gdbarch);
 
-  if (core_regset_p
-      && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg",
-                                                    sizeof (gregs))) != NULL
-      && regset->collect_regset != NULL)
-    regset->collect_regset (regset, regcache, -1,
-                           &gregs, sizeof (gregs));
-  else
-    fill_gregset (regcache, &gregs, -1);
-
-  note_data = (char *) elfcore_write_prstatus (obfd,
-                                              note_data,
-                                              note_size,
-                                              lwp,
-                                              stop_signal, &gregs);
-
   /* The loop below uses the new struct core_regset_section, which stores
      the supported section names and sizes for the core file.  Note that
      note PRSTATUS needs to be treated specially.  But the other notes are
@@ -4164,12 +4158,6 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
   if (core_regset_p && sect_list != NULL)
     while (sect_list->sect_name != NULL)
       {
-       /* .reg was already handled above.  */
-       if (strcmp (sect_list->sect_name, ".reg") == 0)
-         {
-           sect_list++;
-           continue;
-         }
        regset = gdbarch_regset_from_core_section (gdbarch,
                                                   sect_list->sect_name,
                                                   sect_list->size);
@@ -4177,12 +4165,16 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
        gdb_regset = xmalloc (sect_list->size);
        regset->collect_regset (regset, regcache, -1,
                                gdb_regset, sect_list->size);
-       note_data = (char *) elfcore_write_register_note (obfd,
-                                                         note_data,
-                                                         note_size,
-                                                         sect_list->sect_name,
-                                                         gdb_regset,
-                                                         sect_list->size);
+
+       if (strcmp (sect_list->sect_name, ".reg") == 0)
+         note_data = (char *) elfcore_write_prstatus
+                               (obfd, note_data, note_size,
+                                lwp, stop_signal, gdb_regset);
+       else
+         note_data = (char *) elfcore_write_register_note
+                               (obfd, note_data, note_size,
+                                sect_list->sect_name, gdb_regset,
+                                sect_list->size);
        xfree (gdb_regset);
        sect_list++;
       }
@@ -4192,6 +4184,24 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
      the new support, the code below should be deleted.  */
   else
     {
+      gdb_gregset_t gregs;
+      gdb_fpregset_t fpregs;
+
+      if (core_regset_p
+         && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg",
+                                                        sizeof (gregs))) != NULL
+         && regset->collect_regset != NULL)
+       regset->collect_regset (regset, regcache, -1,
+                               &gregs, sizeof (gregs));
+      else
+       fill_gregset (regcache, &gregs, -1);
+
+      note_data = (char *) elfcore_write_prstatus (obfd,
+                                                  note_data,
+                                                  note_size,
+                                                  lwp,
+                                                  stop_signal, &gregs);
+
       if (core_regset_p
           && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",
                                                         sizeof (fpregs))) != NULL
@@ -4340,6 +4350,7 @@ static char *
 linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
 {
   struct linux_spu_corefile_data args;
+
   args.obfd = obfd;
   args.note_data = note_data;
   args.note_size = note_size;
@@ -4496,6 +4507,7 @@ linux_nat_info_proc_cmd (char *args, int from_tty)
       if ((procfile = fopen (fname1, "r")) != NULL)
        {
          struct cleanup *cleanup = make_cleanup_fclose (procfile);
+
           if (fgets (buffer, sizeof (buffer), procfile))
             printf_filtered ("cmdline = '%s'\n", buffer);
           else
@@ -4591,6 +4603,7 @@ linux_nat_info_proc_cmd (char *args, int from_tty)
       if ((procfile = fopen (fname1, "r")) != NULL)
        {
          struct cleanup *cleanup = make_cleanup_fclose (procfile);
+
          while (fgets (buffer, sizeof (buffer), procfile) != NULL)
            puts_filtered (buffer);
          do_cleanups (cleanup);
@@ -4921,8 +4934,8 @@ linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigse
 
 static LONGEST
 linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
-                    const char *annex, gdb_byte *readbuf,
-                    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+                      const char *annex, gdb_byte *readbuf,
+                      const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
 {
   /* We make the process list snapshot when the object starts to be
      read.  */
@@ -4934,6 +4947,45 @@ linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
 
   gdb_assert (object == TARGET_OBJECT_OSDATA);
 
+  if (!annex)
+    {
+      if (offset == 0)
+       {
+         if (len_avail != -1 && len_avail != 0)
+           obstack_free (&obstack, NULL);
+         len_avail = 0;
+         buf = NULL;
+         obstack_init (&obstack);
+         obstack_grow_str (&obstack, "<osdata type=\"types\">\n");
+
+         obstack_xml_printf (
+                             &obstack,
+                             "<item>"
+                             "<column name=\"Type\">processes</column>"
+                             "<column name=\"Description\">Listing of all processes</column>"
+                             "</item>");
+
+         obstack_grow_str0 (&obstack, "</osdata>\n");
+         buf = obstack_finish (&obstack);
+         len_avail = strlen (buf);
+       }
+
+      if (offset >= len_avail)
+       {
+         /* Done.  Get rid of the obstack.  */
+         obstack_free (&obstack, NULL);
+         buf = NULL;
+         len_avail = 0;
+         return 0;
+       }
+
+      if (len > len_avail - offset)
+       len = len_avail - offset;
+      memcpy (readbuf, buf + offset, len);
+
+      return len;
+    }
+
   if (strcmp (annex, "processes") != 0)
     return 0;
 
@@ -4942,7 +4994,7 @@ linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
   if (offset == 0)
     {
       if (len_avail != -1 && len_avail != 0)
-       obstack_free (&obstack, NULL);
+       obstack_free (&obstack, NULL);
       len_avail = 0;
       buf = NULL;
       obstack_init (&obstack);
@@ -4950,60 +5002,63 @@ linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
 
       dirp = opendir ("/proc");
       if (dirp)
-       {
-         struct dirent *dp;
-         while ((dp = readdir (dirp)) != NULL)
-           {
-             struct stat statbuf;
-             char procentry[sizeof ("/proc/4294967295")];
-
-             if (!isdigit (dp->d_name[0])
-                 || NAMELEN (dp) > sizeof ("4294967295") - 1)
-               continue;
-
-             sprintf (procentry, "/proc/%s", dp->d_name);
-             if (stat (procentry, &statbuf) == 0
-                 && S_ISDIR (statbuf.st_mode))
-               {
-                 char *pathname;
-                 FILE *f;
-                 char cmd[MAXPATHLEN + 1];
-                 struct passwd *entry;
-
-                 pathname = xstrprintf ("/proc/%s/cmdline", dp->d_name);
-                 entry = getpwuid (statbuf.st_uid);
-
-                 if ((f = fopen (pathname, "r")) != NULL)
-                   {
-                     size_t len = fread (cmd, 1, sizeof (cmd) - 1, f);
-                     if (len > 0)
-                       {
-                         int i;
-                         for (i = 0; i < len; i++)
-                           if (cmd[i] == '\0')
-                             cmd[i] = ' ';
-                         cmd[len] = '\0';
-
-                         obstack_xml_printf (
-                          &obstack,
-                          "<item>"
-                          "<column name=\"pid\">%s</column>"
-                          "<column name=\"user\">%s</column>"
-                          "<column name=\"command\">%s</column>"
-                          "</item>",
-                          dp->d_name,
-                          entry ? entry->pw_name : "?",
-                          cmd);
-                       }
-                     fclose (f);
-                   }
-
-                 xfree (pathname);
-               }
-           }
-
-         closedir (dirp);
-       }
+       {
+         struct dirent *dp;
+
+         while ((dp = readdir (dirp)) != NULL)
+           {
+             struct stat statbuf;
+             char procentry[sizeof ("/proc/4294967295")];
+
+             if (!isdigit (dp->d_name[0])
+                 || NAMELEN (dp) > sizeof ("4294967295") - 1)
+               continue;
+
+             sprintf (procentry, "/proc/%s", dp->d_name);
+             if (stat (procentry, &statbuf) == 0
+                 && S_ISDIR (statbuf.st_mode))
+               {
+                 char *pathname;
+                 FILE *f;
+                 char cmd[MAXPATHLEN + 1];
+                 struct passwd *entry;
+
+                 pathname = xstrprintf ("/proc/%s/cmdline", dp->d_name);
+                 entry = getpwuid (statbuf.st_uid);
+
+                 if ((f = fopen (pathname, "r")) != NULL)
+                   {
+                     size_t len = fread (cmd, 1, sizeof (cmd) - 1, f);
+
+                     if (len > 0)
+                       {
+                         int i;
+
+                         for (i = 0; i < len; i++)
+                           if (cmd[i] == '\0')
+                             cmd[i] = ' ';
+                         cmd[len] = '\0';
+
+                         obstack_xml_printf (
+                           &obstack,
+                           "<item>"
+                           "<column name=\"pid\">%s</column>"
+                           "<column name=\"user\">%s</column>"
+                           "<column name=\"command\">%s</column>"
+                           "</item>",
+                           dp->d_name,
+                           entry ? entry->pw_name : "?",
+                           cmd);
+                       }
+                     fclose (f);
+                   }
+
+                 xfree (pathname);
+               }
+           }
+
+         closedir (dirp);
+       }
 
       obstack_grow_str0 (&obstack, "</osdata>\n");
       buf = obstack_finish (&obstack);
@@ -5478,6 +5533,7 @@ linux_nat_core_of_thread_1 (ptid_t ptid)
   for (;;)
     {
       int n;
+
       content = xrealloc (content, content_read + 1024);
       n = fread (content + content_read, 1, 1024, f);
       content_read += n;
@@ -5491,15 +5547,21 @@ linux_nat_core_of_thread_1 (ptid_t ptid)
   make_cleanup (xfree, content);
 
   p = strchr (content, '(');
-  p = strchr (p, ')') + 2; /* skip ")" and a whitespace. */
+
+  /* Skip ")".  */
+  if (p != NULL)
+    p = strchr (p, ')');
+  if (p != NULL)
+    p++;
 
   /* If the first field after program name has index 0, then core number is
      the field with index 36.  There's no constant for that anywhere.  */
-  p = strtok_r (p, " ", &ts);
-  for (i = 0; i != 36; ++i)
+  if (p != NULL)
+    p = strtok_r (p, " ", &ts);
+  for (i = 0; p != NULL && i != 36; ++i)
     p = strtok_r (NULL, " ", &ts);
 
-  if (sscanf (p, "%d", &core) == 0)
+  if (p == NULL || sscanf (p, "%d", &core) == 0)
     core = -1;
 
   do_cleanups (back_to);
@@ -5513,6 +5575,7 @@ int
 linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid)
 {
   struct lwp_info *info = find_lwp_pid (ptid);
+
   if (info)
     return info->core;
   return -1;