* elfcore.h: Add support for core files with multiple threads.
authorStu Grossman <grossman@cygnus>
Tue, 16 Apr 1996 23:39:54 +0000 (23:39 +0000)
committerStu Grossman <grossman@cygnus>
Tue, 16 Apr 1996 23:39:54 +0000 (23:39 +0000)
(Primarily for Solaris.)

bfd/ChangeLog
bfd/elfcore.h

index ad92c2c..d894d24 100644 (file)
@@ -1,3 +1,8 @@
+Tue Apr 16 16:36:38 1996  Stu Grossman  (grossman@lisa.cygnus.com)
+
+       * elfcore.h:  Add support for core files with multiple threads.
+       (Primarily for Solaris.)
+
 Tue Apr 16 13:44:08 1996  Ian Lance Taylor  <ian@cygnus.com>
 
        * aoutx.h (NAME(aout,squirt_out_relocs)): Don't do anything if
index e22faf7..ab8b79f 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF core file support for BFD.
-   Copyright  1995 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -21,27 +21,51 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #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_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);
@@ -52,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;
 }
@@ -75,21 +112,44 @@ bfd_prpsinfo (abfd, descdata, descsz, filepos)
 }
 
 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;
 
-  newsect = bfd_make_section (abfd, ".reg2");
+  sprintf (secname, ".reg2/%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 = 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;
 }
 
@@ -237,6 +297,10 @@ 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 *) bfd_malloc ((size_t) hdr->p_filesz)) != NULL
@@ -256,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 */