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