133965Sjdp/* BFD back end for NetBSD style core files
289857Sobrien   Copyright 1988, 1989, 1991, 1992, 1993, 1996, 1998, 1999, 2000, 2001,
3218822Sdim   2002, 2003, 2004, 2005, 2006, 2007
478828Sobrien   Free Software Foundation, Inc.
533965Sjdp   Written by Paul Kranenburg, EUR
633965Sjdp
7218822Sdim   This file is part of BFD, the Binary File Descriptor library.
833965Sjdp
9218822Sdim   This program is free software; you can redistribute it and/or modify
10218822Sdim   it under the terms of the GNU General Public License as published by
11218822Sdim   the Free Software Foundation; either version 2 of the License, or
12218822Sdim   (at your option) any later version.
1333965Sjdp
14218822Sdim   This program is distributed in the hope that it will be useful,
15218822Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
16218822Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17218822Sdim   GNU General Public License for more details.
1833965Sjdp
19218822Sdim   You should have received a copy of the GNU General Public License
20218822Sdim   along with this program; if not, write to the Free Software
21218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2233965Sjdp
23218822Sdim#include "sysdep.h"
2433965Sjdp#include "bfd.h"
2533965Sjdp#include "libbfd.h"
26218822Sdim#include "libaout.h"           /* BFD a.out internal data structures.  */
2733965Sjdp
2833965Sjdp#include <sys/param.h>
2933965Sjdp#include <sys/dir.h>
3033965Sjdp#include <signal.h>
3133965Sjdp#include <sys/core.h>
3233965Sjdp
33218822Sdim/* The machine ID for OpenBSD/sparc64 and older versions of
34218822Sdim   NetBSD/sparc64 overlaps with M_MIPS1.  */
35218822Sdim#define M_SPARC64_OPENBSD	M_MIPS1
3633965Sjdp
37130561Sobrien/* Offset of StackGhost cookie within `struct md_coredump' on
38130561Sobrien   OpenBSD/sparc.  */
39218822Sdim#define SPARC_WCOOKIE_OFFSET	344
40130561Sobrien
41218822Sdim/* Offset of StackGhost cookie within `struct md_coredump' on
42218822Sdim   OpenBSD/sparc64.  */
43218822Sdim#define SPARC64_WCOOKIE_OFFSET	832
4433965Sjdp
45218822Sdim#define netbsd_core_file_matches_executable_p generic_core_file_matches_executable_p
4633965Sjdp
47218822Sdimstruct netbsd_core_struct
48218822Sdim{
49218822Sdim  struct core core;
50218822Sdim} *rawptr;
5133965Sjdp
5233965Sjdp/* Handle NetBSD-style core dump file.  */
5333965Sjdp
5433965Sjdpstatic const bfd_target *
55218822Sdimnetbsd_core_file_p (bfd *abfd)
5633965Sjdp{
57218822Sdim  int val;
58218822Sdim  unsigned i;
5989857Sobrien  file_ptr offset;
60218822Sdim  asection *asect;
6189857Sobrien  struct core core;
6289857Sobrien  struct coreseg coreseg;
6389857Sobrien  bfd_size_type amt = sizeof core;
6433965Sjdp
65218822Sdim  val = bfd_bread (&core, amt, abfd);
6689857Sobrien  if (val != sizeof core)
6789857Sobrien    {
68218822Sdim      /* Too small to be a core file.  */
6989857Sobrien      bfd_set_error (bfd_error_wrong_format);
7089857Sobrien      return 0;
7189857Sobrien    }
7233965Sjdp
7389857Sobrien  if (CORE_GETMAGIC (core) != COREMAGIC)
7489857Sobrien    {
7589857Sobrien      bfd_set_error (bfd_error_wrong_format);
7689857Sobrien      return 0;
7789857Sobrien    }
7833965Sjdp
7989857Sobrien  amt = sizeof (struct netbsd_core_struct);
8089857Sobrien  rawptr = (struct netbsd_core_struct *) bfd_zalloc (abfd, amt);
8189857Sobrien  if (rawptr == NULL)
8289857Sobrien    return 0;
8333965Sjdp
8489857Sobrien  rawptr->core = core;
8589857Sobrien  abfd->tdata.netbsd_core_data = rawptr;
8633965Sjdp
8789857Sobrien  offset = core.c_hdrsize;
8889857Sobrien  for (i = 0; i < core.c_nseg; i++)
8989857Sobrien    {
9089857Sobrien      const char *sname;
9189857Sobrien      flagword flags;
9233965Sjdp
9389857Sobrien      if (bfd_seek (abfd, offset, SEEK_SET) != 0)
9489857Sobrien	goto punt;
9533965Sjdp
96218822Sdim      val = bfd_bread (&coreseg, sizeof coreseg, abfd);
9789857Sobrien      if (val != sizeof coreseg)
9889857Sobrien	{
9989857Sobrien	  bfd_set_error (bfd_error_file_truncated);
10089857Sobrien	  goto punt;
10189857Sobrien	}
10289857Sobrien      if (CORE_GETMAGIC (coreseg) != CORESEGMAGIC)
10389857Sobrien	{
10489857Sobrien	  bfd_set_error (bfd_error_wrong_format);
10589857Sobrien	  goto punt;
10689857Sobrien	}
10733965Sjdp
10889857Sobrien      offset += core.c_seghdrsize;
10933965Sjdp
11089857Sobrien      switch (CORE_GETFLAG (coreseg))
11189857Sobrien	{
11289857Sobrien	case CORE_CPU:
11389857Sobrien	  sname = ".reg";
11489857Sobrien	  flags = SEC_ALLOC + SEC_HAS_CONTENTS;
11589857Sobrien	  break;
11689857Sobrien	case CORE_DATA:
11789857Sobrien	  sname = ".data";
11889857Sobrien	  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
11989857Sobrien	  break;
12089857Sobrien	case CORE_STACK:
12189857Sobrien	  sname = ".stack";
12289857Sobrien	  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
12389857Sobrien	  break;
12489857Sobrien	default:
12589857Sobrien	  sname = ".unknown";
12689857Sobrien	  flags = SEC_ALLOC + SEC_HAS_CONTENTS;
12789857Sobrien	  break;
12889857Sobrien	}
129218822Sdim      asect = bfd_make_section_anyway_with_flags (abfd, sname, flags);
13089857Sobrien      if (asect == NULL)
13189857Sobrien	goto punt;
13233965Sjdp
133218822Sdim      asect->size = coreseg.c_size;
13489857Sobrien      asect->vma = coreseg.c_addr;
13589857Sobrien      asect->filepos = offset;
13689857Sobrien      asect->alignment_power = 2;
13733965Sjdp
138218822Sdim      if (CORE_GETFLAG (coreseg) == CORE_CPU)
139130561Sobrien	{
140218822Sdim	  bfd_size_type wcookie_offset;
141130561Sobrien
142218822Sdim	  switch (CORE_GETMID (core))
143218822Sdim	    {
144218822Sdim	    case M_SPARC_NETBSD:
145218822Sdim	      wcookie_offset = SPARC_WCOOKIE_OFFSET;
146218822Sdim	      break;
147218822Sdim	    case M_SPARC64_OPENBSD:
148218822Sdim	      wcookie_offset = SPARC64_WCOOKIE_OFFSET;
149218822Sdim	      break;
150218822Sdim	    default:
151218822Sdim	      wcookie_offset = 0;
152218822Sdim	      break;
153218822Sdim	    }
154130561Sobrien
155218822Sdim	  if (wcookie_offset > 0 && coreseg.c_size > wcookie_offset)
156218822Sdim	    {
157218822Sdim	      /* Truncate the .reg section.  */
158218822Sdim	      asect->size = wcookie_offset;
159218822Sdim
160218822Sdim	      /* And create the .wcookie section.  */
161218822Sdim	      flags = SEC_ALLOC + SEC_HAS_CONTENTS;
162218822Sdim	      asect = bfd_make_section_anyway_with_flags (abfd, ".wcookie",
163218822Sdim							  flags);
164218822Sdim	      if (asect == NULL)
165218822Sdim		goto punt;
166218822Sdim
167218822Sdim	      asect->size = coreseg.c_size - wcookie_offset;
168218822Sdim	      asect->vma = 0;
169218822Sdim	      asect->filepos = offset + wcookie_offset;
170218822Sdim	      asect->alignment_power = 2;
171218822Sdim	    }
172130561Sobrien	}
173130561Sobrien
17489857Sobrien      offset += coreseg.c_size;
175218822Sdim    }
17689857Sobrien
177218822Sdim  /* Set architecture from machine ID.  */
178218822Sdim  switch (CORE_GETMID (core))
179218822Sdim    {
180218822Sdim    case M_ALPHA_NETBSD:
181218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
182218822Sdim      break;
183218822Sdim
184218822Sdim    case M_ARM6_NETBSD:
185218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_3);
186218822Sdim      break;
187218822Sdim
188218822Sdim    case M_X86_64_NETBSD:
189218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
190218822Sdim      break;
191218822Sdim
192218822Sdim    case M_386_NETBSD:
193218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386);
194218822Sdim      break;
195218822Sdim
196218822Sdim    case M_68K_NETBSD:
197218822Sdim    case M_68K4K_NETBSD:
198218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
199218822Sdim      break;
200218822Sdim
201218822Sdim    case M_88K_OPENBSD:
202218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_m88k, 0);
203218822Sdim      break;
204218822Sdim
205218822Sdim    case M_HPPA_OPENBSD:
206218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_hppa, bfd_mach_hppa11);
207218822Sdim      break;
208218822Sdim
209218822Sdim    case M_POWERPC_NETBSD:
210218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc);
211218822Sdim      break;
212218822Sdim
213218822Sdim    case M_SPARC_NETBSD:
214218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
215218822Sdim      break;
216218822Sdim
217218822Sdim    case M_SPARC64_NETBSD:
218218822Sdim    case M_SPARC64_OPENBSD:
219218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9);
220218822Sdim      break;
221218822Sdim
222218822Sdim    case M_VAX_NETBSD:
223218822Sdim    case M_VAX4K_NETBSD:
224218822Sdim      bfd_default_set_arch_mach (abfd, bfd_arch_vax, 0);
225218822Sdim      break;
22689857Sobrien    }
22733965Sjdp
22889857Sobrien  /* OK, we believe you.  You're a core file (sure, sure).  */
22989857Sobrien  return abfd->xvec;
23033965Sjdp
23189857Sobrien punt:
23289857Sobrien  bfd_release (abfd, abfd->tdata.any);
23389857Sobrien  abfd->tdata.any = NULL;
23489857Sobrien  bfd_section_list_clear (abfd);
23589857Sobrien  return 0;
23633965Sjdp}
23733965Sjdp
23833965Sjdpstatic char*
239218822Sdimnetbsd_core_file_failing_command (bfd *abfd)
24033965Sjdp{
241218822Sdim  /*return core_command (abfd);*/
24233965Sjdp  return abfd->tdata.netbsd_core_data->core.c_name;
24333965Sjdp}
24433965Sjdp
24533965Sjdpstatic int
246218822Sdimnetbsd_core_file_failing_signal (bfd *abfd)
24733965Sjdp{
24833965Sjdp  /*return core_signal (abfd);*/
24933965Sjdp  return abfd->tdata.netbsd_core_data->core.c_signo;
25033965Sjdp}
25133965Sjdp
25233965Sjdp/* If somebody calls any byte-swapping routines, shoot them.  */
253218822Sdim
25433965Sjdpstatic void
255218822Sdimswap_abort (void)
25633965Sjdp{
257218822Sdim /* This way doesn't require any declaration for ANSI to fuck up.  */
258218822Sdim  abort ();
25933965Sjdp}
26033965Sjdp
261130561Sobrien#define	NO_GET ((bfd_vma (*) (const void *)) swap_abort)
262130561Sobrien#define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
263130561Sobrien#define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
264130561Sobrien#define	NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
265130561Sobrien#define	NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
266130561Sobrien#define	NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
267130561Sobrien
26833965Sjdpconst bfd_target netbsd_core_vec =
26933965Sjdp  {
27033965Sjdp    "netbsd-core",
27133965Sjdp    bfd_target_unknown_flavour,
272218822Sdim    BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
273218822Sdim    BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
274218822Sdim    (HAS_RELOC | EXEC_P |	/* Object flags.  */
27533965Sjdp     HAS_LINENO | HAS_DEBUG |
27638889Sjdp     HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
277218822Sdim    (SEC_HAS_CONTENTS |		/* Section flags.  */
278218822Sdim     SEC_ALLOC | SEC_LOAD | SEC_RELOC),
279218822Sdim    0,				/* Symbol prefix.  */
280218822Sdim    ' ',			/* ar_pad_char.  */
281218822Sdim    16,				/* ar_max_namelen.  */
282130561Sobrien    NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data.  */
283130561Sobrien    NO_GET, NO_GETS, NO_PUT,		/* 32 bit data.  */
284130561Sobrien    NO_GET, NO_GETS, NO_PUT,		/* 16 bit data.  */
285130561Sobrien    NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs.  */
286130561Sobrien    NO_GET, NO_GETS, NO_PUT,		/* 32 bit hdrs.  */
287130561Sobrien    NO_GET, NO_GETS, NO_PUT,		/* 16 bit hdrs.  */
28833965Sjdp
289218822Sdim    {					/* bfd_check_format.  */
290218822Sdim      _bfd_dummy_target,		/* Unknown format.  */
291218822Sdim      _bfd_dummy_target,		/* Object file.  */
292218822Sdim      _bfd_dummy_target,		/* Archive.  */
293218822Sdim      netbsd_core_file_p		/* A core file.  */
29433965Sjdp    },
295218822Sdim    {					/* bfd_set_format.  */
296130561Sobrien      bfd_false, bfd_false,
297130561Sobrien      bfd_false, bfd_false
29833965Sjdp    },
299218822Sdim    {					/* bfd_write_contents.  */
300130561Sobrien      bfd_false, bfd_false,
301130561Sobrien      bfd_false, bfd_false
30233965Sjdp    },
30377298Sobrien
304130561Sobrien    BFD_JUMP_TABLE_GENERIC (_bfd_generic),
305130561Sobrien    BFD_JUMP_TABLE_COPY (_bfd_generic),
306130561Sobrien    BFD_JUMP_TABLE_CORE (netbsd),
307130561Sobrien    BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
308130561Sobrien    BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
309130561Sobrien    BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
310130561Sobrien    BFD_JUMP_TABLE_WRITE (_bfd_generic),
311130561Sobrien    BFD_JUMP_TABLE_LINK (_bfd_nolink),
312130561Sobrien    BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
31333965Sjdp
31460484Sobrien    NULL,
31577298Sobrien
316218822Sdim    (PTR) 0			        /* Backend_data.  */
317130561Sobrien  };
318