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