* elfcore.h: Add support for core files with multiple threads.
[deliverable/binutils-gdb.git] / bfd / elfcore.h
index 51dfec526f4b3b6ba2fb39b8fe61c7c564910fa2..ab8b79fe132b017822b6b47c52ce4496eb30d2ca 100644 (file)
@@ -1,28 +1,71 @@
+/* ELF core file support for BFD.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 /* Core file support */
 
-#ifdef HAVE_PROCFS             /* Some core file support requires host /proc files */
+#ifdef HAVE_SYS_PROCFS_H               /* Some core file support requires host /proc files */
+#include <signal.h>
 #include <sys/procfs.h>
+
+/* Solaris includes the field pr_who that indicates the thread number within
+   the process.  */
+
+#ifdef PIOCOPENLWP
+#define get_thread(STATUS) ((((prstatus_t *)(STATUS))->pr_who << 16) \
+                           | ((prstatus_t *)(STATUS))->pr_pid)
+#else
+#define get_thread(STATUS) (((prstatus_t *)(STATUS))->pr_pid)
+#endif
 #else
 #define bfd_prstatus(abfd, descdata, descsz, filepos) true
 #define bfd_fpregset(abfd, descdata, descsz, filepos) true
 #define bfd_prpsinfo(abfd, descdata, descsz, filepos) true
+#define get_thread(STATUS) (1)
 #endif
 
-#ifdef HAVE_PROCFS
+#ifdef HAVE_SYS_PROCFS_H
+
+static int did_reg;
+static int did_reg2;
 
 static boolean
-bfd_prstatus (abfd, descdata, descsz, filepos)
+bfd_prstatus (abfd, descdata, descsz, filepos, thread)
      bfd *abfd;
      char *descdata;
      int descsz;
      long filepos;
+     int thread;
 {
   asection *newsect;
   prstatus_t *status = (prstatus_t *) 0;
 
   if (descsz == sizeof (prstatus_t))
     {
-      newsect = bfd_make_section (abfd, ".reg");
+      char secname[100];
+      char *p;
+
+      sprintf (secname, ".reg/%d", thread);
+      p = bfd_alloc (abfd, strlen (secname) + 1);
+      if (!p)
+       return false;
+      strcpy (p, secname);
+      
+      newsect = bfd_make_section (abfd, p);
       if (newsect == NULL)
        return false;
       newsect->_raw_size = sizeof (status->pr_reg);
@@ -33,6 +76,19 @@ bfd_prstatus (abfd, descdata, descsz, filepos)
        {
          memcpy (core_prstatus (abfd), descdata, descsz);
        }
+
+      if (!did_reg++)
+       {
+         asection *regsect;
+
+         regsect = bfd_make_section (abfd, ".reg");
+         if (regsect == NULL)
+           return false;
+         regsect->_raw_size = newsect->_raw_size;
+         regsect->filepos = newsect->filepos;
+         regsect->flags = newsect->flags;
+         regsect->alignment_power = newsect->alignment_power;
+       }
     }
   return true;
 }
@@ -49,35 +105,55 @@ bfd_prpsinfo (abfd, descdata, descsz, filepos)
   if (descsz == sizeof (prpsinfo_t))
     {
       if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       memcpy (core_prpsinfo (abfd), descdata, descsz);
     }
   return true;
 }
 
 static boolean
-bfd_fpregset (abfd, descdata, descsz, filepos)
+bfd_fpregset (abfd, descdata, descsz, filepos, thread)
      bfd *abfd;
      char *descdata;
      int descsz;
      long filepos;
+     int thread;
 {
   asection *newsect;
+  char secname[100];
+  char *p;
+
+  sprintf (secname, ".reg2/%d", thread);
+  p = bfd_alloc (abfd, strlen (secname) + 1);
+  if (!p)
+    return false;
+  strcpy (p, secname);
 
-  newsect = bfd_make_section (abfd, ".reg2");
+  newsect = bfd_make_section (abfd, p);
   if (newsect == NULL)
     return false;
   newsect->_raw_size = descsz;
   newsect->filepos = filepos;
   newsect->flags = SEC_HAS_CONTENTS;
   newsect->alignment_power = 2;
+
+  if (!did_reg2++)
+    {
+      asection *regsect;
+
+      regsect = bfd_make_section (abfd, ".reg2");
+      if (regsect == NULL)
+       return false;
+      regsect->_raw_size = newsect->_raw_size;
+      regsect->filepos = newsect->filepos;
+      regsect->flags = newsect->flags;
+      regsect->alignment_power = newsect->alignment_power;
+    }
+
   return true;
 }
 
