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