xref: /openbsd-src/gnu/usr.bin/binutils/bfd/netbsd-core.c (revision 31ec35ba769d6bc6b0f746006f8727a08d8efe1d)
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