1c88b1d6cSniklas /* BFD back end for NetBSD style core files
2c074d1c9Sdrahn Copyright 1988, 1989, 1991, 1992, 1993, 1996, 1998, 1999, 2000, 2001,
3007c2a45Smiod 2002, 2003, 2004
4b55d4692Sfgsch Free Software Foundation, Inc.
5c88b1d6cSniklas Written by Paul Kranenburg, EUR
6c88b1d6cSniklas
7c88b1d6cSniklas This file is part of BFD, the Binary File Descriptor library.
8c88b1d6cSniklas
9c88b1d6cSniklas This program is free software; you can redistribute it and/or modify
10c88b1d6cSniklas it under the terms of the GNU General Public License as published by
11c88b1d6cSniklas the Free Software Foundation; either version 2 of the License, or
12c88b1d6cSniklas (at your option) any later version.
13c88b1d6cSniklas
14c88b1d6cSniklas This program is distributed in the hope that it will be useful,
15c88b1d6cSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
16c88b1d6cSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17c88b1d6cSniklas GNU General Public License for more details.
18c88b1d6cSniklas
19c88b1d6cSniklas You should have received a copy of the GNU General Public License
20c88b1d6cSniklas along with this program; if not, write to the Free Software
21c88b1d6cSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22c88b1d6cSniklas
23c88b1d6cSniklas #include "bfd.h"
24c88b1d6cSniklas #include "sysdep.h"
25c88b1d6cSniklas #include "libbfd.h"
26c88b1d6cSniklas #include "libaout.h" /* BFD a.out internal data structures */
27c88b1d6cSniklas
28c88b1d6cSniklas #include <sys/param.h>
29c88b1d6cSniklas #include <sys/dir.h>
30c88b1d6cSniklas #include <signal.h>
31c88b1d6cSniklas #include <sys/core.h>
32c88b1d6cSniklas
337839e2deSkettenis /* The machine ID for OpenBSD/sparc64 and older versions of
347839e2deSkettenis NetBSD/sparc64 overlaps with M_MIPS1. */
357839e2deSkettenis #define M_SPARC64_OPENBSD M_MIPS1
367839e2deSkettenis
377839e2deSkettenis /* Offset of StackGhost cookie within `struct md_coredump' on
387839e2deSkettenis OpenBSD/sparc. */
39*31ec35baSkettenis #define SPARC_WCOOKIE_OFFSET 344
40*31ec35baSkettenis
41*31ec35baSkettenis /* Offset of StackGhost cookie within `struct md_coredump' on
42*31ec35baSkettenis OpenBSD/sparc64. */
43*31ec35baSkettenis #define SPARC64_WCOOKIE_OFFSET 832
44c88b1d6cSniklas
45c88b1d6cSniklas struct netbsd_core_struct {
46c88b1d6cSniklas struct core core;
47c88b1d6cSniklas } *rawptr;
48c88b1d6cSniklas
49c88b1d6cSniklas /* forward declarations */
50c88b1d6cSniklas
51c074d1c9Sdrahn static const bfd_target *netbsd_core_file_p
52c074d1c9Sdrahn PARAMS ((bfd *abfd));
53c074d1c9Sdrahn static char *netbsd_core_file_failing_command
54c074d1c9Sdrahn PARAMS ((bfd *abfd));
55c074d1c9Sdrahn static int netbsd_core_file_failing_signal
56c074d1c9Sdrahn PARAMS ((bfd *abfd));
57c074d1c9Sdrahn static bfd_boolean netbsd_core_file_matches_executable_p
58c88b1d6cSniklas PARAMS ((bfd *core_bfd, bfd *exec_bfd));
59c074d1c9Sdrahn static void swap_abort
60c074d1c9Sdrahn PARAMS ((void));
61c88b1d6cSniklas
62c88b1d6cSniklas /* Handle NetBSD-style core dump file. */
63c88b1d6cSniklas
64c88b1d6cSniklas static const bfd_target *
netbsd_core_file_p(abfd)65b305b0f1Sespie netbsd_core_file_p (abfd)
66c88b1d6cSniklas bfd *abfd;
67c88b1d6cSniklas
68c88b1d6cSniklas {
69c074d1c9Sdrahn int i, val;
70c074d1c9Sdrahn file_ptr offset;
717839e2deSkettenis asection *asect;
72c88b1d6cSniklas struct core core;
73c88b1d6cSniklas struct coreseg coreseg;
74c074d1c9Sdrahn bfd_size_type amt = sizeof core;
75c88b1d6cSniklas
76c074d1c9Sdrahn val = bfd_bread ((void *) &core, amt, abfd);
77c074d1c9Sdrahn if (val != sizeof core)
78c074d1c9Sdrahn {
79c88b1d6cSniklas /* Too small to be a core file */
80c88b1d6cSniklas bfd_set_error (bfd_error_wrong_format);
81c88b1d6cSniklas return 0;
82c88b1d6cSniklas }
83c88b1d6cSniklas
84c074d1c9Sdrahn if (CORE_GETMAGIC (core) != COREMAGIC)
85c074d1c9Sdrahn {
86c88b1d6cSniklas bfd_set_error (bfd_error_wrong_format);
87c88b1d6cSniklas return 0;
88c88b1d6cSniklas }
89c88b1d6cSniklas
90c074d1c9Sdrahn amt = sizeof (struct netbsd_core_struct);
91c074d1c9Sdrahn rawptr = (struct netbsd_core_struct *) bfd_zalloc (abfd, amt);
92c074d1c9Sdrahn if (rawptr == NULL)
93c88b1d6cSniklas return 0;
94c88b1d6cSniklas
95c88b1d6cSniklas rawptr->core = core;
96c88b1d6cSniklas abfd->tdata.netbsd_core_data = rawptr;
97c88b1d6cSniklas
98c88b1d6cSniklas offset = core.c_hdrsize;
99c074d1c9Sdrahn for (i = 0; i < core.c_nseg; i++)
100c074d1c9Sdrahn {
101c074d1c9Sdrahn const char *sname;
102c074d1c9Sdrahn flagword flags;
103c88b1d6cSniklas
104c88b1d6cSniklas if (bfd_seek (abfd, offset, SEEK_SET) != 0)
105c88b1d6cSniklas goto punt;
106c88b1d6cSniklas
107c074d1c9Sdrahn val = bfd_bread ((void *) &coreseg, (bfd_size_type) sizeof coreseg, abfd);
108c074d1c9Sdrahn if (val != sizeof coreseg)
109c074d1c9Sdrahn {
110c88b1d6cSniklas bfd_set_error (bfd_error_file_truncated);
111c88b1d6cSniklas goto punt;
112c88b1d6cSniklas }
113c074d1c9Sdrahn if (CORE_GETMAGIC (coreseg) != CORESEGMAGIC)
114c074d1c9Sdrahn {
115c88b1d6cSniklas bfd_set_error (bfd_error_wrong_format);
116c88b1d6cSniklas goto punt;
117c88b1d6cSniklas }
118c88b1d6cSniklas
119c88b1d6cSniklas offset += core.c_seghdrsize;
120c88b1d6cSniklas
121c074d1c9Sdrahn switch (CORE_GETFLAG (coreseg))
122c074d1c9Sdrahn {
123c074d1c9Sdrahn case CORE_CPU:
124c074d1c9Sdrahn sname = ".reg";
125c074d1c9Sdrahn flags = SEC_ALLOC + SEC_HAS_CONTENTS;
126c074d1c9Sdrahn break;
127c074d1c9Sdrahn case CORE_DATA:
128c074d1c9Sdrahn sname = ".data";
129c074d1c9Sdrahn flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
130c074d1c9Sdrahn break;
131c074d1c9Sdrahn case CORE_STACK:
132c074d1c9Sdrahn sname = ".stack";
133c074d1c9Sdrahn flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
134c074d1c9Sdrahn break;
135c074d1c9Sdrahn default:
136c074d1c9Sdrahn sname = ".unknown";
137c074d1c9Sdrahn flags = SEC_ALLOC + SEC_HAS_CONTENTS;
138c074d1c9Sdrahn break;
139c88b1d6cSniklas }
140c074d1c9Sdrahn asect = bfd_make_section_anyway (abfd, sname);
141c074d1c9Sdrahn if (asect == NULL)
142c074d1c9Sdrahn goto punt;
143c88b1d6cSniklas
144c074d1c9Sdrahn asect->flags = flags;
145c88b1d6cSniklas asect->_raw_size = coreseg.c_size;
146c88b1d6cSniklas asect->vma = coreseg.c_addr;
147c88b1d6cSniklas asect->filepos = offset;
148c88b1d6cSniklas asect->alignment_power = 2;
149c074d1c9Sdrahn
150*31ec35baSkettenis if (CORE_GETFLAG (coreseg) == CORE_CPU)
151*31ec35baSkettenis {
152*31ec35baSkettenis bfd_size_type wcookie_offset;
153*31ec35baSkettenis
154*31ec35baSkettenis switch (CORE_GETMID (core))
155*31ec35baSkettenis {
156*31ec35baSkettenis case M_SPARC_NETBSD:
157*31ec35baSkettenis wcookie_offset = SPARC_WCOOKIE_OFFSET;
158*31ec35baSkettenis break;
159*31ec35baSkettenis case M_SPARC64_OPENBSD:
160*31ec35baSkettenis wcookie_offset = SPARC64_WCOOKIE_OFFSET;
161*31ec35baSkettenis break;
162*31ec35baSkettenis default:
163*31ec35baSkettenis wcookie_offset = 0;
164*31ec35baSkettenis break;
165*31ec35baSkettenis }
166*31ec35baSkettenis
167*31ec35baSkettenis if (wcookie_offset > 0 && coreseg.c_size > wcookie_offset)
168c074d1c9Sdrahn {
1697839e2deSkettenis /* Truncate the .reg section. */
170*31ec35baSkettenis asect->_raw_size = wcookie_offset;
1717839e2deSkettenis
1727839e2deSkettenis /* And create the .wcookie section. */
1737839e2deSkettenis asect = bfd_make_section_anyway (abfd, ".wcookie");
1747839e2deSkettenis if (asect == NULL)
175c88b1d6cSniklas goto punt;
1767839e2deSkettenis
1777839e2deSkettenis asect->flags = SEC_ALLOC + SEC_HAS_CONTENTS;
178*31ec35baSkettenis asect->_raw_size = coreseg.c_size - wcookie_offset;
1797839e2deSkettenis asect->vma = 0;
180*31ec35baSkettenis asect->filepos = offset + wcookie_offset;
1817839e2deSkettenis asect->alignment_power = 2;
182c88b1d6cSniklas }
183*31ec35baSkettenis }
1847839e2deSkettenis
1857839e2deSkettenis offset += coreseg.c_size;
1867839e2deSkettenis }
1877839e2deSkettenis
1887839e2deSkettenis /* Set architecture from machine ID. */
1897839e2deSkettenis switch (CORE_GETMID (core))
1907839e2deSkettenis {
1917839e2deSkettenis case M_X86_64_NETBSD:
1927839e2deSkettenis bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
1937839e2deSkettenis break;
1947839e2deSkettenis
1957839e2deSkettenis case M_386_NETBSD:
1967839e2deSkettenis bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386);
1977839e2deSkettenis break;
1987839e2deSkettenis
1997839e2deSkettenis case M_68K_NETBSD:
2007839e2deSkettenis case M_68K4K_NETBSD:
2017839e2deSkettenis bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
2027839e2deSkettenis break;
2037839e2deSkettenis
204eb020baeSkettenis case M_88K_OPENBSD:
205eb020baeSkettenis bfd_default_set_arch_mach (abfd, bfd_arch_m88k, 0);
206eb020baeSkettenis break;
207eb020baeSkettenis
208285d8e81Skettenis case M_HPPA_OPENBSD:
209285d8e81Skettenis bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
210285d8e81Skettenis break;
211285d8e81Skettenis
2127839e2deSkettenis case M_POWERPC_NETBSD:
2137839e2deSkettenis bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc);
2147839e2deSkettenis break;
2157839e2deSkettenis
2167839e2deSkettenis case M_SPARC_NETBSD:
2177839e2deSkettenis bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
2187839e2deSkettenis break;
2197839e2deSkettenis
2207839e2deSkettenis case M_SPARC64_NETBSD:
2217839e2deSkettenis case M_SPARC64_OPENBSD:
2227839e2deSkettenis bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9);
2237839e2deSkettenis break;
2247839e2deSkettenis
2257839e2deSkettenis case M_VAX_NETBSD:
2267839e2deSkettenis case M_VAX4K_NETBSD:
2277839e2deSkettenis bfd_default_set_arch_mach (abfd, bfd_arch_vax, 0);
2287839e2deSkettenis break;
229c88b1d6cSniklas }
230c88b1d6cSniklas
231c88b1d6cSniklas /* OK, we believe you. You're a core file (sure, sure). */
232c88b1d6cSniklas return abfd->xvec;
233c88b1d6cSniklas
234c074d1c9Sdrahn punt:
235c074d1c9Sdrahn bfd_release (abfd, abfd->tdata.any);
236c074d1c9Sdrahn abfd->tdata.any = NULL;
237c074d1c9Sdrahn bfd_section_list_clear (abfd);
238c88b1d6cSniklas return 0;
239c88b1d6cSniklas }
240c88b1d6cSniklas
241c88b1d6cSniklas static char*
netbsd_core_file_failing_command(abfd)242b305b0f1Sespie netbsd_core_file_failing_command (abfd)
243c88b1d6cSniklas bfd *abfd;
244c88b1d6cSniklas {
245c88b1d6cSniklas /*return core_command (abfd);*/
246c88b1d6cSniklas return abfd->tdata.netbsd_core_data->core.c_name;
247c88b1d6cSniklas }
248c88b1d6cSniklas
249c88b1d6cSniklas static int
netbsd_core_file_failing_signal(abfd)250b305b0f1Sespie netbsd_core_file_failing_signal (abfd)
251c88b1d6cSniklas bfd *abfd;
252c88b1d6cSniklas {
253c88b1d6cSniklas /*return core_signal (abfd);*/
254c88b1d6cSniklas return abfd->tdata.netbsd_core_data->core.c_signo;
255c88b1d6cSniklas }
256c88b1d6cSniklas
257c074d1c9Sdrahn static bfd_boolean
netbsd_core_file_matches_executable_p(core_bfd,exec_bfd)258b305b0f1Sespie netbsd_core_file_matches_executable_p (core_bfd, exec_bfd)
259c074d1c9Sdrahn bfd *core_bfd ATTRIBUTE_UNUSED;
260c074d1c9Sdrahn bfd *exec_bfd ATTRIBUTE_UNUSED;
261c88b1d6cSniklas {
262c074d1c9Sdrahn return TRUE; /* FIXME, We have no way of telling at this point */
263c88b1d6cSniklas }
264c88b1d6cSniklas
265c88b1d6cSniklas /* If somebody calls any byte-swapping routines, shoot them. */
266c88b1d6cSniklas static void
swap_abort()267c88b1d6cSniklas swap_abort ()
268c88b1d6cSniklas {
269c88b1d6cSniklas abort (); /* This way doesn't require any declaration for ANSI to fuck up */
270c88b1d6cSniklas }
271007c2a45Smiod
272007c2a45Smiod #define NO_GET ((bfd_vma (*) (const void *)) swap_abort)
273007c2a45Smiod #define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
274007c2a45Smiod #define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
275007c2a45Smiod #define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
276007c2a45Smiod #define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
277007c2a45Smiod #define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
278c88b1d6cSniklas
279c88b1d6cSniklas const bfd_target netbsd_core_vec =
280c88b1d6cSniklas {
281c88b1d6cSniklas "netbsd-core",
282c88b1d6cSniklas bfd_target_unknown_flavour,
283b305b0f1Sespie BFD_ENDIAN_UNKNOWN, /* target byte order */
284b305b0f1Sespie BFD_ENDIAN_UNKNOWN, /* target headers byte order */
285c88b1d6cSniklas (HAS_RELOC | EXEC_P | /* object flags */
286c88b1d6cSniklas HAS_LINENO | HAS_DEBUG |
287b305b0f1Sespie HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
288c88b1d6cSniklas (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
289c88b1d6cSniklas 0, /* symbol prefix */
290c88b1d6cSniklas ' ', /* ar_pad_char */
291c88b1d6cSniklas 16, /* ar_max_namelen */
292007c2a45Smiod NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data. */
293007c2a45Smiod NO_GET, NO_GETS, NO_PUT, /* 32 bit data. */
294007c2a45Smiod NO_GET, NO_GETS, NO_PUT, /* 16 bit data. */
295007c2a45Smiod NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs. */
296007c2a45Smiod NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs. */
297007c2a45Smiod NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs. */
298c88b1d6cSniklas
299c88b1d6cSniklas { /* bfd_check_format */
300c88b1d6cSniklas _bfd_dummy_target, /* unknown format */
301c88b1d6cSniklas _bfd_dummy_target, /* object file */
302c88b1d6cSniklas _bfd_dummy_target, /* archive */
303b305b0f1Sespie netbsd_core_file_p /* a core file */
304c88b1d6cSniklas },
305c88b1d6cSniklas { /* bfd_set_format */
306c88b1d6cSniklas bfd_false, bfd_false,
307c88b1d6cSniklas bfd_false, bfd_false
308c88b1d6cSniklas },
309c88b1d6cSniklas { /* bfd_write_contents */
310c88b1d6cSniklas bfd_false, bfd_false,
311c88b1d6cSniklas bfd_false, bfd_false
312c88b1d6cSniklas },
313c88b1d6cSniklas
314c88b1d6cSniklas BFD_JUMP_TABLE_GENERIC (_bfd_generic),
315c88b1d6cSniklas BFD_JUMP_TABLE_COPY (_bfd_generic),
316b305b0f1Sespie BFD_JUMP_TABLE_CORE (netbsd),
317c88b1d6cSniklas BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
318c88b1d6cSniklas BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
319c88b1d6cSniklas BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
320c88b1d6cSniklas BFD_JUMP_TABLE_WRITE (_bfd_generic),
321c88b1d6cSniklas BFD_JUMP_TABLE_LINK (_bfd_nolink),
322c88b1d6cSniklas BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
323c88b1d6cSniklas
324b305b0f1Sespie NULL,
325b305b0f1Sespie
326c88b1d6cSniklas (PTR) 0 /* backend_data */
327c88b1d6cSniklas };
328