xref: /openbsd/gnu/usr.bin/binutils/bfd/lynx-core.c (revision c074d1c9)
12159047fSniklas /* BFD back end for Lynx core files
2*c074d1c9Sdrahn    Copyright 1993, 1994, 1995, 2001, 2002 Free Software Foundation, Inc.
32159047fSniklas    Written by Stu Grossman of Cygnus Support.
42159047fSniklas 
52159047fSniklas This file is part of BFD, the Binary File Descriptor library.
62159047fSniklas 
72159047fSniklas This program is free software; you can redistribute it and/or modify
82159047fSniklas it under the terms of the GNU General Public License as published by
92159047fSniklas the Free Software Foundation; either version 2 of the License, or
102159047fSniklas (at your option) any later version.
112159047fSniklas 
122159047fSniklas This program is distributed in the hope that it will be useful,
132159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
152159047fSniklas GNU General Public License for more details.
162159047fSniklas 
172159047fSniklas You should have received a copy of the GNU General Public License
182159047fSniklas along with this program; if not, write to the Free Software
192159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
202159047fSniklas 
212159047fSniklas #include "bfd.h"
222159047fSniklas #include "sysdep.h"
232159047fSniklas #include "libbfd.h"
242159047fSniklas 
252159047fSniklas #ifdef LYNX_CORE
262159047fSniklas 
272159047fSniklas #include <sys/conf.h>
282159047fSniklas #include <sys/kernel.h>
292159047fSniklas /* sys/kernel.h should define this, but doesn't always, sigh.  */
302159047fSniklas #ifndef __LYNXOS
312159047fSniklas #define __LYNXOS
322159047fSniklas #endif
332159047fSniklas #include <sys/mem.h>
342159047fSniklas #include <sys/signal.h>
352159047fSniklas #include <sys/time.h>
362159047fSniklas #include <sys/resource.h>
372159047fSniklas #include <sys/itimer.h>
382159047fSniklas #include <sys/file.h>
392159047fSniklas #include <sys/proc.h>
402159047fSniklas 
412159047fSniklas /* These are stored in the bfd's tdata */
422159047fSniklas 
432159047fSniklas struct lynx_core_struct
442159047fSniklas {
452159047fSniklas   int sig;
462159047fSniklas   char cmd[PNMLEN + 1];
472159047fSniklas };
482159047fSniklas 
492159047fSniklas #define core_hdr(bfd) ((bfd)->tdata.lynx_core_data)
502159047fSniklas #define core_signal(bfd) (core_hdr(bfd)->sig)
512159047fSniklas #define core_command(bfd) (core_hdr(bfd)->cmd)
522159047fSniklas 
532159047fSniklas /* Handle Lynx core dump file.  */
542159047fSniklas 
552159047fSniklas static asection *
make_bfd_asection(abfd,name,flags,_raw_size,vma,filepos)562159047fSniklas make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
572159047fSniklas      bfd *abfd;
58*c074d1c9Sdrahn      const char *name;
592159047fSniklas      flagword flags;
602159047fSniklas      bfd_size_type _raw_size;
612159047fSniklas      bfd_vma vma;
622159047fSniklas      file_ptr filepos;
632159047fSniklas {
642159047fSniklas   asection *asect;
652159047fSniklas   char *newname;
662159047fSniklas 
67*c074d1c9Sdrahn   newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1);
682159047fSniklas   if (!newname)
692159047fSniklas     return NULL;
702159047fSniklas 
712159047fSniklas   strcpy (newname, name);
722159047fSniklas 
732159047fSniklas   asect = bfd_make_section (abfd, newname);
742159047fSniklas   if (!asect)
752159047fSniklas     return NULL;
762159047fSniklas 
772159047fSniklas   asect->flags = flags;
782159047fSniklas   asect->_raw_size = _raw_size;
792159047fSniklas   asect->vma = vma;
802159047fSniklas   asect->filepos = filepos;
812159047fSniklas   asect->alignment_power = 2;
822159047fSniklas 
832159047fSniklas   return asect;
842159047fSniklas }
852159047fSniklas 
862159047fSniklas const bfd_target *
lynx_core_file_p(abfd)872159047fSniklas lynx_core_file_p (abfd)
882159047fSniklas      bfd *abfd;
892159047fSniklas {
902159047fSniklas   int secnum;
912159047fSniklas   struct pssentry pss;
92*c074d1c9Sdrahn   bfd_size_type tcontext_size;
932159047fSniklas   core_st_t *threadp;
942159047fSniklas   int pagesize;
952159047fSniklas   asection *newsect;
96*c074d1c9Sdrahn   bfd_size_type amt;
972159047fSniklas 
982159047fSniklas   pagesize = getpagesize ();	/* Serious cross-target issue here...  This
992159047fSniklas 				   really needs to come from a system-specific
1002159047fSniklas 				   header file.  */
1012159047fSniklas 
1022159047fSniklas   /* Get the pss entry from the core file */
1032159047fSniklas 
104*c074d1c9Sdrahn   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
1052159047fSniklas     return NULL;
1062159047fSniklas 
107*c074d1c9Sdrahn   amt = sizeof pss;
108*c074d1c9Sdrahn   if (bfd_bread ((void *) &pss, amt, abfd) != amt)
1092159047fSniklas     {
1102159047fSniklas       /* Too small to be a core file */
1112159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
1122159047fSniklas 	bfd_set_error (bfd_error_wrong_format);
1132159047fSniklas       return NULL;
1142159047fSniklas     }
1152159047fSniklas 
116*c074d1c9Sdrahn   amt = sizeof (struct lynx_core_struct);
117*c074d1c9Sdrahn   core_hdr (abfd) = (struct lynx_core_struct *) bfd_zalloc (abfd, amt);
1182159047fSniklas 
1192159047fSniklas   if (!core_hdr (abfd))
1202159047fSniklas     return NULL;
1212159047fSniklas 
1222159047fSniklas   strncpy (core_command (abfd), pss.pname, PNMLEN + 1);
1232159047fSniklas 
1242159047fSniklas   /* Compute the size of the thread contexts */
1252159047fSniklas 
1262159047fSniklas   tcontext_size = pss.threadcnt * sizeof (core_st_t);
1272159047fSniklas 
1282159047fSniklas   /* Allocate space for the thread contexts */
1292159047fSniklas 
1302159047fSniklas   threadp = (core_st_t *) bfd_alloc (abfd, tcontext_size);
1312159047fSniklas   if (!threadp)
132*c074d1c9Sdrahn     goto fail;
1332159047fSniklas 
1342159047fSniklas   /* Save thread contexts */
1352159047fSniklas 
136*c074d1c9Sdrahn   if (bfd_seek (abfd, (file_ptr) pagesize, SEEK_SET) != 0)
137*c074d1c9Sdrahn     goto fail;
1382159047fSniklas 
139*c074d1c9Sdrahn   if (bfd_bread ((void *) threadp, tcontext_size, abfd) != tcontext_size)
1402159047fSniklas     {
1412159047fSniklas       /* Probably too small to be a core file */
1422159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
1432159047fSniklas 	bfd_set_error (bfd_error_wrong_format);
144*c074d1c9Sdrahn       goto fail;
1452159047fSniklas     }
1462159047fSniklas 
1472159047fSniklas   core_signal (abfd) = threadp->currsig;
1482159047fSniklas 
1492159047fSniklas   newsect = make_bfd_asection (abfd, ".stack",
1502159047fSniklas 			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
1512159047fSniklas 			       pss.ssize,
1522159047fSniklas 			       pss.slimit,
1532159047fSniklas 			       pagesize + tcontext_size);
1542159047fSniklas   if (!newsect)
155*c074d1c9Sdrahn     goto fail;
1562159047fSniklas 
1572159047fSniklas   newsect = make_bfd_asection (abfd, ".data",
1582159047fSniklas 			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
1592159047fSniklas 			       pss.data_len + pss.bss_len,
1602159047fSniklas 			       pss.data_start,
1612159047fSniklas 			       pagesize + tcontext_size + pss.ssize
1622159047fSniklas #if defined (SPARC) || defined (__SPARC__)
1632159047fSniklas 			       /* SPARC Lynx seems to start dumping
1642159047fSniklas                                   the .data section at a page
1652159047fSniklas                                   boundary.  It's OK to check a
1662159047fSniklas                                   #define like SPARC here because this
1672159047fSniklas                                   file can only be compiled on a Lynx
1682159047fSniklas                                   host.  */
1692159047fSniklas 			       + pss.data_start % pagesize
1702159047fSniklas #endif
1712159047fSniklas 			       );
1722159047fSniklas   if (!newsect)
173*c074d1c9Sdrahn     goto fail;
1742159047fSniklas 
1752159047fSniklas /* And, now for the .reg/XXX pseudo sections.  Each thread has it's own
1762159047fSniklas    .reg/XXX section, where XXX is the thread id (without leading zeros).  The
1772159047fSniklas    currently running thread (at the time of the core dump) also has an alias
1782159047fSniklas    called `.reg' (just to keep GDB happy).  Note that we use `.reg/XXX' as
1792159047fSniklas    opposed to `.regXXX' because GDB expects that .reg2 will be the floating-
1802159047fSniklas    point registers.  */
1812159047fSniklas 
1822159047fSniklas   newsect = make_bfd_asection (abfd, ".reg",
1832159047fSniklas 			       SEC_HAS_CONTENTS,
1842159047fSniklas 			       sizeof (core_st_t),
1852159047fSniklas 			       0,
1862159047fSniklas 			       pagesize);
1872159047fSniklas   if (!newsect)
188*c074d1c9Sdrahn     goto fail;
1892159047fSniklas 
1902159047fSniklas   for (secnum = 0; secnum < pss.threadcnt; secnum++)
1912159047fSniklas     {
1922159047fSniklas       char secname[100];
1932159047fSniklas 
1942159047fSniklas       sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid));
1952159047fSniklas       newsect = make_bfd_asection (abfd, secname,
1962159047fSniklas 				   SEC_HAS_CONTENTS,
1972159047fSniklas 				   sizeof (core_st_t),
1982159047fSniklas 				   0,
1992159047fSniklas 				   pagesize + secnum * sizeof (core_st_t));
2002159047fSniklas       if (!newsect)
201*c074d1c9Sdrahn 	goto fail;
2022159047fSniklas     }
2032159047fSniklas 
2042159047fSniklas   return abfd->xvec;
205*c074d1c9Sdrahn 
206*c074d1c9Sdrahn  fail:
207*c074d1c9Sdrahn   bfd_release (abfd, core_hdr (abfd));
208*c074d1c9Sdrahn   core_hdr (abfd) = NULL;
209*c074d1c9Sdrahn   bfd_section_list_clear (abfd);
210*c074d1c9Sdrahn   return NULL;
2112159047fSniklas }
2122159047fSniklas 
2132159047fSniklas char *
lynx_core_file_failing_command(abfd)2142159047fSniklas lynx_core_file_failing_command (abfd)
2152159047fSniklas      bfd *abfd;
2162159047fSniklas {
2172159047fSniklas   return core_command (abfd);
2182159047fSniklas }
2192159047fSniklas 
2202159047fSniklas int
lynx_core_file_failing_signal(abfd)2212159047fSniklas lynx_core_file_failing_signal (abfd)
2222159047fSniklas      bfd *abfd;
2232159047fSniklas {
2242159047fSniklas   return core_signal (abfd);
2252159047fSniklas }
2262159047fSniklas 
227*c074d1c9Sdrahn bfd_boolean
lynx_core_file_matches_executable_p(core_bfd,exec_bfd)2282159047fSniklas lynx_core_file_matches_executable_p  (core_bfd, exec_bfd)
2292159047fSniklas      bfd *core_bfd, *exec_bfd;
2302159047fSniklas {
231*c074d1c9Sdrahn   return TRUE;		/* FIXME, We have no way of telling at this point */
2322159047fSniklas }
2332159047fSniklas 
2342159047fSniklas #endif /* LYNX_CORE */
235