(root)/
binutils-2.41/
bfd/
trad-core.c
       1  /* BFD back end for traditional Unix core files (U-area and raw sections)
       2     Copyright (C) 1988-2023 Free Software Foundation, Inc.
       3     Written by John Gilmore of Cygnus Support.
       4  
       5     This file is part of BFD, the Binary File Descriptor library.
       6  
       7     This program is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3 of the License, or
      10     (at your option) any later version.
      11  
      12     This program is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with this program; if not, write to the Free Software
      19     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      20     MA 02110-1301, USA.  */
      21  
      22  #include "sysdep.h"
      23  #include "bfd.h"
      24  #include "libbfd.h"
      25  #include "libaout.h"	       /* BFD a.out internal data structures */
      26  
      27  #include <sys/param.h>
      28  #include <dirent.h>
      29  #include <signal.h>
      30  
      31  #include <sys/user.h>		/* After a.out.h  */
      32  
      33  #ifdef TRAD_HEADER
      34  #include TRAD_HEADER
      35  #endif
      36  
      37  #ifndef NBPG
      38  # define NBPG getpagesize()
      39  #endif
      40  
      41  struct trad_core_struct
      42  {
      43    asection *data_section;
      44    asection *stack_section;
      45    asection *reg_section;
      46    struct user u;
      47  };
      48  
      49  #define core_upage(bfd)  (&((bfd)->tdata.trad_core_data->u))
      50  #define core_datasec(bfd)  ((bfd)->tdata.trad_core_data->data_section)
      51  #define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section)
      52  #define core_regsec(bfd)   ((bfd)->tdata.trad_core_data->reg_section)
      53  
      54  /* forward declarations */
      55  
      56  #define trad_unix_core_file_matches_executable_p generic_core_file_matches_executable_p
      57  #define trad_unix_core_file_pid _bfd_nocore_core_file_pid
      58  
      59  
      60  /* Handle 4.2-style (and perhaps also sysV-style) core dump file.  */
      61  
      62  static bfd_cleanup
      63  trad_unix_core_file_p (bfd *abfd)
      64  {
      65    int val;
      66    struct user u;
      67    struct trad_core_struct *rawptr;
      68    size_t amt;
      69    flagword flags;
      70  
      71  #ifdef TRAD_CORE_USER_OFFSET
      72    /* If defined, this macro is the file position of the user struct.  */
      73    if (bfd_seek (abfd, (file_ptr) TRAD_CORE_USER_OFFSET, SEEK_SET) != 0)
      74      return 0;
      75  #endif
      76  
      77    val = bfd_bread ((void *) &u, (bfd_size_type) sizeof u, abfd);
      78    if (val != sizeof u)
      79      {
      80        /* Too small to be a core file */
      81        bfd_set_error (bfd_error_wrong_format);
      82        return 0;
      83      }
      84  
      85    /* Sanity check perhaps??? */
      86    if (u.u_dsize > 0x1000000)	/* Remember, it's in pages...  */
      87      {
      88        bfd_set_error (bfd_error_wrong_format);
      89        return 0;
      90      }
      91    if (u.u_ssize > 0x1000000)
      92      {
      93        bfd_set_error (bfd_error_wrong_format);
      94        return 0;
      95      }
      96  
      97    /* Check that the size claimed is no greater than the file size.  */
      98    {
      99      struct stat statbuf;
     100  
     101      if (bfd_stat (abfd, &statbuf) < 0)
     102        return 0;
     103  
     104      if ((ufile_ptr) NBPG * (UPAGES + u.u_dsize
     105  #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
     106  			    - u.u_tsize
     107  #endif
     108  			    + u.u_ssize)
     109  	> (ufile_ptr) statbuf.st_size)
     110        {
     111  	bfd_set_error (bfd_error_wrong_format);
     112  	return 0;
     113        }
     114  #ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE
     115      if (((ufile_ptr) NBPG * (UPAGES + u.u_dsize + u.u_ssize)
     116  #ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED
     117  	/* Some systems write the file too big.  */
     118  	 + TRAD_CORE_EXTRA_SIZE_ALLOWED
     119  #endif
     120  	 )
     121  	< (ufile_ptr) statbuf.st_size)
     122        {
     123  	/* The file is too big.  Maybe it's not a core file
     124  	   or we otherwise have bad values for u_dsize and u_ssize).  */
     125  	bfd_set_error (bfd_error_wrong_format);
     126  	return 0;
     127        }
     128  #endif
     129    }
     130  
     131    /* OK, we believe you.  You're a core file (sure, sure).  */
     132  
     133    /* Allocate both the upage and the struct core_data at once, so
     134       a single free() will free them both.  */
     135    amt = sizeof (struct trad_core_struct);
     136    rawptr = (struct trad_core_struct *) bfd_zmalloc (amt);
     137    if (rawptr == NULL)
     138      return 0;
     139  
     140    abfd->tdata.trad_core_data = rawptr;
     141  
     142    rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
     143  
     144    /* Create the sections.  */
     145  
     146    flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
     147    core_stacksec(abfd) = bfd_make_section_anyway_with_flags (abfd, ".stack",
     148  							    flags);
     149    if (core_stacksec (abfd) == NULL)
     150      goto fail;
     151    core_datasec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".data",
     152  							    flags);
     153    if (core_datasec (abfd) == NULL)
     154      goto fail;
     155    core_regsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg",
     156  							   SEC_HAS_CONTENTS);
     157    if (core_regsec (abfd) == NULL)
     158      goto fail;
     159  
     160    core_datasec (abfd)->size =  NBPG * u.u_dsize
     161  #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
     162      - NBPG * u.u_tsize
     163  #endif
     164        ;
     165    core_stacksec (abfd)->size = NBPG * u.u_ssize;
     166    core_regsec (abfd)->size = NBPG * UPAGES; /* Larger than sizeof struct u */
     167  
     168    /* What a hack... we'd like to steal it from the exec file,
     169       since the upage does not seem to provide it.  FIXME.  */
     170  #ifdef HOST_DATA_START_ADDR
     171    core_datasec (abfd)->vma = HOST_DATA_START_ADDR;
     172  #else
     173    core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize);
     174  #endif
     175  
     176  #ifdef HOST_STACK_START_ADDR
     177    core_stacksec (abfd)->vma = HOST_STACK_START_ADDR;
     178  #else
     179    core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize);
     180  #endif
     181  
     182    /* This is tricky.  As the "register section", we give them the entire
     183       upage and stack.  u.u_ar0 points to where "register 0" is stored.
     184       There are two tricks with this, though.  One is that the rest of the
     185       registers might be at positive or negative (or both) displacements
     186       from *u_ar0.  The other is that u_ar0 is sometimes an absolute address
     187       in kernel memory, and on other systems it is an offset from the beginning
     188       of the `struct user'.
     189  
     190       As a practical matter, we don't know where the registers actually are,
     191       so we have to pass the whole area to GDB.  We encode the value of u_ar0
     192       by setting the .regs section up so that its virtual memory address
     193       0 is at the place pointed to by u_ar0 (by setting the vma of the start
     194       of the section to -u_ar0).  GDB uses this info to locate the regs,
     195       using minor trickery to get around the offset-or-absolute-addr problem.  */
     196    core_regsec (abfd)->vma = - (bfd_vma) (unsigned long) u.u_ar0;
     197  
     198    core_datasec (abfd)->filepos = NBPG * UPAGES;
     199    core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize
     200  #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
     201      - NBPG * u.u_tsize
     202  #endif
     203        ;
     204    core_regsec (abfd)->filepos = 0; /* Register segment is the upage */
     205  
     206    /* Align to word at least */
     207    core_stacksec (abfd)->alignment_power = 2;
     208    core_datasec (abfd)->alignment_power = 2;
     209    core_regsec (abfd)->alignment_power = 2;
     210  
     211    return _bfd_no_cleanup;
     212  
     213   fail:
     214    bfd_release (abfd, abfd->tdata.any);
     215    abfd->tdata.any = NULL;
     216    bfd_section_list_clear (abfd);
     217    return NULL;
     218  }
     219  
     220  static char *
     221  trad_unix_core_file_failing_command (bfd *abfd)
     222  {
     223  #ifndef NO_CORE_COMMAND
     224    char *com = abfd->tdata.trad_core_data->u.u_comm;
     225    if (*com)
     226      return com;
     227    else
     228  #endif
     229      return 0;
     230  }
     231  
     232  static int
     233  trad_unix_core_file_failing_signal (bfd *ignore_abfd ATTRIBUTE_UNUSED)
     234  {
     235  #ifdef TRAD_UNIX_CORE_FILE_FAILING_SIGNAL
     236    return TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(ignore_abfd);
     237  #else
     238    return -1;		/* FIXME, where is it? */
     239  #endif
     240  }
     241  
     242  /* If somebody calls any byte-swapping routines, shoot them.  */
     243  static void
     244  swap_abort (void)
     245  {
     246    abort (); /* This way doesn't require any declaration for ANSI to fuck up */
     247  }
     248  
     249  #define	NO_GET ((bfd_vma (*) (const void *)) swap_abort)
     250  #define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
     251  #define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
     252  #define	NO_GET64 ((uint64_t (*) (const void *)) swap_abort)
     253  #define	NO_PUT64 ((void (*) (uint64_t, void *)) swap_abort)
     254  #define	NO_GETS64 ((int64_t (*) (const void *)) swap_abort)
     255  
     256  const bfd_target core_trad_vec =
     257    {
     258      "trad-core",
     259      bfd_target_unknown_flavour,
     260      BFD_ENDIAN_UNKNOWN,		/* target byte order */
     261      BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
     262      (HAS_RELOC | EXEC_P |	/* object flags */
     263       HAS_LINENO | HAS_DEBUG |
     264       HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
     265      (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
     266      0,				/* symbol prefix */
     267      ' ',			/* ar_pad_char */
     268      16,				/* ar_max_namelen */
     269      0,				/* match priority.  */
     270      TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
     271      NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data */
     272      NO_GET, NO_GETS, NO_PUT,		/* 32 bit data */
     273      NO_GET, NO_GETS, NO_PUT,		/* 16 bit data */
     274      NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs */
     275      NO_GET, NO_GETS, NO_PUT,		/* 32 bit hdrs */
     276      NO_GET, NO_GETS, NO_PUT,		/* 16 bit hdrs */
     277  
     278      {				/* bfd_check_format */
     279        _bfd_dummy_target,		/* unknown format */
     280        _bfd_dummy_target,		/* object file */
     281        _bfd_dummy_target,		/* archive */
     282        trad_unix_core_file_p		/* a core file */
     283      },
     284      {				/* bfd_set_format */
     285        _bfd_bool_bfd_false_error,
     286        _bfd_bool_bfd_false_error,
     287        _bfd_bool_bfd_false_error,
     288        _bfd_bool_bfd_false_error
     289      },
     290      {				/* bfd_write_contents */
     291        _bfd_bool_bfd_false_error,
     292        _bfd_bool_bfd_false_error,
     293        _bfd_bool_bfd_false_error,
     294        _bfd_bool_bfd_false_error
     295      },
     296  
     297      BFD_JUMP_TABLE_GENERIC (_bfd_generic),
     298      BFD_JUMP_TABLE_COPY (_bfd_generic),
     299      BFD_JUMP_TABLE_CORE (trad_unix),
     300      BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
     301      BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
     302      BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
     303      BFD_JUMP_TABLE_WRITE (_bfd_generic),
     304      BFD_JUMP_TABLE_LINK (_bfd_nolink),
     305      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
     306  
     307      NULL,
     308  
     309      NULL			/* backend_data */
     310    };