dummy commit before egcs merge
[deliverable/binutils-gdb.git] / bfd / rs6000-core.c
index 8fb49783800970c457fb730cd4fe36f68121398f..270b5e782079b98ae38e864b234745fc41d438e4 100644 (file)
@@ -1,5 +1,5 @@
 /* IBM RS/6000 "XCOFF" back-end for BFD.
-   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
    FIXME: Can someone provide a transliteration of this name into ASCII?
    Using the following chars caused a compiler warning on HIUX (so I replaced
    them with octal escapes), and isn't useful without an understanding of what
@@ -23,7 +23,7 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* This port currently only handles reading object files, except when
    compiled on an RS/6000 host.  -- no archive support, no core files.
@@ -42,7 +42,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "sysdep.h"
 #include "libbfd.h"
 
-#ifdef HOST_AIX
+#ifdef AIX_CORE
 
 /* AOUTHDR is defined by the above.  We need another defn of it, from the
    system include files.  Punt the old one and get us a new name for the
@@ -69,7 +69,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    the macros in sys/reg.h.  FIXMEmgo. */
 
 #define        NUM_OF_SPEC_REGS  7
-#define        STACK_END_ADDR 0x2ff80000
 
 #define        core_hdr(bfd)           (((Rs6kCorData*)(bfd->tdata.any))->hdr)
 #define        core_datasec(bfd)       (((Rs6kCorData*)(bfd->tdata.any))->data_section)
@@ -77,9 +76,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define        core_regsec(bfd)        (((Rs6kCorData*)(bfd->tdata.any))->reg_section)
 #define        core_reg2sec(bfd)       (((Rs6kCorData*)(bfd->tdata.any))->reg2_section)
 
