(root)/
binutils-2.41/
bfd/
lynx-core.c
       1  /* BFD back end for Lynx core files
       2     Copyright (C) 1993-2023 Free Software Foundation, Inc.
       3     Written by Stu Grossman 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  
      26  #ifdef LYNX_CORE
      27  
      28  #include <sys/conf.h>
      29  #include <sys/kernel.h>
      30  /* sys/kernel.h should define this, but doesn't always, sigh.  */
      31  #ifndef __LYNXOS
      32  #define __LYNXOS
      33  #endif
      34  #include <sys/mem.h>
      35  #include <sys/signal.h>
      36  #include <sys/time.h>
      37  #include <sys/resource.h>
      38  #include <sys/itimer.h>
      39  #include <sys/file.h>
      40  #include <sys/proc.h>
      41  
      42  /* These are stored in the bfd's tdata */
      43  
      44  struct lynx_core_struct
      45  {
      46    int sig;
      47    char cmd[PNMLEN + 1];
      48  };
      49  
      50  #define core_hdr(bfd) ((bfd)->tdata.lynx_core_data)
      51  #define core_signal(bfd) (core_hdr(bfd)->sig)
      52  #define core_command(bfd) (core_hdr(bfd)->cmd)
      53  
      54  #define lynx_core_file_matches_executable_p generic_core_file_matches_executable_p
      55  #define lynx_core_file_pid _bfd_nocore_core_file_pid
      56  
      57  /* Handle Lynx core dump file.  */
      58  
      59  static asection *
      60  make_bfd_asection (bfd *abfd,
      61  		   const char *name,
      62  		   flagword flags,
      63  		   bfd_size_type size,
      64  		   bfd_vma vma,
      65  		   file_ptr filepos)
      66  {
      67    asection *asect;
      68    char *newname;
      69  
      70    newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1);
      71    if (!newname)
      72      return NULL;
      73  
      74    strcpy (newname, name);
      75  
      76    asect = bfd_make_section_with_flags (abfd, newname, flags);
      77    if (!asect)
      78      return NULL;
      79  
      80    asect->size = size;
      81    asect->vma = vma;
      82    asect->filepos = filepos;
      83    asect->alignment_power = 2;
      84  
      85    return asect;
      86  }
      87  
      88  bfd_cleanup
      89  lynx_core_file_p (bfd *abfd)
      90  {
      91    int secnum;
      92    struct pssentry pss;
      93    bfd_size_type tcontext_size;
      94    core_st_t *threadp;
      95    int pagesize;
      96    asection *newsect;
      97    size_t amt;
      98  
      99    pagesize = getpagesize ();	/* Serious cross-target issue here...  This
     100  				   really needs to come from a system-specific
     101  				   header file.  */
     102  
     103    /* Get the pss entry from the core file */
     104  
     105    if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
     106      return NULL;
     107  
     108    amt = sizeof pss;
     109    if (bfd_bread ((void *) &pss, amt, abfd) != amt)
     110      {
     111        /* Too small to be a core file */
     112        if (bfd_get_error () != bfd_error_system_call)
     113  	bfd_set_error (bfd_error_wrong_format);
     114        return NULL;
     115      }
     116  
     117    amt = sizeof (struct lynx_core_struct);
     118    core_hdr (abfd) = (struct lynx_core_struct *) bfd_zalloc (abfd, amt);
     119  
     120    if (!core_hdr (abfd))
     121      return NULL;
     122  
     123    strncpy (core_command (abfd), pss.pname, PNMLEN + 1);
     124  
     125    /* Compute the size of the thread contexts */
     126  
     127    tcontext_size = pss.threadcnt * sizeof (core_st_t);
     128  
     129    /* Save thread contexts */
     130    if (bfd_seek (abfd, pagesize, SEEK_SET) != 0)
     131      goto fail;
     132    threadp = (core_st_t *) _bfd_alloc_and_read (abfd, tcontext_size,
     133  					       tcontext_size);
     134    if (!threadp)
     135      goto fail;
     136  
     137    core_signal (abfd) = threadp->currsig;
     138  
     139    newsect = make_bfd_asection (abfd, ".stack",
     140  			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
     141  			       pss.ssize,
     142  			       pss.slimit,
     143  			       pagesize + tcontext_size);
     144    if (!newsect)
     145      goto fail;
     146  
     147    newsect = make_bfd_asection (abfd, ".data",
     148  			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
     149  			       pss.data_len + pss.bss_len,
     150  			       pss.data_start,
     151  			       pagesize + tcontext_size + pss.ssize
     152  #if defined (SPARC) || defined (__SPARC__)
     153  			       /* SPARC Lynx seems to start dumping
     154  				  the .data section at a page
     155  				  boundary.  It's OK to check a
     156  				  #define like SPARC here because this
     157  				  file can only be compiled on a Lynx
     158  				  host.  */
     159  			       + pss.data_start % pagesize
     160  #endif
     161  			       );
     162    if (!newsect)
     163      goto fail;
     164  
     165  /* And, now for the .reg/XXX pseudo sections.  Each thread has it's own
     166     .reg/XXX section, where XXX is the thread id (without leading zeros).  The
     167     currently running thread (at the time of the core dump) also has an alias
     168     called `.reg' (just to keep GDB happy).  Note that we use `.reg/XXX' as
     169     opposed to `.regXXX' because GDB expects that .reg2 will be the floating-
     170     point registers.  */
     171  
     172    newsect = make_bfd_asection (abfd, ".reg",
     173  			       SEC_HAS_CONTENTS,
     174  			       sizeof (core_st_t),
     175  			       0,
     176  			       pagesize);
     177    if (!newsect)
     178      goto fail;
     179  
     180    for (secnum = 0; secnum < pss.threadcnt; secnum++)
     181      {
     182        char secname[100];
     183  
     184        sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid));
     185        newsect = make_bfd_asection (abfd, secname,
     186  				   SEC_HAS_CONTENTS,
     187  				   sizeof (core_st_t),
     188  				   0,
     189  				   pagesize + secnum * sizeof (core_st_t));
     190        if (!newsect)
     191  	goto fail;
     192      }
     193  
     194    return _bfd_no_cleanup;
     195  
     196   fail:
     197    bfd_release (abfd, core_hdr (abfd));
     198    core_hdr (abfd) = NULL;
     199    bfd_section_list_clear (abfd);
     200    return NULL;
     201  }
     202  
     203  char *
     204  lynx_core_file_failing_command (bfd *abfd)
     205  {
     206    return core_command (abfd);
     207  }
     208  
     209  int
     210  lynx_core_file_failing_signal (bfd *abfd)
     211  {
     212    return core_signal (abfd);
     213  }
     214  
     215  #endif /* LYNX_CORE */