xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/lynx-core.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* BFD back end for Lynx core files
2*e992f068Schristos    Copyright (C) 1993-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Written by Stu Grossman of Cygnus Support.
475fd0b74Schristos 
575fd0b74Schristos    This file is part of BFD, the Binary File Descriptor library.
675fd0b74Schristos 
775fd0b74Schristos    This program is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3 of the License, or
1075fd0b74Schristos    (at your option) any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    This program is distributed in the hope that it will be useful,
1375fd0b74Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1475fd0b74Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1575fd0b74Schristos    GNU General Public License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this program; if not, write to the Free Software
1975fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2075fd0b74Schristos    MA 02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos #include "sysdep.h"
2375fd0b74Schristos #include "bfd.h"
2475fd0b74Schristos #include "libbfd.h"
2575fd0b74Schristos 
2675fd0b74Schristos #ifdef LYNX_CORE
2775fd0b74Schristos 
2875fd0b74Schristos #include <sys/conf.h>
2975fd0b74Schristos #include <sys/kernel.h>
3075fd0b74Schristos /* sys/kernel.h should define this, but doesn't always, sigh.  */
3175fd0b74Schristos #ifndef __LYNXOS
3275fd0b74Schristos #define __LYNXOS
3375fd0b74Schristos #endif
3475fd0b74Schristos #include <sys/mem.h>
3575fd0b74Schristos #include <sys/signal.h>
3675fd0b74Schristos #include <sys/time.h>
3775fd0b74Schristos #include <sys/resource.h>
3875fd0b74Schristos #include <sys/itimer.h>
3975fd0b74Schristos #include <sys/file.h>
4075fd0b74Schristos #include <sys/proc.h>
4175fd0b74Schristos 
4275fd0b74Schristos /* These are stored in the bfd's tdata */
4375fd0b74Schristos 
4475fd0b74Schristos struct lynx_core_struct
4575fd0b74Schristos {
4675fd0b74Schristos   int sig;
4775fd0b74Schristos   char cmd[PNMLEN + 1];
4875fd0b74Schristos };
4975fd0b74Schristos 
5075fd0b74Schristos #define core_hdr(bfd) ((bfd)->tdata.lynx_core_data)
5175fd0b74Schristos #define core_signal(bfd) (core_hdr(bfd)->sig)
5275fd0b74Schristos #define core_command(bfd) (core_hdr(bfd)->cmd)
5375fd0b74Schristos 
5475fd0b74Schristos #define lynx_core_file_matches_executable_p generic_core_file_matches_executable_p
5575fd0b74Schristos #define lynx_core_file_pid _bfd_nocore_core_file_pid
5675fd0b74Schristos 
5775fd0b74Schristos /* Handle Lynx core dump file.  */
5875fd0b74Schristos 
5975fd0b74Schristos static asection *
make_bfd_asection(bfd * abfd,const char * name,flagword flags,bfd_size_type size,bfd_vma vma,file_ptr filepos)6075fd0b74Schristos make_bfd_asection (bfd *abfd,
6175fd0b74Schristos 		   const char *name,
6275fd0b74Schristos 		   flagword flags,
6375fd0b74Schristos 		   bfd_size_type size,
6475fd0b74Schristos 		   bfd_vma vma,
6575fd0b74Schristos 		   file_ptr filepos)
6675fd0b74Schristos {
6775fd0b74Schristos   asection *asect;
6875fd0b74Schristos   char *newname;
6975fd0b74Schristos 
7075fd0b74Schristos   newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1);
7175fd0b74Schristos   if (!newname)
7275fd0b74Schristos     return NULL;
7375fd0b74Schristos 
7475fd0b74Schristos   strcpy (newname, name);
7575fd0b74Schristos 
7675fd0b74Schristos   asect = bfd_make_section_with_flags (abfd, newname, flags);
7775fd0b74Schristos   if (!asect)
7875fd0b74Schristos     return NULL;
7975fd0b74Schristos 
8075fd0b74Schristos   asect->size = size;
8175fd0b74Schristos   asect->vma = vma;
8275fd0b74Schristos   asect->filepos = filepos;
8375fd0b74Schristos   asect->alignment_power = 2;
8475fd0b74Schristos 
8575fd0b74Schristos   return asect;
8675fd0b74Schristos }
8775fd0b74Schristos 
88*e992f068Schristos bfd_cleanup
lynx_core_file_p(bfd * abfd)8975fd0b74Schristos lynx_core_file_p (bfd *abfd)
9075fd0b74Schristos {
9175fd0b74Schristos   int secnum;
9275fd0b74Schristos   struct pssentry pss;
9375fd0b74Schristos   bfd_size_type tcontext_size;
9475fd0b74Schristos   core_st_t *threadp;
9575fd0b74Schristos   int pagesize;
9675fd0b74Schristos   asection *newsect;
97*e992f068Schristos   size_t amt;
9875fd0b74Schristos 
9975fd0b74Schristos   pagesize = getpagesize ();	/* Serious cross-target issue here...  This
10075fd0b74Schristos 				   really needs to come from a system-specific
10175fd0b74Schristos 				   header file.  */
10275fd0b74Schristos 
10375fd0b74Schristos   /* Get the pss entry from the core file */
10475fd0b74Schristos 
10575fd0b74Schristos   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
10675fd0b74Schristos     return NULL;
10775fd0b74Schristos 
10875fd0b74Schristos   amt = sizeof pss;
10975fd0b74Schristos   if (bfd_bread ((void *) &pss, amt, abfd) != amt)
11075fd0b74Schristos     {
11175fd0b74Schristos       /* Too small to be a core file */
11275fd0b74Schristos       if (bfd_get_error () != bfd_error_system_call)
11375fd0b74Schristos 	bfd_set_error (bfd_error_wrong_format);
11475fd0b74Schristos       return NULL;
11575fd0b74Schristos     }
11675fd0b74Schristos 
11775fd0b74Schristos   amt = sizeof (struct lynx_core_struct);
11875fd0b74Schristos   core_hdr (abfd) = (struct lynx_core_struct *) bfd_zalloc (abfd, amt);
11975fd0b74Schristos 
12075fd0b74Schristos   if (!core_hdr (abfd))
12175fd0b74Schristos     return NULL;
12275fd0b74Schristos 
12375fd0b74Schristos   strncpy (core_command (abfd), pss.pname, PNMLEN + 1);
12475fd0b74Schristos 
12575fd0b74Schristos   /* Compute the size of the thread contexts */
12675fd0b74Schristos 
12775fd0b74Schristos   tcontext_size = pss.threadcnt * sizeof (core_st_t);
12875fd0b74Schristos 
129*e992f068Schristos   /* Save thread contexts */
130*e992f068Schristos   if (bfd_seek (abfd, pagesize, SEEK_SET) != 0)
131*e992f068Schristos     goto fail;
132*e992f068Schristos   threadp = (core_st_t *) _bfd_alloc_and_read (abfd, tcontext_size,
133*e992f068Schristos 					       tcontext_size);
13475fd0b74Schristos   if (!threadp)
13575fd0b74Schristos     goto fail;
13675fd0b74Schristos 
13775fd0b74Schristos   core_signal (abfd) = threadp->currsig;
13875fd0b74Schristos 
13975fd0b74Schristos   newsect = make_bfd_asection (abfd, ".stack",
14075fd0b74Schristos 			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
14175fd0b74Schristos 			       pss.ssize,
14275fd0b74Schristos 			       pss.slimit,
14375fd0b74Schristos 			       pagesize + tcontext_size);
14475fd0b74Schristos   if (!newsect)
14575fd0b74Schristos     goto fail;
14675fd0b74Schristos 
14775fd0b74Schristos   newsect = make_bfd_asection (abfd, ".data",
14875fd0b74Schristos 			       SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
14975fd0b74Schristos 			       pss.data_len + pss.bss_len,
15075fd0b74Schristos 			       pss.data_start,
15175fd0b74Schristos 			       pagesize + tcontext_size + pss.ssize
15275fd0b74Schristos #if defined (SPARC) || defined (__SPARC__)
15375fd0b74Schristos 			       /* SPARC Lynx seems to start dumping
15475fd0b74Schristos 				  the .data section at a page
15575fd0b74Schristos 				  boundary.  It's OK to check a
15675fd0b74Schristos 				  #define like SPARC here because this
15775fd0b74Schristos 				  file can only be compiled on a Lynx
15875fd0b74Schristos 				  host.  */
15975fd0b74Schristos 			       + pss.data_start % pagesize
16075fd0b74Schristos #endif
16175fd0b74Schristos 			       );
16275fd0b74Schristos   if (!newsect)
16375fd0b74Schristos     goto fail;
16475fd0b74Schristos 
16575fd0b74Schristos /* And, now for the .reg/XXX pseudo sections.  Each thread has it's own
16675fd0b74Schristos    .reg/XXX section, where XXX is the thread id (without leading zeros).  The
16775fd0b74Schristos    currently running thread (at the time of the core dump) also has an alias
16875fd0b74Schristos    called `.reg' (just to keep GDB happy).  Note that we use `.reg/XXX' as
16975fd0b74Schristos    opposed to `.regXXX' because GDB expects that .reg2 will be the floating-
17075fd0b74Schristos    point registers.  */
17175fd0b74Schristos 
17275fd0b74Schristos   newsect = make_bfd_asection (abfd, ".reg",
17375fd0b74Schristos 			       SEC_HAS_CONTENTS,
17475fd0b74Schristos 			       sizeof (core_st_t),
17575fd0b74Schristos 			       0,
17675fd0b74Schristos 			       pagesize);
17775fd0b74Schristos   if (!newsect)
17875fd0b74Schristos     goto fail;
17975fd0b74Schristos 
18075fd0b74Schristos   for (secnum = 0; secnum < pss.threadcnt; secnum++)
18175fd0b74Schristos     {
18275fd0b74Schristos       char secname[100];
18375fd0b74Schristos 
18475fd0b74Schristos       sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid));
18575fd0b74Schristos       newsect = make_bfd_asection (abfd, secname,
18675fd0b74Schristos 				   SEC_HAS_CONTENTS,
18775fd0b74Schristos 				   sizeof (core_st_t),
18875fd0b74Schristos 				   0,
18975fd0b74Schristos 				   pagesize + secnum * sizeof (core_st_t));
19075fd0b74Schristos       if (!newsect)
19175fd0b74Schristos 	goto fail;
19275fd0b74Schristos     }
19375fd0b74Schristos 
194*e992f068Schristos   return _bfd_no_cleanup;
19575fd0b74Schristos 
19675fd0b74Schristos  fail:
19775fd0b74Schristos   bfd_release (abfd, core_hdr (abfd));
19875fd0b74Schristos   core_hdr (abfd) = NULL;
19975fd0b74Schristos   bfd_section_list_clear (abfd);
20075fd0b74Schristos   return NULL;
20175fd0b74Schristos }
20275fd0b74Schristos 
20375fd0b74Schristos char *
lynx_core_file_failing_command(bfd * abfd)20475fd0b74Schristos lynx_core_file_failing_command (bfd *abfd)
20575fd0b74Schristos {
20675fd0b74Schristos   return core_command (abfd);
20775fd0b74Schristos }
20875fd0b74Schristos 
20975fd0b74Schristos int
lynx_core_file_failing_signal(bfd * abfd)21075fd0b74Schristos lynx_core_file_failing_signal (bfd *abfd)
21175fd0b74Schristos {
21275fd0b74Schristos   return core_signal (abfd);
21375fd0b74Schristos }
21475fd0b74Schristos 
21575fd0b74Schristos #endif /* LYNX_CORE */
216