+/* AIX 4.1 Changed the names and locations of a few items in the core file,
+   this seems to be the quickest easiet way to deal with it. 
+
+   Note however that encoding magic addresses (STACK_END_ADDR) is going
+   to be _very_ fragile.  But I don't see any easy way to get that info
+   right now.  */
+#ifdef CORE_VERSION_1
+#define CORE_DATA_SIZE_FIELD c_u.U_dsize
+#define CORE_COMM_FIELD c_u.U_comm
+#define SAVE_FIELD c_mst
+#define        STACK_END_ADDR 0x2ff23000
+#else
+#define CORE_DATA_SIZE_FIELD c_u.u_dsize
+#define CORE_COMM_FIELD c_u.u_comm
+#define SAVE_FIELD c_u.u_save
+#define        STACK_END_ADDR 0x2ff80000
+#endif
+
 /* These are stored in the bfd's tdata */
 typedef struct {
-  struct core *hdr;            /* core file header */
+  struct core_dump hdr;                /* core file header */
   asection *data_section,
           *stack_section,
           *reg_section,        /* section for GPRs and special registers. */
@@ -95,7 +112,7 @@ typedef struct {
 /* Decide if a given bfd represents a `core' file or not. There really is no
    magic number or anything like, in rs6000coff. */
 
-bfd_target *
+const bfd_target *
 rs6000coff_core_p (abfd)
      bfd *abfd;
 {
@@ -108,27 +125,27 @@ rs6000coff_core_p (abfd)
   fd = open (abfd->filename, O_RDONLY);
   if (fd < 0)
     {
-      bfd_error = system_call_error;
+      bfd_set_error (bfd_error_system_call);
       return NULL;
     }
 
   if (fstat (fd, &statbuf) < 0)
     {
-      bfd_error = system_call_error;
+      bfd_set_error (bfd_error_system_call);
       close (fd);
       return NULL;
     }
   if (read (fd, &coredata, sizeof (struct core_dump))
       != sizeof (struct core_dump))
     {
-      bfd_error = wrong_format;
+      bfd_set_error (bfd_error_wrong_format);
       close (fd);
       return NULL;
     }
 
   if (close (fd) < 0)
     {
-      bfd_error = system_call_error;
+      bfd_set_error (bfd_error_system_call);
       return NULL;
     }
 
@@ -138,8 +155,7 @@ rs6000coff_core_p (abfd)
      are always set) (this is based on experimentation on AIX 3.2).
      Now, the thing is that GDB users will be surprised
      if segments just silently don't appear (well, maybe they would
-     think to check "info files", I don't know), but we have no way of
-     returning warnings (as opposed to errors).
+     think to check "info files", I don't know).
 
      For the data segment, we have no choice but to keep going if it's
      not there, since the default behavior is not to dump it (regardless
@@ -151,23 +167,23 @@ rs6000coff_core_p (abfd)
   if (!(coredata.c_flag & UBLOCK_VALID)
       || !(coredata.c_flag & LE_VALID))
     {
-      bfd_error = wrong_format;
+      bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
 
-  if ((coredata.c_flag & CORE_TRUNC)
-      || !(coredata.c_flag & USTACK_VALID))
+  if (!(coredata.c_flag & USTACK_VALID))
     {
-      bfd_error = file_truncated;
+      bfd_set_error (bfd_error_file_truncated);
       return NULL;
     }
 
-  if (((bfd_vma)coredata.c_stack + coredata.c_size
-       + ((coredata.c_flag & FULL_CORE) ? coredata.c_u.u_dsize : 0))
-      != statbuf.st_size)
+  /* Don't check the core file size for a full core, AIX 4.1 includes
+     additional shared library sections in a full core.  */
+  if (!(coredata.c_flag & (FULL_CORE | CORE_TRUNC))
+      && ((bfd_vma)coredata.c_stack + coredata.c_size) != statbuf.st_size)
     {
       /* If the size is wrong, it means we're misinterpreting something.  */
-      bfd_error = wrong_format;
+      bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
 
@@ -176,76 +192,69 @@ rs6000coff_core_p (abfd)
       (u_long) coredata.c_tab >= statbuf.st_size ||
       (long) coredata.c_tab >= (long)coredata.c_stack)
     {
-      bfd_error = wrong_format;
+      bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
 
+  /* Issue warning if the core file was truncated during writing.  */
+  if (coredata.c_flag & CORE_TRUNC)
+    (*_bfd_error_handler) ("%s: warning core file truncated",
+                          bfd_get_filename (abfd));
+
   /* maybe you should alloc space for the whole core chunk over here!! FIXMEmgo */
   tmpptr = (char*)bfd_zalloc (abfd, sizeof (Rs6kCorData));
   if (!tmpptr)
-    {
-      bfd_error = no_memory;
-      return NULL;
-    }
+    return NULL;
       
   set_tdata (abfd, tmpptr);
 
+  /* Copy core file header.  */
+  core_hdr (abfd) = coredata;
+
   /* .stack section. */
   if ((core_stacksec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
-       == NULL)  {
-    bfd_error = no_memory;
-    /* bfd_release (abfd, ???? ) */
+       == NULL)
     return NULL;
-  }
   core_stacksec (abfd)->name = ".stack";
-  core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
   core_stacksec (abfd)->_raw_size = coredata.c_size;
   core_stacksec (abfd)->vma = STACK_END_ADDR - coredata.c_size;
   core_stacksec (abfd)->filepos = (int)coredata.c_stack;       /*???? */
 
   /* .reg section for GPRs and special registers. */
   if ((core_regsec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
-       == NULL)  {
-    bfd_error = no_memory;
-    /* bfd_release (abfd, ???? ) */
+       == NULL)
     return NULL;
-  }
   core_regsec (abfd)->name = ".reg";
-  core_regsec (abfd)->flags = SEC_ALLOC;
+  core_regsec (abfd)->flags = SEC_HAS_CONTENTS;
   core_regsec (abfd)->_raw_size = (32 + NUM_OF_SPEC_REGS) * 4;
   core_regsec (abfd)->vma = 0;                 /* not used?? */
   core_regsec (abfd)->filepos = 
-       (char*)&coredata.c_u.u_save - (char*)&coredata;
+       (char*)&coredata.SAVE_FIELD - (char*)&coredata;
 
   /* .reg2 section for FPRs (floating point registers). */
   if ((core_reg2sec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
-       == NULL)  {
-    bfd_error = no_memory;
-    /* bfd_release (abfd, ???? ) */
+       == NULL)
     return NULL;
-  }
   core_reg2sec (abfd)->name = ".reg2";
-  core_reg2sec (abfd)->flags = SEC_ALLOC;
+  core_reg2sec (abfd)->flags = SEC_HAS_CONTENTS;
   core_reg2sec (abfd)->_raw_size = 8 * 32;                     /* 32 FPRs. */
   core_reg2sec (abfd)->vma = 0;                        /* not used?? */
   core_reg2sec (abfd)->filepos = 
-       (char*)&coredata.c_u.u_save.fpr[0] - (char*)&coredata;
+       (char*)&coredata.SAVE_FIELD.fpr[0] - (char*)&coredata;
 
   if ((core_ldinfosec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
-       == NULL)  {
-    bfd_error = no_memory;
-    /* bfd_release (abfd, ???? ) */
+       == NULL)
     return NULL;
-  }
   core_ldinfosec (abfd)->name = ".ldinfo";
-  core_ldinfosec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_ldinfosec (abfd)->flags = SEC_HAS_CONTENTS;
   /* To actually find out how long this section is in this particular
      core dump would require going down the whole list of struct ld_info's.
      See if we can just fake it.  */
   core_ldinfosec (abfd)->_raw_size = 0x7fffffff;
   /* Not relevant for ldinfo section.  */
   core_ldinfosec (abfd)->vma = 0;
-  core_ldinfosec (abfd)->filepos = coredata.c_tab;
+  core_ldinfosec (abfd)->filepos = (file_ptr) coredata.c_tab;
 
   /* set up section chain here. */
   abfd->section_count = 4;
@@ -259,14 +268,11 @@ rs6000coff_core_p (abfd)
     {
       asection *sec = (asection *) bfd_zalloc (abfd, sizeof (asection));
       if (sec == NULL)
-       {
-         bfd_error = no_memory;
-         return NULL;
-       }
+       return NULL;
       sec->name = ".data";
       sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
-      sec->_raw_size = coredata.c_u.u_dsize;
-      sec->vma = CDATA_ADDR (coredata.c_u.u_dsize);
+      sec->_raw_size = coredata.CORE_DATA_SIZE_FIELD;
+      sec->vma = CDATA_ADDR (coredata.CORE_DATA_SIZE_FIELD);
       sec->filepos = (int)coredata.c_stack + coredata.c_size;
 
       sec->next = abfd->sections;
@@ -285,33 +291,90 @@ rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd)
      bfd *core_bfd;
      bfd *exec_bfd;
 {
-  FILE *fd;
   struct core_dump coredata;
   struct ld_info ldinfo;
-  char pathname [1024];
-  char *str1, *str2;
-
-  /* Use bfd_xxx routines, rather than O/S primitives, do error checking!!
-                                                               FIXMEmgo */
-  /* Actually should be able to use bfd_get_section_contents now that
-     we have a .ldinfo section.  */
-  fd = fopen (core_bfd->filename, FOPEN_RB);
-
-  fread (&coredata, sizeof (struct core_dump), 1, fd);
-  fseek (fd, (long)coredata.c_tab, 0);
-  fread (&ldinfo, (char*)&ldinfo.ldinfo_filename[0] - (char*)&ldinfo.ldinfo_next,
-        1, fd);
-  fscanf (fd, "%s", pathname);
+  int size;
+  char *path, *s;
+  size_t alloc;
+  const char *str1, *str2;
+  boolean ret;
+
+  if (bfd_seek (core_bfd, 0, SEEK_SET) != 0
+      || bfd_read (&coredata, sizeof coredata, 1, core_bfd) != sizeof coredata)
+    return false;
+
+  if (bfd_seek (core_bfd, (long) coredata.c_tab, SEEK_SET) != 0)
+    return false;
+
+  size = (char *) &ldinfo.ldinfo_filename[0] - (char *) &ldinfo.ldinfo_next;
+  if (bfd_read (&ldinfo, size, 1, core_bfd) != size)
+    return false;
+
+  alloc = 100;
+  path = bfd_malloc (alloc);
+  if (path == NULL)
+    return false;
+  s = path;
+
+  while (1)
+    {
+      if (bfd_read (s, 1, 1, core_bfd) != 1)
+       {
+         free (path);
+         return false;
+       }
+      if (*s == '\0')
+       break;
+      ++s;
+      if (s == path + alloc)
+       {
+         char *n;
+
+         alloc *= 2;
+         n = bfd_realloc (path, alloc);
+         if (n == NULL)
+           {
+             free (path);
+             return false;
+           }
+         s = n + (path - s);
+         path = n;
+       }
+    }
   
-  str1 = strrchr (pathname, '/');
+  str1 = strrchr (path, '/');
   str2 = strrchr (exec_bfd->filename, '/');
 
   /* step over character '/' */
-  str1 = str1 ? str1+1 : &pathname[0];
-  str2 = str2 ? str2+1 : exec_bfd->filename;
+  str1 = str1 != NULL ? str1 + 1 : path;
+  str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
+
+  if (strcmp (str1, str2) == 0)
+    ret = true;
+  else
+    ret = false;
+
+  free (path);
+
+  return ret;
+}
 
-  fclose (fd);
-  return strcmp (str1, str2) == 0;
+char *
+rs6000coff_core_file_failing_command (abfd)
+     bfd *abfd;
+{
+  char *com = core_hdr (abfd).CORE_COMM_FIELD;
+  if (*com)
+    return com;
+  else
+    return 0;
+}
+
+int
+rs6000coff_core_file_failing_signal (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd).c_signo;
 }
 
 
@@ -338,7 +401,8 @@ rs6000coff_get_section_contents (abfd, section, location, offset, count)
       /* Assert that the only way this code will be executed is reading the
          whole section. */
       if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS)))
-        fprintf (stderr, "ERROR! in rs6000coff_get_section_contents()\n");
+        (*_bfd_error_handler)
+         ("ERROR! in rs6000coff_get_section_contents()\n");
 
       /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure
          in the core file. */
@@ -367,8 +431,8 @@ rs6000coff_get_section_contents (abfd, section, location, offset, count)
 
     /* else, use default bfd section content transfer. */
     else
-      return bfd_generic_get_section_contents 
+      return _bfd_generic_get_section_contents 
                        (abfd, section, location, offset, count);
 }
 
-#endif /* HOST_AIX */
+#endif /* AIX_CORE */
This page took 0.032058 seconds and 4 git commands to generate.