175fd0b74Schristos /* BFD back end for NetBSD style core files
2*e992f068Schristos Copyright (C) 1988-2022 Free Software Foundation, Inc.
375fd0b74Schristos Written by Paul Kranenburg, EUR
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 #include "libaout.h" /* BFD a.out internal data structures. */
2675fd0b74Schristos
2775fd0b74Schristos #include <sys/param.h>
2875fd0b74Schristos #include <sys/dir.h>
2975fd0b74Schristos #include <signal.h>
3075fd0b74Schristos #include <sys/core.h>
3175fd0b74Schristos
3275fd0b74Schristos /* The machine ID for OpenBSD/sparc64 and older versions of
3375fd0b74Schristos NetBSD/sparc64 overlaps with M_MIPS1. */
3475fd0b74Schristos #define M_SPARC64_OPENBSD M_MIPS1
3575fd0b74Schristos
3675fd0b74Schristos /* Offset of StackGhost cookie within `struct md_coredump' on
3775fd0b74Schristos OpenBSD/sparc. */
3875fd0b74Schristos #define SPARC_WCOOKIE_OFFSET 344
3975fd0b74Schristos
4075fd0b74Schristos /* Offset of StackGhost cookie within `struct md_coredump' on
4175fd0b74Schristos OpenBSD/sparc64. */
4275fd0b74Schristos #define SPARC64_WCOOKIE_OFFSET 832
4375fd0b74Schristos
4475fd0b74Schristos #define netbsd_core_file_matches_executable_p generic_core_file_matches_executable_p
4575fd0b74Schristos #define netbsd_core_file_pid _bfd_nocore_core_file_pid
4675fd0b74Schristos
4775fd0b74Schristos struct netbsd_core_struct
4875fd0b74Schristos {
4975fd0b74Schristos struct core core;
5075fd0b74Schristos } *rawptr;
5175fd0b74Schristos
5275fd0b74Schristos /* Handle NetBSD-style core dump file. */
5375fd0b74Schristos
54*e992f068Schristos static bfd_cleanup
netbsd_core_file_p(bfd * abfd)5575fd0b74Schristos netbsd_core_file_p (bfd *abfd)
5675fd0b74Schristos {
5775fd0b74Schristos int val;
5875fd0b74Schristos unsigned i;
5975fd0b74Schristos file_ptr offset;
6075fd0b74Schristos asection *asect;
6175fd0b74Schristos struct core core;
6275fd0b74Schristos struct coreseg coreseg;
63*e992f068Schristos size_t amt = sizeof core;
6475fd0b74Schristos
6575fd0b74Schristos val = bfd_bread (&core, amt, abfd);
6675fd0b74Schristos if (val != sizeof core)
6775fd0b74Schristos {
6875fd0b74Schristos /* Too small to be a core file. */
6975fd0b74Schristos bfd_set_error (bfd_error_wrong_format);
7075fd0b74Schristos return 0;
7175fd0b74Schristos }
7275fd0b74Schristos
7375fd0b74Schristos if (CORE_GETMAGIC (core) != COREMAGIC)
7475fd0b74Schristos {
7575fd0b74Schristos bfd_set_error (bfd_error_wrong_format);
7675fd0b74Schristos return 0;
7775fd0b74Schristos }
7875fd0b74Schristos
7975fd0b74Schristos amt = sizeof (struct netbsd_core_struct);
8075fd0b74Schristos rawptr = (struct netbsd_core_struct *) bfd_zalloc (abfd, amt);
8175fd0b74Schristos if (rawptr == NULL)
8275fd0b74Schristos return 0;
8375fd0b74Schristos
8475fd0b74Schristos rawptr->core = core;
8575fd0b74Schristos abfd->tdata.netbsd_core_data = rawptr;
8675fd0b74Schristos
8775fd0b74Schristos offset = core.c_hdrsize;
8875fd0b74Schristos for (i = 0; i < core.c_nseg; i++)
8975fd0b74Schristos {
9075fd0b74Schristos const char *sname;
9175fd0b74Schristos flagword flags;
9275fd0b74Schristos
9375fd0b74Schristos if (bfd_seek (abfd, offset, SEEK_SET) != 0)
9475fd0b74Schristos goto punt;
9575fd0b74Schristos
9675fd0b74Schristos val = bfd_bread (&coreseg, sizeof coreseg, abfd);
9775fd0b74Schristos if (val != sizeof coreseg)
9875fd0b74Schristos {
9975fd0b74Schristos bfd_set_error (bfd_error_file_truncated);
10075fd0b74Schristos goto punt;
10175fd0b74Schristos }
10275fd0b74Schristos if (CORE_GETMAGIC (coreseg) != CORESEGMAGIC)
10375fd0b74Schristos {
10475fd0b74Schristos bfd_set_error (bfd_error_wrong_format);
10575fd0b74Schristos goto punt;
10675fd0b74Schristos }
10775fd0b74Schristos
10875fd0b74Schristos offset += core.c_seghdrsize;
10975fd0b74Schristos
11075fd0b74Schristos switch (CORE_GETFLAG (coreseg))
11175fd0b74Schristos {
11275fd0b74Schristos case CORE_CPU:
11375fd0b74Schristos sname = ".reg";
11475fd0b74Schristos flags = SEC_ALLOC + SEC_HAS_CONTENTS;
11575fd0b74Schristos break;
11675fd0b74Schristos case CORE_DATA:
11775fd0b74Schristos sname = ".data";
11875fd0b74Schristos flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
11975fd0b74Schristos break;
12075fd0b74Schristos case CORE_STACK:
12175fd0b74Schristos sname = ".stack";
12275fd0b74Schristos flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
12375fd0b74Schristos break;
12475fd0b74Schristos default:
12575fd0b74Schristos sname = ".unknown";
12675fd0b74Schristos flags = SEC_ALLOC + SEC_HAS_CONTENTS;
12775fd0b74Schristos break;
12875fd0b74Schristos }
12975fd0b74Schristos asect = bfd_make_section_anyway_with_flags (abfd, sname, flags);
13075fd0b74Schristos if (asect == NULL)
13175fd0b74Schristos goto punt;
13275fd0b74Schristos
13375fd0b74Schristos asect->size = coreseg.c_size;
13475fd0b74Schristos asect->vma = coreseg.c_addr;
13575fd0b74Schristos asect->filepos = offset;
13675fd0b74Schristos asect->alignment_power = 2;
13775fd0b74Schristos
13875fd0b74Schristos if (CORE_GETFLAG (coreseg) == CORE_CPU)
13975fd0b74Schristos {
14075fd0b74Schristos bfd_size_type wcookie_offset;
14175fd0b74Schristos
14275fd0b74Schristos switch (CORE_GETMID (core))
14375fd0b74Schristos {
14475fd0b74Schristos case M_SPARC_NETBSD:
14575fd0b74Schristos wcookie_offset = SPARC_WCOOKIE_OFFSET;
14675fd0b74Schristos break;
14775fd0b74Schristos case M_SPARC64_OPENBSD:
14875fd0b74Schristos wcookie_offset = SPARC64_WCOOKIE_OFFSET;
14975fd0b74Schristos break;
15075fd0b74Schristos default:
15175fd0b74Schristos wcookie_offset = 0;
15275fd0b74Schristos break;
15375fd0b74Schristos }
15475fd0b74Schristos
15575fd0b74Schristos if (wcookie_offset > 0 && coreseg.c_size > wcookie_offset)
15675fd0b74Schristos {
15775fd0b74Schristos /* Truncate the .reg section. */
15875fd0b74Schristos asect->size = wcookie_offset;
15975fd0b74Schristos
16075fd0b74Schristos /* And create the .wcookie section. */
16175fd0b74Schristos flags = SEC_ALLOC + SEC_HAS_CONTENTS;
16275fd0b74Schristos asect = bfd_make_section_anyway_with_flags (abfd, ".wcookie",
16375fd0b74Schristos flags);
16475fd0b74Schristos if (asect == NULL)
16575fd0b74Schristos goto punt;
16675fd0b74Schristos
16775fd0b74Schristos asect->size = coreseg.c_size - wcookie_offset;
16875fd0b74Schristos asect->vma = 0;
16975fd0b74Schristos asect->filepos = offset + wcookie_offset;
17075fd0b74Schristos asect->alignment_power = 2;
17175fd0b74Schristos }
17275fd0b74Schristos }
17375fd0b74Schristos
17475fd0b74Schristos offset += coreseg.c_size;
17575fd0b74Schristos }
17675fd0b74Schristos
17775fd0b74Schristos /* Set architecture from machine ID. */
17875fd0b74Schristos switch (CORE_GETMID (core))
17975fd0b74Schristos {
18075fd0b74Schristos case M_ALPHA_NETBSD:
18175fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
18275fd0b74Schristos break;
18375fd0b74Schristos
18475fd0b74Schristos case M_ARM6_NETBSD:
18575fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_3);
18675fd0b74Schristos break;
18775fd0b74Schristos
18875fd0b74Schristos case M_X86_64_NETBSD:
18975fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
19075fd0b74Schristos break;
19175fd0b74Schristos
19275fd0b74Schristos case M_386_NETBSD:
19375fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386);
19475fd0b74Schristos break;
19575fd0b74Schristos
19675fd0b74Schristos case M_68K_NETBSD:
19775fd0b74Schristos case M_68K4K_NETBSD:
19875fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
19975fd0b74Schristos break;
20075fd0b74Schristos
20175fd0b74Schristos case M_HPPA_OPENBSD:
20275fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_hppa, bfd_mach_hppa11);
20375fd0b74Schristos break;
20475fd0b74Schristos
20575fd0b74Schristos case M_POWERPC_NETBSD:
20675fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc);
20775fd0b74Schristos break;
20875fd0b74Schristos
20975fd0b74Schristos case M_SPARC_NETBSD:
21075fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
21175fd0b74Schristos break;
21275fd0b74Schristos
21375fd0b74Schristos case M_SPARC64_NETBSD:
21475fd0b74Schristos case M_SPARC64_OPENBSD:
21575fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9);
21675fd0b74Schristos break;
21775fd0b74Schristos
21875fd0b74Schristos case M_VAX_NETBSD:
21975fd0b74Schristos case M_VAX4K_NETBSD:
22075fd0b74Schristos bfd_default_set_arch_mach (abfd, bfd_arch_vax, 0);
22175fd0b74Schristos break;
22275fd0b74Schristos }
22375fd0b74Schristos
22475fd0b74Schristos /* OK, we believe you. You're a core file (sure, sure). */
225*e992f068Schristos return _bfd_no_cleanup;
22675fd0b74Schristos
22775fd0b74Schristos punt:
22875fd0b74Schristos bfd_release (abfd, abfd->tdata.any);
22975fd0b74Schristos abfd->tdata.any = NULL;
23075fd0b74Schristos bfd_section_list_clear (abfd);
23175fd0b74Schristos return 0;
23275fd0b74Schristos }
23375fd0b74Schristos
23475fd0b74Schristos static char*
netbsd_core_file_failing_command(bfd * abfd)23575fd0b74Schristos netbsd_core_file_failing_command (bfd *abfd)
23675fd0b74Schristos {
23775fd0b74Schristos /*return core_command (abfd);*/
23875fd0b74Schristos return abfd->tdata.netbsd_core_data->core.c_name;
23975fd0b74Schristos }
24075fd0b74Schristos
24175fd0b74Schristos static int
netbsd_core_file_failing_signal(bfd * abfd)24275fd0b74Schristos netbsd_core_file_failing_signal (bfd *abfd)
24375fd0b74Schristos {
24475fd0b74Schristos /*return core_signal (abfd);*/
24575fd0b74Schristos return abfd->tdata.netbsd_core_data->core.c_signo;
24675fd0b74Schristos }
24775fd0b74Schristos
24875fd0b74Schristos /* If somebody calls any byte-swapping routines, shoot them. */
24975fd0b74Schristos
25075fd0b74Schristos static void
swap_abort(void)25175fd0b74Schristos swap_abort (void)
25275fd0b74Schristos {
25375fd0b74Schristos /* This way doesn't require any declaration for ANSI to fuck up. */
25475fd0b74Schristos abort ();
25575fd0b74Schristos }
25675fd0b74Schristos
25775fd0b74Schristos #define NO_GET ((bfd_vma (*) (const void *)) swap_abort)
25875fd0b74Schristos #define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
25975fd0b74Schristos #define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
260*e992f068Schristos #define NO_GET64 ((uint64_t (*) (const void *)) swap_abort)
261*e992f068Schristos #define NO_PUT64 ((void (*) (uint64_t, void *)) swap_abort)
262*e992f068Schristos #define NO_GETS64 ((int64_t (*) (const void *)) swap_abort)
26375fd0b74Schristos
26475fd0b74Schristos const bfd_target core_netbsd_vec =
26575fd0b74Schristos {
26675fd0b74Schristos "netbsd-core",
26775fd0b74Schristos bfd_target_unknown_flavour,
26875fd0b74Schristos BFD_ENDIAN_UNKNOWN, /* Target byte order. */
26975fd0b74Schristos BFD_ENDIAN_UNKNOWN, /* Target headers byte order. */
27075fd0b74Schristos (HAS_RELOC | EXEC_P | /* Object flags. */
27175fd0b74Schristos HAS_LINENO | HAS_DEBUG |
27275fd0b74Schristos HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
27375fd0b74Schristos (SEC_HAS_CONTENTS | /* Section flags. */
27475fd0b74Schristos SEC_ALLOC | SEC_LOAD | SEC_RELOC),
27575fd0b74Schristos 0, /* Symbol prefix. */
27675fd0b74Schristos ' ', /* ar_pad_char. */
27775fd0b74Schristos 16, /* ar_max_namelen. */
27875fd0b74Schristos 0, /* Match priority. */
279*e992f068Schristos TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
28075fd0b74Schristos NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data. */
28175fd0b74Schristos NO_GET, NO_GETS, NO_PUT, /* 32 bit data. */
28275fd0b74Schristos NO_GET, NO_GETS, NO_PUT, /* 16 bit data. */
28375fd0b74Schristos NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs. */
28475fd0b74Schristos NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs. */
28575fd0b74Schristos NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs. */
28675fd0b74Schristos
28775fd0b74Schristos { /* bfd_check_format. */
28875fd0b74Schristos _bfd_dummy_target, /* Unknown format. */
28975fd0b74Schristos _bfd_dummy_target, /* Object file. */
29075fd0b74Schristos _bfd_dummy_target, /* Archive. */
29175fd0b74Schristos netbsd_core_file_p /* A core file. */
29275fd0b74Schristos },
29375fd0b74Schristos { /* bfd_set_format. */
294ede78133Schristos _bfd_bool_bfd_false_error,
295ede78133Schristos _bfd_bool_bfd_false_error,
296ede78133Schristos _bfd_bool_bfd_false_error,
297ede78133Schristos _bfd_bool_bfd_false_error
29875fd0b74Schristos },
29975fd0b74Schristos { /* bfd_write_contents. */
300ede78133Schristos _bfd_bool_bfd_false_error,
301ede78133Schristos _bfd_bool_bfd_false_error,
302ede78133Schristos _bfd_bool_bfd_false_error,
303ede78133Schristos _bfd_bool_bfd_false_error
30475fd0b74Schristos },
30575fd0b74Schristos
30675fd0b74Schristos BFD_JUMP_TABLE_GENERIC (_bfd_generic),
30775fd0b74Schristos BFD_JUMP_TABLE_COPY (_bfd_generic),
30875fd0b74Schristos BFD_JUMP_TABLE_CORE (netbsd),
30975fd0b74Schristos BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
31075fd0b74Schristos BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
31175fd0b74Schristos BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
31275fd0b74Schristos BFD_JUMP_TABLE_WRITE (_bfd_generic),
31375fd0b74Schristos BFD_JUMP_TABLE_LINK (_bfd_nolink),
31475fd0b74Schristos BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
31575fd0b74Schristos
31675fd0b74Schristos NULL,
31775fd0b74Schristos
31875fd0b74Schristos NULL /* Backend_data. */
31975fd0b74Schristos };
320