-#endif /* HAVE_PROCFS */
+#endif /* HAVE_SYS_PROCFS_H */
 
 /* Return a pointer to the args (including the command name) that were
    seen by the program that generated the core dump.  Note that for
@@ -89,7 +165,7 @@ char *
 elf_core_file_failing_command (abfd)
      bfd *abfd;
 {
-#ifdef HAVE_PROCFS
+#ifdef HAVE_SYS_PROCFS_H
   if (core_prpsinfo (abfd))
     {
       prpsinfo_t *p = core_prpsinfo (abfd);
@@ -117,7 +193,7 @@ int
 elf_core_file_failing_signal (abfd)
      bfd *abfd;
 {
-#ifdef HAVE_PROCFS
+#ifdef HAVE_SYS_PROCFS_H
   if (core_prstatus (abfd))
     {
       return ((prstatus_t *) (core_prstatus (abfd)))->pr_cursig;
@@ -137,7 +213,7 @@ elf_core_file_matches_executable_p (core_bfd, exec_bfd)
      bfd *core_bfd;
      bfd *exec_bfd;
 {
-#ifdef HAVE_PROCFS
+#ifdef HAVE_SYS_PROCFS_H
   char *corename;
   char *execname;
 #endif
@@ -150,7 +226,7 @@ elf_core_file_matches_executable_p (core_bfd, exec_bfd)
       return false;
     }
 
-#ifdef HAVE_PROCFS
+#ifdef HAVE_SYS_PROCFS_H
 
   /* If no prpsinfo, just return true.  Otherwise, grab the last component
      of the exec'd pathname from the prpsinfo. */
@@ -183,7 +259,7 @@ elf_core_file_matches_executable_p (core_bfd, exec_bfd)
 
   return true;
 
-#endif /* HAVE_PROCFS */
+#endif /* HAVE_SYS_PROCFS_H */
 }
 
 /* ELF core files contain a segment of type PT_NOTE, that holds much of
@@ -200,11 +276,11 @@ elf_core_file_matches_executable_p (core_bfd, exec_bfd)
    the bfd client will have to interpret the structures itself.  Even with
    /proc support, it might want these full structures for it's own reasons.
 
-   In the second level of support, where HAVE_PROCFS is defined, bfd will
-   pick apart the structures to gather some additional information that
-   clients may want, such as the general register set, the name of the
-   exec'ed file and its arguments, the signal (if any) that caused the
-   core dump, etc.
+   In the second level of support, where HAVE_SYS_PROCFS_H is defined,
+   bfd will pick apart the structures to gather some additional
+   information that clients may want, such as the general register
+   set, the name of the exec'ed file and its arguments, the signal (if
+   any) that caused the core dump, etc.
 
    */
 
@@ -221,9 +297,13 @@ elf_corefile_note (abfd, hdr)
   char *sectname;              /* Name to use for new section */
   long filepos;                        /* File offset to descriptor data */
   asection *newsect;
+  int thread = 1;              /* Current thread number */
+
+  did_reg = 0;                 /* Non-zero if we made .reg section */
+  did_reg2 = 0;                        /* Ditto for .reg2 */
 
   if (hdr->p_filesz > 0
-      && (buf = (char *) malloc (hdr->p_filesz)) != NULL
+      && (buf = (char *) bfd_malloc ((size_t) hdr->p_filesz)) != NULL
       && bfd_seek (abfd, hdr->p_offset, SEEK_SET) != -1
       && bfd_read ((PTR) buf, hdr->p_filesz, 1, abfd) == hdr->p_filesz)
     {
@@ -240,15 +320,18 @@ elf_corefile_note (abfd, hdr)
            {
            case NT_PRSTATUS:
              /* process descdata as prstatus info */
-             if (! bfd_prstatus (abfd, descdata, i_note.descsz, filepos))
+             thread = get_thread (descdata);
+             if (! bfd_prstatus (abfd, descdata, i_note.descsz, filepos,
+                                 thread))
                return false;
-             sectname = ".prstatus";
+             sectname = NULL;
              break;
            case NT_FPREGSET:
              /* process descdata as fpregset info */
-             if (! bfd_fpregset (abfd, descdata, i_note.descsz, filepos))
+             if (! bfd_fpregset (abfd, descdata, i_note.descsz, filepos,
+                                 thread))
                return false;
-             sectname = ".fpregset";
+             sectname = NULL;
              break;
            case NT_PRPSINFO:
              /* process descdata as prpsinfo */
@@ -281,7 +364,6 @@ elf_corefile_note (abfd, hdr)
     }
   else if (hdr->p_filesz > 0)
     {
-      bfd_set_error (bfd_error_no_memory);
       return false;
     }
   return true;
@@ -352,11 +434,11 @@ elf_core_file_p (abfd)
   switch (x_ehdr.e_ident[EI_DATA])
     {
     case ELFDATA2MSB:          /* Big-endian */
-      if (abfd->xvec->byteorder_big_p == false)
+      if (! bfd_big_endian (abfd))
        goto wrong;
       break;
     case ELFDATA2LSB:          /* Little-endian */
-      if (abfd->xvec->byteorder_big_p == true)
+      if (! bfd_little_endian (abfd))
        goto wrong;
       break;
     case ELFDATANONE:          /* No data encoding specified */
@@ -370,10 +452,7 @@ elf_core_file_p (abfd)
   elf_tdata (abfd) =
     (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
   if (elf_tdata (abfd) == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
 
   /* FIXME, `wrong' returns from this point onward, leak memory.  */
 
@@ -431,10 +510,7 @@ elf_core_file_p (abfd)
   i_phdrp = (Elf_Internal_Phdr *)
     bfd_alloc (abfd, sizeof (*i_phdrp) * i_ehdrp->e_phnum);
   if (!i_phdrp)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
   if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1)
     return NULL;
   for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
This page took 0.02764 seconds and 4 git commands to generate.