Home | History | Annotate | Line # | Download | only in bfd
aix5ppc-core.c revision 1.1.1.6.2.1
      1 /* IBM RS/6000 "XCOFF" back-end for BFD.
      2    Copyright (C) 2001-2024 Free Software Foundation, Inc.
      3    Written by Tom Rix
      4    Contributed by Red Hat Inc.
      5 
      6    This file is part of BFD, the Binary File Descriptor library.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21    MA 02110-1301, USA.  */
     22 
     23 #include "sysdep.h"
     24 #include "bfd.h"
     25 
     26 bfd_cleanup xcoff64_core_p (bfd *);
     27 bool xcoff64_core_file_matches_executable_p (bfd *, bfd *);
     28 char *xcoff64_core_file_failing_command (bfd *);
     29 int xcoff64_core_file_failing_signal (bfd *);
     30 
     31 #ifdef AIX_5_CORE
     32 
     33 #include "libbfd.h"
     34 
     35 /* Aix 5.1 system include file.  */
     36 
     37 /* Need to define this macro so struct ld_info64 get included.  */
     38 #define __LDINFO_PTRACE64__
     39 #include <sys/ldr.h>
     40 #include <core.h>
     41 
     42 /* The default architecture and machine for matching core files.  */
     43 #define DEFAULT_ARCHITECTURE	bfd_arch_powerpc
     44 #define DEFAULT_MACHINE		bfd_mach_ppc_620
     45 
     46 #define	core_hdr(abfd)		((struct core_dumpxx *) abfd->tdata.any)
     47 
     48 #define CHECK_FILE_OFFSET(s, v) \
     49   ((bfd_signed_vma)(v) < 0 || (bfd_signed_vma)(v) > (bfd_signed_vma)(s).st_size)
     50 
     51 bfd_cleanup
     52 xcoff64_core_p (bfd *abfd)
     53 {
     54   enum bfd_architecture arch;
     55   unsigned long mach;
     56   struct core_dumpxx core, *new_core_hdr;
     57   struct stat statbuf;
     58   asection *sec;
     59   struct __ld_info64 ldinfo;
     60   bfd_vma ld_offset;
     61   bfd_size_type i;
     62   struct vm_infox vminfo;
     63   flagword flags;
     64 
     65   /* Get the header.  */
     66   if (bfd_seek (abfd, 0, SEEK_SET) != 0)
     67     goto xcoff64_core_p_error;
     68 
     69   if (sizeof (struct core_dumpxx)
     70       != bfd_read (&core, sizeof (struct core_dumpxx), abfd))
     71     goto xcoff64_core_p_error;
     72 
     73   if (bfd_stat (abfd, &statbuf) < 0)
     74     goto xcoff64_core_p_error;
     75 
     76   /* Sanity checks
     77      c_flag has CORE_VERSION_1, Aix 4+
     78      c_entries = 0 for Aix 4.3+
     79      IS_PROC64 is a macro defined in procinfo.h, test for 64 bit process.
     80 
     81      We will still be confused if a Aix 4.3 64 bit core file is
     82      copied over to a Aix 5 machine.
     83 
     84      Check file header offsets
     85 
     86      See rs6000-core.c for comment on size of core
     87      If there isn't enough of a real core file, bail.  */
     88 
     89   if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1))
     90       || (0 != core.c_entries)
     91       || (! (IS_PROC64 (&core.c_u.U_proc)))
     92       || ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox)))
     93       || ((CHECK_FILE_OFFSET (statbuf, core.c_loader)))
     94       || ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize)))
     95       || ((CHECK_FILE_OFFSET (statbuf, core.c_thr)))
     96       || ((CHECK_FILE_OFFSET (statbuf, core.c_segregion)))
     97       || ((CHECK_FILE_OFFSET (statbuf, core.c_stack)))
     98       || ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size)))
     99       || ((CHECK_FILE_OFFSET (statbuf, core.c_data)))
    100       || ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize)))
    101       || (! (core.c_flag & UBLOCK_VALID))
    102       || (! (core.c_flag & LE_VALID)))
    103     goto xcoff64_core_p_error;
    104 
    105   /* Check for truncated stack or general truncating.  */
    106   if ((! (core.c_flag & USTACK_VALID))
    107       || (core.c_flag & CORE_TRUNC))
    108     {
    109       bfd_set_error (bfd_error_file_truncated);
    110 
    111       return NULL;
    112     }
    113 
    114   new_core_hdr = bfd_zalloc (abfd, sizeof (struct core_dumpxx));
    115   if (NULL == new_core_hdr)
    116     return NULL;
    117 
    118   memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx));
    119   /* The core_hdr() macro is no longer used here because it would
    120      expand to code relying on gcc's cast-as-lvalue extension,
    121      which was removed in gcc 4.0.  */
    122   abfd->tdata.any = new_core_hdr;
    123 
    124   /* .stack section.  */
    125   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
    126   sec = bfd_make_section_anyway_with_flags (abfd, ".stack", flags);
    127   if (NULL == sec)
    128     return NULL;
    129 
    130   sec->size = core.c_size;
    131   sec->vma = core.c_stackorg;
    132   sec->filepos = core.c_stack;
    133 
    134   /* .reg section for all registers.  */
    135   flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
    136   sec = bfd_make_section_anyway_with_flags (abfd, ".reg", flags);
    137   if (NULL == sec)
    138     return NULL;
    139 
    140   sec->size = sizeof (struct __context64);
    141   sec->vma = 0;
    142   sec->filepos = 0;
    143   sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64;
    144 
    145   if (core.c_extctx)
    146     {
    147       /* vmx section.  */
    148       flags = SEC_HAS_CONTENTS;
    149       sec = bfd_make_section_anyway_with_flags (abfd, ".aix-vmx", flags);
    150       if (sec == NULL)
    151 	return NULL;
    152       sec->size = 560;
    153       sec->vma = 0;
    154       sec->filepos = core.c_extctx;
    155 
    156       /* vmx section.  */
    157       flags = SEC_HAS_CONTENTS;
    158       sec = bfd_make_section_anyway_with_flags (abfd, ".aix-vsx", flags);
    159       if (sec == NULL)
    160 	return NULL;
    161       sec->size = 256;
    162       sec->vma = 0;
    163       sec->filepos = core.c_extctx + 584;
    164     }
    165 
    166   /* .ldinfo section.
    167      To actually find out how long this section is in this particular
    168      core dump would require going down the whole list of struct
    169      ld_info's.   See if we can just fake it.  */
    170   flags = SEC_HAS_CONTENTS;
    171   sec = bfd_make_section_anyway_with_flags (abfd, ".ldinfo", flags);
    172   if (NULL == sec)
    173     return NULL;
    174 
    175   sec->size = core.c_lsize;
    176   sec->vma = 0;
    177   sec->filepos = core.c_loader;
    178 
    179   /* AIX 4 adds data sections from loaded objects to the core file,
    180      which can be found by examining ldinfo, and anonymously mmapped
    181      regions.  */
    182 
    183   /* .data section from executable.  */
    184   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
    185   sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
    186   if (NULL == sec)
    187     return NULL;
    188 
    189   sec->size = core.c_datasize;
    190   sec->vma = core.c_dataorg;
    191   sec->filepos = core.c_data;
    192 
    193   /* .data sections from loaded objects.  */
    194   ld_offset = core.c_loader;
    195 
    196   while (1)
    197     {
    198       if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0)
    199 	return NULL;
    200 
    201       if (sizeof (struct __ld_info64) !=
    202 	  bfd_read (&ldinfo, sizeof (struct __ld_info64), abfd))
    203 	return NULL;
    204 
    205       if (ldinfo.ldinfo_core)
    206 	{
    207 	  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
    208 	  sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags);
    209 	  if (NULL == sec)
    210 	    return NULL;
    211 
    212 	  sec->size = ldinfo.ldinfo_datasize;
    213 	  sec->vma = ldinfo.ldinfo_dataorg;
    214 	  sec->filepos = ldinfo.ldinfo_core;
    215 	}
    216 
    217       if (0 == ldinfo.ldinfo_next)
    218 	break;
    219       ld_offset += ldinfo.ldinfo_next;
    220     }
    221 
    222   /* .vmdata sections from anonymously mmapped regions.  */
    223   if (core.c_vmregions)
    224     {
    225       if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0)
    226 	return NULL;
    227 
    228       for (i = 0; i < core.c_vmregions; i++)
    229 	if (sizeof (struct vm_infox) !=
    230 	    bfd_read (&vminfo, sizeof (struct vm_infox), abfd))
    231 	  return NULL;
    232 
    233       if (vminfo.vminfo_offset)
    234 	{
    235 	  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
    236 	  sec = bfd_make_section_anyway_with_flags (abfd, ".vmdata", flags);
    237 	  if (NULL == sec)
    238 	    return NULL;
    239 
    240 	  sec->size = vminfo.vminfo_size;
    241 	  sec->vma = vminfo.vminfo_addr;
    242 	  sec->filepos = vminfo.vminfo_offset;
    243 	}
    244     }
    245 
    246   /* Set the architecture and machine.  */
    247   arch = DEFAULT_ARCHITECTURE;
    248   mach = DEFAULT_MACHINE;
    249   bfd_default_set_arch_mach (abfd, arch, mach);
    250 
    251   return _bfd_no_cleanup;
    252 
    253  xcoff64_core_p_error:
    254   if (bfd_get_error () != bfd_error_system_call)
    255     bfd_set_error (bfd_error_wrong_format);
    256 
    257   return NULL;
    258 }
    259 
    260 /* Return `TRUE' if given core is from the given executable.  */
    261 
    262 bool
    263 xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
    264 {
    265   struct core_dumpxx core;
    266   char *path, *s;
    267   size_t alloc;
    268   const char *str1, *str2;
    269   bool return_value = false;
    270 
    271   /* Get the header.  */
    272   if (bfd_seek (core_bfd, 0, SEEK_SET) != 0)
    273     return return_value;
    274 
    275   if (sizeof (struct core_dumpxx) !=
    276       bfd_read (&core, sizeof (struct core_dumpxx), core_bfd))
    277     return return_value;
    278 
    279   if (bfd_seek (core_bfd, core.c_loader, SEEK_SET) != 0)
    280     return return_value;
    281 
    282   alloc = 100;
    283   path = bfd_malloc (alloc);
    284   if (path == NULL)
    285     return return_value;
    286 
    287   s = path;
    288 
    289   while (1)
    290     {
    291       if (bfd_read (s, 1, core_bfd) != 1)
    292 	goto xcoff64_core_file_matches_executable_p_end_1;
    293 
    294       if (*s == '\0')
    295 	break;
    296       ++s;
    297       if (s == path + alloc)
    298 	{
    299 	  char *n;
    300 
    301 	  alloc *= 2;
    302 	  n = bfd_realloc (path, alloc);
    303 	  if (n == NULL)
    304 	    goto xcoff64_core_file_matches_executable_p_end_1;
    305 
    306 	  s = n + (path - s);
    307 	  path = n;
    308 	}
    309     }
    310 
    311   str1 = strrchr (path, '/');
    312   str2 = strrchr (bfd_get_filename (exec_bfd), '/');
    313 
    314   /* Step over character '/'.  */
    315   str1 = str1 != NULL ? str1 + 1 : path;
    316   str2 = str2 != NULL ? str2 + 1 : bfd_get_filename (exec_bfd);
    317 
    318   if (strcmp (str1, str2) == 0)
    319     return_value = true;
    320 
    321  xcoff64_core_file_matches_executable_p_end_1:
    322   free (path);
    323   return return_value;
    324 }
    325 
    326 char *
    327 xcoff64_core_file_failing_command (bfd *abfd)
    328 {
    329   struct core_dumpxx *c = core_hdr (abfd);
    330   char *return_value = 0;
    331 
    332   if (NULL != c)
    333     return_value = c->c_u.U_proc.pi_comm;
    334 
    335   return return_value;
    336 }
    337 
    338 int
    339 xcoff64_core_file_failing_signal (bfd *abfd)
    340 {
    341   struct core_dumpxx *c = core_hdr (abfd);
    342   int return_value = 0;
    343 
    344   if (NULL != c)
    345     return_value = c->c_signo;
    346 
    347   return return_value;
    348 }
    349 
    350 #else /* AIX_5_CORE */
    351 
    352 bfd_cleanup
    353 xcoff64_core_p (bfd *abfd ATTRIBUTE_UNUSED)
    354 {
    355   bfd_set_error (bfd_error_wrong_format);
    356   return 0;
    357 }
    358 
    359 bool
    360 xcoff64_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
    361 {
    362   return generic_core_file_matches_executable_p (core_bfd, exec_bfd);
    363 }
    364 
    365 char *
    366 xcoff64_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
    367 {
    368   return 0;
    369 }
    370 
    371 int
    372 xcoff64_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
    373 {
    374   return 0;
    375 }
    376 
    377 #endif /* AIX_5_CORE */
    378