133965Sjdp/* BFD backend for core files which use the ptrace_user structure
2218822Sdim   Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2002, 2003, 2004,
3218822Sdim   2006, 2007  Free Software Foundation, Inc.
433965Sjdp   The structure of this file is based on trad-core.c written by John Gilmore
533965Sjdp   of Cygnus Support.
633965Sjdp   Modified to work with the ptrace_user structure by Kevin A. Buettner.
733965Sjdp   (Longterm it may be better to merge this file with trad-core.c)
833965Sjdp
933965SjdpThis file is part of BFD, the Binary File Descriptor library.
1033965Sjdp
1133965SjdpThis program is free software; you can redistribute it and/or modify
1233965Sjdpit under the terms of the GNU General Public License as published by
1333965Sjdpthe Free Software Foundation; either version 2 of the License, or
1433965Sjdp(at your option) any later version.
1533965Sjdp
1633965SjdpThis program is distributed in the hope that it will be useful,
1733965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1833965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1933965SjdpGNU General Public License for more details.
2033965Sjdp
2133965SjdpYou should have received a copy of the GNU General Public License
2233965Sjdpalong with this program; if not, write to the Free Software
23218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2433965Sjdp
2533965Sjdp#ifdef PTRACE_CORE
2633965Sjdp
27218822Sdim#include "sysdep.h"
2833965Sjdp#include "bfd.h"
2933965Sjdp#include "libbfd.h"
3033965Sjdp
3133965Sjdp#include <sys/param.h>
3233965Sjdp#include <sys/dir.h>
3333965Sjdp#include <signal.h>
3433965Sjdp#include <sys/ptrace.h>
3533965Sjdp
3633965Sjdpstruct trad_core_struct
3733965Sjdp  {
3833965Sjdp    asection *data_section;
3933965Sjdp    asection *stack_section;
4033965Sjdp    asection *reg_section;
4133965Sjdp    struct ptrace_user u;
4233965Sjdp  };
4333965Sjdp
4433965Sjdp#define core_upage(bfd) (&((bfd)->tdata.trad_core_data->u))
4533965Sjdp#define core_datasec(bfd) ((bfd)->tdata.trad_core_data->data_section)
4633965Sjdp#define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section)
4733965Sjdp#define core_regsec(bfd) ((bfd)->tdata.trad_core_data->reg_section)
4833965Sjdp
4933965Sjdp/* forward declarations */
5033965Sjdp
5133965Sjdpconst bfd_target *ptrace_unix_core_file_p PARAMS ((bfd *abfd));
52130561Sobrienchar * ptrace_unix_core_file_failing_command PARAMS ((bfd *abfd));
53130561Sobrienint ptrace_unix_core_file_failing_signal PARAMS ((bfd *abfd));
54218822Sdim#define ptrace_unix_core_file_matches_executable_p generic_core_file_matches_executable_p
55130561Sobrienstatic void swap_abort PARAMS ((void));
5633965Sjdp
5733965Sjdpconst bfd_target *
5833965Sjdpptrace_unix_core_file_p (abfd)
5933965Sjdp     bfd *abfd;
6033965Sjdp
6133965Sjdp{
6233965Sjdp  int val;
6333965Sjdp  struct ptrace_user u;
6433965Sjdp  struct trad_core_struct *rawptr;
6589857Sobrien  bfd_size_type amt;
66218822Sdim  flagword flags;
6733965Sjdp
6889857Sobrien  val = bfd_bread ((void *)&u, (bfd_size_type) sizeof u, abfd);
6977298Sobrien  if (val != sizeof u || u.pt_magic != _BCS_PTRACE_MAGIC
7033965Sjdp      || u.pt_rev != _BCS_PTRACE_REV)
7133965Sjdp    {
7233965Sjdp      /* Too small to be a core file */
7333965Sjdp      bfd_set_error (bfd_error_wrong_format);
7433965Sjdp      return 0;
7533965Sjdp    }
7633965Sjdp
7733965Sjdp  /* OK, we believe you.  You're a core file (sure, sure).  */
7833965Sjdp
7933965Sjdp  /* Allocate both the upage and the struct core_data at once, so
8033965Sjdp     a single free() will free them both.  */
8189857Sobrien  amt = sizeof (struct trad_core_struct);
8289857Sobrien  rawptr = (struct trad_core_struct *) bfd_zalloc (abfd, amt);
8333965Sjdp
8433965Sjdp  if (rawptr == NULL)
8533965Sjdp    return 0;
8677298Sobrien
8733965Sjdp  abfd->tdata.trad_core_data = rawptr;
8833965Sjdp
8933965Sjdp  rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
9033965Sjdp
9189857Sobrien  /* Create the sections.  */
9233965Sjdp
93218822Sdim  flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
94218822Sdim  core_stacksec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".stack",
95218822Sdim							     flags);
9633965Sjdp  if (core_stacksec (abfd) == NULL)
9789857Sobrien    goto fail;
98218822Sdim  core_datasec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".data",
99218822Sdim							    flags);
10033965Sjdp  if (core_datasec (abfd) == NULL)
10189857Sobrien    goto fail;
102218822Sdim  core_regsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg",
103218822Sdim							   SEC_HAS_CONTENTS);
10433965Sjdp  if (core_regsec (abfd) == NULL)
10589857Sobrien    goto fail;
10633965Sjdp
10733965Sjdp  /* FIXME:  Need to worry about shared memory, library data, and library
10833965Sjdp     text.  I don't think that any of these things are supported on the
10977298Sobrien     system on which I am developing this for though.  */
11033965Sjdp
111218822Sdim  core_datasec (abfd)->size =  u.pt_dsize;
112218822Sdim  core_stacksec (abfd)->size = u.pt_ssize;
113218822Sdim  core_regsec (abfd)->size = sizeof (u);
11433965Sjdp
11533965Sjdp  core_datasec (abfd)->vma = u.pt_o_data_start;
11633965Sjdp  core_stacksec (abfd)->vma = USRSTACK - u.pt_ssize;
11777298Sobrien  core_regsec (abfd)->vma = 0 - sizeof (u);	/* see trad-core.c */
11833965Sjdp
11933965Sjdp  core_datasec (abfd)->filepos = (int) u.pt_dataptr;
12033965Sjdp  core_stacksec (abfd)->filepos = (int) (u.pt_dataptr + u.pt_dsize);
12133965Sjdp  core_regsec (abfd)->filepos = 0; /* Register segment is ptrace_user */
12233965Sjdp
12333965Sjdp  /* Align to word at least */
12433965Sjdp  core_stacksec (abfd)->alignment_power = 2;
12533965Sjdp  core_datasec (abfd)->alignment_power = 2;
12633965Sjdp  core_regsec (abfd)->alignment_power = 2;
12733965Sjdp
12889857Sobrien  return abfd->xvec;
12933965Sjdp
13089857Sobrien fail:
13189857Sobrien  bfd_release (abfd, abfd->tdata.any);
13289857Sobrien  abfd->tdata.any = NULL;
13389857Sobrien  bfd_section_list_clear (abfd);
13489857Sobrien  return NULL;
13533965Sjdp}
13633965Sjdp
13733965Sjdpchar *
13833965Sjdpptrace_unix_core_file_failing_command (abfd)
13933965Sjdp     bfd *abfd;
14033965Sjdp{
14133965Sjdp  char *com = abfd->tdata.trad_core_data->u.pt_comm;
14233965Sjdp  if (*com)
14333965Sjdp    return com;
14433965Sjdp  else
14533965Sjdp    return 0;
14633965Sjdp}
14733965Sjdp
14833965Sjdpint
14933965Sjdpptrace_unix_core_file_failing_signal (abfd)
15033965Sjdp     bfd *abfd;
15133965Sjdp{
15233965Sjdp  return abfd->tdata.trad_core_data->u.pt_sigframe.sig_num;
15333965Sjdp}
15433965Sjdp
15533965Sjdp/* If somebody calls any byte-swapping routines, shoot them.  */
15633965Sjdpstatic void
15777298Sobrienswap_abort ()
15833965Sjdp{
15977298Sobrien  abort (); /* This way doesn't require any declaration for ANSI to fuck up */
16033965Sjdp}
16133965Sjdp
162130561Sobrien#define	NO_GET ((bfd_vma (*) (const void *)) swap_abort)
163130561Sobrien#define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
164130561Sobrien#define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
165130561Sobrien#define	NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
166130561Sobrien#define	NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
167130561Sobrien#define	NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
168130561Sobrien
16933965Sjdpconst bfd_target ptrace_core_vec =
17033965Sjdp  {
17133965Sjdp    "trad-core",
17233965Sjdp    bfd_target_unknown_flavour,
17333965Sjdp    BFD_ENDIAN_UNKNOWN,		/* target byte order */
17433965Sjdp    BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
17533965Sjdp    (HAS_RELOC | EXEC_P |	/* object flags */
17633965Sjdp     HAS_LINENO | HAS_DEBUG |
17733965Sjdp     HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
17833965Sjdp    (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
17933965Sjdp    0,			                                   /* symbol prefix */
18033965Sjdp    ' ',						   /* ar_pad_char */
18133965Sjdp    16,							   /* ar_max_namelen */
182130561Sobrien    NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data */
183130561Sobrien    NO_GET, NO_GETS, NO_PUT,		/* 32 bit data */
184130561Sobrien    NO_GET, NO_GETS, NO_PUT,		/* 16 bit data */
185130561Sobrien    NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs */
186130561Sobrien    NO_GET, NO_GETS, NO_PUT,		/* 32 bit hdrs */
187130561Sobrien    NO_GET, NO_GETS, NO_PUT,		/* 16 bit hdrs */
18833965Sjdp
18933965Sjdp    {				/* bfd_check_format */
190130561Sobrien      _bfd_dummy_target,		/* unknown format */
191130561Sobrien      _bfd_dummy_target,		/* object file */
192130561Sobrien      _bfd_dummy_target,		/* archive */
193130561Sobrien      ptrace_unix_core_file_p		/* a core file */
19433965Sjdp    },
19533965Sjdp    {				/* bfd_set_format */
196130561Sobrien      bfd_false, bfd_false,
197130561Sobrien      bfd_false, bfd_false
19833965Sjdp    },
19933965Sjdp    {				/* bfd_write_contents */
200130561Sobrien      bfd_false, bfd_false,
201130561Sobrien      bfd_false, bfd_false
20233965Sjdp    },
20377298Sobrien
204130561Sobrien    BFD_JUMP_TABLE_GENERIC (_bfd_generic),
205130561Sobrien    BFD_JUMP_TABLE_COPY (_bfd_generic),
206130561Sobrien    BFD_JUMP_TABLE_CORE (ptrace_unix),
207130561Sobrien    BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
208130561Sobrien    BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
209130561Sobrien    BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
210130561Sobrien    BFD_JUMP_TABLE_WRITE (_bfd_generic),
211130561Sobrien    BFD_JUMP_TABLE_LINK (_bfd_nolink),
212130561Sobrien    BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
21333965Sjdp
21460484Sobrien    NULL,
21577298Sobrien
21633965Sjdp    (PTR) 0			/* backend_data */
217130561Sobrien  };
21833965Sjdp
21933965Sjdp#endif /* PTRACE_CORE */
220