Back to index

cell-binutils  2.17cvs20070401
aix5ppc-core.c
Go to the documentation of this file.
00001 /* IBM RS/6000 "XCOFF" back-end for BFD.
00002    Copyright 2001, 2002, 2003, 2004, 2005, 2006
00003    Free Software Foundation, Inc.
00004    Written by Tom Rix
00005    Contributed by Red Hat Inc.
00006 
00007    This file is part of BFD, the Binary File Descriptor library.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00022    MA 02110-1301, USA.  */
00023 
00024 #include "bfd.h"
00025 
00026 const bfd_target *xcoff64_core_p (bfd *);
00027 bfd_boolean xcoff64_core_file_matches_executable_p (bfd *, bfd *);
00028 char *xcoff64_core_file_failing_command (bfd *);
00029 int xcoff64_core_file_failing_signal (bfd *);
00030 
00031 #ifdef AIX_5_CORE
00032 
00033 #include "sysdep.h"
00034 #include "libbfd.h"
00035 
00036 /* Aix 5.1 system include file.  */
00037 
00038 /* Need to define this macro so struct ld_info64 get included.  */
00039 #define __LDINFO_PTRACE64__
00040 #include <sys/ldr.h>
00041 #include <core.h>
00042 
00043 #define       core_hdr(abfd)              ((struct core_dumpxx *) abfd->tdata.any)
00044 
00045 #define CHECK_FILE_OFFSET(s, v) \
00046   ((bfd_signed_vma)(v) < 0 || (bfd_signed_vma)(v) > (bfd_signed_vma)(s).st_size)
00047 
00048 const bfd_target *
00049 xcoff64_core_p (bfd *abfd)
00050 {
00051   struct core_dumpxx core, *new_core_hdr;
00052   struct stat statbuf;
00053   asection *sec;
00054   struct __ld_info64 ldinfo;
00055   bfd_vma ld_offset;
00056   bfd_size_type i;
00057   struct vm_infox vminfo;
00058   const bfd_target *return_value = NULL;
00059   flagword flags;
00060 
00061   /* Get the header.  */
00062   if (bfd_seek (abfd, 0, SEEK_SET) != 0)
00063     goto xcoff64_core_p_error;
00064 
00065   if (sizeof (struct core_dumpxx)
00066       != bfd_bread (&core, sizeof (struct core_dumpxx), abfd))
00067     goto xcoff64_core_p_error;
00068 
00069   if (bfd_stat (abfd, &statbuf) < 0)
00070     goto xcoff64_core_p_error;
00071 
00072   /* Sanity checks
00073      c_flag has CORE_VERSION_1, Aix 4+
00074      c_entries = 0 for Aix 4.3+
00075      IS_PROC64 is a macro defined in procinfo.h, test for 64 bit process.
00076 
00077      We will still be confused if a Aix 4.3 64 bit core file is
00078      copied over to a Aix 5 machine.
00079 
00080      Check file header offsets
00081 
00082      See rs6000-core.c for comment on size of core
00083      If there isn't enough of a real core file, bail.  */
00084 
00085   if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1))
00086       || (0 != core.c_entries)
00087       || (! (IS_PROC64 (&core.c_u.U_proc)))
00088       || ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox)))
00089       || ((CHECK_FILE_OFFSET (statbuf, core.c_loader)))
00090       || ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize)))
00091       || ((CHECK_FILE_OFFSET (statbuf, core.c_thr)))
00092       || ((CHECK_FILE_OFFSET (statbuf, core.c_segregion)))
00093       || ((CHECK_FILE_OFFSET (statbuf, core.c_stack)))
00094       || ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size)))
00095       || ((CHECK_FILE_OFFSET (statbuf, core.c_data)))
00096       || ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize)))
00097       || (! (core.c_flag & UBLOCK_VALID))
00098       || (! (core.c_flag & LE_VALID)))
00099     goto xcoff64_core_p_error;
00100 
00101   /* Check for truncated stack or general truncating.  */
00102   if ((! (core.c_flag & USTACK_VALID))
00103       || (core.c_flag & CORE_TRUNC))
00104     {
00105       bfd_set_error (bfd_error_file_truncated);
00106 
00107       return return_value;
00108     }
00109 
00110   new_core_hdr = bfd_zalloc (abfd, sizeof (struct core_dumpxx));
00111   if (NULL == new_core_hdr)
00112     return return_value;
00113 
00114   memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx));
00115   /* The core_hdr() macro is no longer used here because it would
00116      expand to code relying on gcc's cast-as-lvalue extension,
00117      which was removed in gcc 4.0.  */
00118   abfd->tdata.any = new_core_hdr;
00119 
00120   /* .stack section.  */
00121   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
00122   sec = bfd_make_section_anyway_with_flags (abfd, ".stack", flags);
00123   if (NULL == sec)
00124     return return_value;
00125 
00126   sec->size = core.c_size;
00127   sec->vma = core.c_stackorg;
00128   sec->filepos = core.c_stack;
00129 
00130   /* .reg section for all registers.  */
00131   flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
00132   sec = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
00133   if (NULL == sec)
00134     return return_value;
00135 
00136   sec->size = sizeof (struct __context64);
00137   sec->vma = 0;
00138   sec->filepos = 0;
00139   sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64;
00140 
00141   /* .ldinfo section.
00142      To actually find out how long this section is in this particular
00143      core dump would require going down the whole list of struct
00144      ld_info's.   See if we can just fake it.  */
00145   flags = SEC_HAS_CONTENTS;
00146   sec = bfd_make_section_anyway_with_flags (abfd, ".ldinfo", flags);
00147   if (NULL == sec)
00148     return return_value;
00149 
00150   sec->size = core.c_lsize;
00151   sec->vma = 0;
00152   sec->filepos = core.c_loader;
00153 
00154   /* AIX 4 adds data sections from loaded objects to the core file,
00155      which can be found by examining ldinfo, and anonymously mmapped
00156      regions.  */
00157 
00158   /* .data section from executable.  */
00159   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
00160   sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
00161   if (NULL == sec)
00162     return return_value;
00163 
00164   sec->size = core.c_datasize;
00165   sec->vma = core.c_dataorg;
00166   sec->filepos = core.c_data;
00167 
00168   /* .data sections from loaded objects.  */
00169   ld_offset = core.c_loader;
00170 
00171   while (1)
00172     {
00173       if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0)
00174        return return_value;
00175 
00176       if (sizeof (struct __ld_info64) !=
00177          bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd))
00178        return return_value;
00179 
00180       if (ldinfo.ldinfo_core)
00181        {
00182          flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
00183          sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
00184          if (NULL == sec)
00185            return return_value;
00186 
00187          sec->size = ldinfo.ldinfo_datasize;
00188          sec->vma = ldinfo.ldinfo_dataorg;
00189          sec->filepos = ldinfo.ldinfo_core;
00190        }
00191 
00192       if (0 == ldinfo.ldinfo_next)
00193        break;
00194       ld_offset += ldinfo.ldinfo_next;
00195     }
00196 
00197   /* .vmdata sections from anonymously mmapped regions.  */
00198   if (core.c_vmregions)
00199     {
00200       if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0)
00201        return return_value;
00202 
00203       for (i = 0; i < core.c_vmregions; i++)
00204        if (sizeof (struct vm_infox) !=
00205            bfd_bread (&vminfo, sizeof (struct vm_infox), abfd))
00206          return return_value;
00207 
00208       if (vminfo.vminfo_offset)
00209        {
00210          flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
00211          sec = bfd_make_section_anyway_with_flags (abfd, ".vmdata", flags);
00212          if (NULL == sec)
00213            return return_value;
00214 
00215          sec->size = vminfo.vminfo_size;
00216          sec->vma = vminfo.vminfo_addr;
00217          sec->filepos = vminfo.vminfo_offset;
00218        }
00219     }
00220 
00221   return_value = (bfd_target *) abfd->xvec;      /* This is garbage for now.  */
00222 
00223  xcoff64_core_p_error:
00224   if (bfd_get_error () != bfd_error_system_call)
00225     bfd_set_error (bfd_error_wrong_format);
00226 
00227   return return_value;
00228 }
00229 
00230 /* Return `TRUE' if given core is from the given executable.  */
00231 
00232 bfd_boolean
00233 xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
00234 {
00235   struct core_dumpxx core;
00236   char *path, *s;
00237   size_t alloc;
00238   const char *str1, *str2;
00239   bfd_boolean return_value = FALSE;
00240 
00241   /* Get the header.  */
00242   if (bfd_seek (core_bfd, 0, SEEK_SET) != 0)
00243     return return_value;
00244 
00245   if (sizeof (struct core_dumpxx) !=
00246       bfd_bread (&core, sizeof (struct core_dumpxx), core_bfd))
00247     return return_value;
00248 
00249   if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0)
00250     return return_value;
00251 
00252   alloc = 100;
00253   path = bfd_malloc (alloc);
00254   if (path == NULL)
00255     return return_value;
00256 
00257   s = path;
00258 
00259   while (1)
00260     {
00261       if (bfd_bread (s, 1, core_bfd) != 1)
00262        goto xcoff64_core_file_matches_executable_p_end_1;
00263 
00264       if (*s == '\0')
00265        break;
00266       ++s;
00267       if (s == path + alloc)
00268        {
00269          char *n;
00270 
00271          alloc *= 2;
00272          n = bfd_realloc (path, alloc);
00273          if (n == NULL)
00274            goto xcoff64_core_file_matches_executable_p_end_1;
00275 
00276          s = n + (path - s);
00277          path = n;
00278        }
00279     }
00280 
00281   str1 = strrchr (path, '/');
00282   str2 = strrchr (exec_bfd->filename, '/');
00283 
00284   /* Step over character '/'.  */
00285   str1 = str1 != NULL ? str1 + 1 : path;
00286   str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
00287 
00288   if (strcmp (str1, str2) == 0)
00289     return_value = TRUE;
00290 
00291  xcoff64_core_file_matches_executable_p_end_1:
00292   free (path);
00293   return return_value;
00294 }
00295 
00296 char *
00297 xcoff64_core_file_failing_command (bfd *abfd)
00298 {
00299   struct core_dumpxx *c = core_hdr (abfd);
00300   char *return_value = 0;
00301 
00302   if (NULL != c)
00303     return_value = c->c_u.U_proc.pi_comm;
00304 
00305   return return_value;
00306 }
00307 
00308 int
00309 xcoff64_core_file_failing_signal (bfd *abfd)
00310 {
00311   struct core_dumpxx *c = core_hdr (abfd);
00312   int return_value = 0;
00313 
00314   if (NULL != c)
00315     return_value = c->c_signo;
00316 
00317   return return_value;
00318 }
00319 
00320 #else /* AIX_5_CORE */
00321 
00322 const bfd_target *
00323 xcoff64_core_p (bfd *abfd ATTRIBUTE_UNUSED)
00324 {
00325   bfd_set_error (bfd_error_wrong_format);
00326   return 0;
00327 }
00328 
00329 bfd_boolean
00330 xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
00331 {
00332   return generic_core_file_matches_executable_p (core_bfd, exec_bfd);
00333 }
00334 
00335 char *
00336 xcoff64_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
00337 {
00338   return 0;
00339 }
00340 
00341 int
00342 xcoff64_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
00343 {
00344   return 0;
00345 }
00346 
00347 #endif /* AIX_5_CORE */