ptrace-core.c revision 89857
133965Sjdp/* BFD backend for core files which use the ptrace_user structure
289857Sobrien   Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2002
378828Sobrien   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
2333965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2433965Sjdp
2533965Sjdp#ifdef PTRACE_CORE
2633965Sjdp
2733965Sjdp#include "bfd.h"
2833965Sjdp#include "sysdep.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));
5233965Sjdpchar *		ptrace_unix_core_file_failing_command PARAMS ((bfd *abfd));
5333965Sjdpint		ptrace_unix_core_file_failing_signal PARAMS ((bfd *abfd));
5433965Sjdpboolean		ptrace_unix_core_file_matches_executable_p
5533965Sjdp			 PARAMS ((bfd *core_bfd, bfd *exec_bfd));
5633965Sjdpstatic void	swap_abort PARAMS ((void));
5733965Sjdp
5833965Sjdp/* ARGSUSED */
5933965Sjdpconst bfd_target *
6033965Sjdpptrace_unix_core_file_p (abfd)
6133965Sjdp     bfd *abfd;
6233965Sjdp
6333965Sjdp{
6433965Sjdp  int val;
6533965Sjdp  struct ptrace_user u;
6633965Sjdp  struct trad_core_struct *rawptr;
6789857Sobrien  bfd_size_type amt;
6833965Sjdp
6989857Sobrien  val = bfd_bread ((void *)&u, (bfd_size_type) sizeof u, abfd);
7077298Sobrien  if (val != sizeof u || u.pt_magic != _BCS_PTRACE_MAGIC
7133965Sjdp      || u.pt_rev != _BCS_PTRACE_REV)
7233965Sjdp    {
7333965Sjdp      /* Too small to be a core file */
7433965Sjdp      bfd_set_error (bfd_error_wrong_format);
7533965Sjdp      return 0;
7633965Sjdp    }
7733965Sjdp
7833965Sjdp  /* OK, we believe you.  You're a core file (sure, sure).  */
7933965Sjdp
8033965Sjdp  /* Allocate both the upage and the struct core_data at once, so
8133965Sjdp     a single free() will free them both.  */
8289857Sobrien  amt = sizeof (struct trad_core_struct);
8389857Sobrien  rawptr = (struct trad_core_struct *) bfd_zalloc (abfd, amt);
8433965Sjdp
8533965Sjdp  if (rawptr == NULL)
8633965Sjdp    return 0;
8777298Sobrien
8833965Sjdp  abfd->tdata.trad_core_data = rawptr;
8933965Sjdp
9033965Sjdp  rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
9133965Sjdp
9289857Sobrien  /* Create the sections.  */
9333965Sjdp
9489857Sobrien  core_stacksec (abfd) = bfd_make_section_anyway (abfd, ".stack");
9533965Sjdp  if (core_stacksec (abfd) == NULL)
9689857Sobrien    goto fail;
9789857Sobrien  core_datasec (abfd) = bfd_make_section_anyway (abfd, ".data");
9833965Sjdp  if (core_datasec (abfd) == NULL)
9989857Sobrien    goto fail;
10089857Sobrien  core_regsec (abfd) = bfd_make_section_anyway (abfd, ".reg");
10133965Sjdp  if (core_regsec (abfd) == NULL)
10289857Sobrien    goto fail;
10333965Sjdp
10433965Sjdp  /* FIXME:  Need to worry about shared memory, library data, and library
10533965Sjdp     text.  I don't think that any of these things are supported on the
10677298Sobrien     system on which I am developing this for though.  */
10733965Sjdp
10833965Sjdp  core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
10933965Sjdp  core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
11033965Sjdp  core_regsec (abfd)->flags = SEC_HAS_CONTENTS;
11133965Sjdp
11233965Sjdp  core_datasec (abfd)->_raw_size =  u.pt_dsize;
11333965Sjdp  core_stacksec (abfd)->_raw_size = u.pt_ssize;
11477298Sobrien  core_regsec (abfd)->_raw_size = sizeof (u);
11533965Sjdp
11633965Sjdp  core_datasec (abfd)->vma = u.pt_o_data_start;
11733965Sjdp  core_stacksec (abfd)->vma = USRSTACK - u.pt_ssize;
11877298Sobrien  core_regsec (abfd)->vma = 0 - sizeof (u);	/* see trad-core.c */
11933965Sjdp
12033965Sjdp  core_datasec (abfd)->filepos = (int) u.pt_dataptr;
12133965Sjdp  core_stacksec (abfd)->filepos = (int) (u.pt_dataptr + u.pt_dsize);
12233965Sjdp  core_regsec (abfd)->filepos = 0; /* Register segment is ptrace_user */
12333965Sjdp
12433965Sjdp  /* Align to word at least */
12533965Sjdp  core_stacksec (abfd)->alignment_power = 2;
12633965Sjdp  core_datasec (abfd)->alignment_power = 2;
12733965Sjdp  core_regsec (abfd)->alignment_power = 2;
12833965Sjdp
12989857Sobrien  return abfd->xvec;
13033965Sjdp
13189857Sobrien fail:
13289857Sobrien  bfd_release (abfd, abfd->tdata.any);
13389857Sobrien  abfd->tdata.any = NULL;
13489857Sobrien  bfd_section_list_clear (abfd);
13589857Sobrien  return NULL;
13633965Sjdp}
13733965Sjdp
13833965Sjdpchar *
13933965Sjdpptrace_unix_core_file_failing_command (abfd)
14033965Sjdp     bfd *abfd;
14133965Sjdp{
14233965Sjdp  char *com = abfd->tdata.trad_core_data->u.pt_comm;
14333965Sjdp  if (*com)
14433965Sjdp    return com;
14533965Sjdp  else
14633965Sjdp    return 0;
14733965Sjdp}
14833965Sjdp
14933965Sjdp/* ARGSUSED */
15033965Sjdpint
15133965Sjdpptrace_unix_core_file_failing_signal (abfd)
15233965Sjdp     bfd *abfd;
15333965Sjdp{
15433965Sjdp  return abfd->tdata.trad_core_data->u.pt_sigframe.sig_num;
15533965Sjdp}
15633965Sjdp
15733965Sjdp/* ARGSUSED */
15833965Sjdpboolean
15933965Sjdpptrace_unix_core_file_matches_executable_p  (core_bfd, exec_bfd)
16033965Sjdp     bfd *core_bfd, *exec_bfd;
16133965Sjdp{
16277298Sobrien  /* FIXME: Use pt_timdat field of the ptrace_user structure to match
16333965Sjdp     the date of the executable */
16433965Sjdp  return true;
16533965Sjdp}
16633965Sjdp
16733965Sjdp/* If somebody calls any byte-swapping routines, shoot them.  */
16833965Sjdpstatic void
16977298Sobrienswap_abort ()
17033965Sjdp{
17177298Sobrien  abort (); /* This way doesn't require any declaration for ANSI to fuck up */
17233965Sjdp}
17333965Sjdp#define	NO_GET	((bfd_vma (*) PARAMS ((   const bfd_byte *))) swap_abort )
17433965Sjdp#define	NO_PUT	((void    (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
17533965Sjdp#define	NO_SIGNED_GET \
17633965Sjdp  ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
17733965Sjdp
17833965Sjdpconst bfd_target ptrace_core_vec =
17933965Sjdp  {
18033965Sjdp    "trad-core",
18133965Sjdp    bfd_target_unknown_flavour,
18233965Sjdp    BFD_ENDIAN_UNKNOWN,		/* target byte order */
18333965Sjdp    BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
18433965Sjdp    (HAS_RELOC | EXEC_P |	/* object flags */
18533965Sjdp     HAS_LINENO | HAS_DEBUG |
18633965Sjdp     HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
18733965Sjdp    (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
18833965Sjdp    0,			                                   /* symbol prefix */
18933965Sjdp    ' ',						   /* ar_pad_char */
19033965Sjdp    16,							   /* ar_max_namelen */
19133965Sjdp    NO_GET, NO_SIGNED_GET, NO_PUT,	/* 64 bit data */
19233965Sjdp    NO_GET, NO_SIGNED_GET, NO_PUT,	/* 32 bit data */
19333965Sjdp    NO_GET, NO_SIGNED_GET, NO_PUT,	/* 16 bit data */
19433965Sjdp    NO_GET, NO_SIGNED_GET, NO_PUT,	/* 64 bit hdrs */
19533965Sjdp    NO_GET, NO_SIGNED_GET, NO_PUT,	/* 32 bit hdrs */
19633965Sjdp    NO_GET, NO_SIGNED_GET, NO_PUT,	/* 16 bit hdrs */
19733965Sjdp
19833965Sjdp    {				/* bfd_check_format */
19933965Sjdp     _bfd_dummy_target,		/* unknown format */
20033965Sjdp     _bfd_dummy_target,		/* object file */
20133965Sjdp     _bfd_dummy_target,		/* archive */
20233965Sjdp     ptrace_unix_core_file_p	/* a core file */
20333965Sjdp    },
20433965Sjdp    {				/* bfd_set_format */
20533965Sjdp     bfd_false, bfd_false,
20633965Sjdp     bfd_false, bfd_false
20733965Sjdp    },
20833965Sjdp    {				/* bfd_write_contents */
20933965Sjdp     bfd_false, bfd_false,
21033965Sjdp     bfd_false, bfd_false
21133965Sjdp    },
21277298Sobrien
21333965Sjdp       BFD_JUMP_TABLE_GENERIC (_bfd_generic),
21433965Sjdp       BFD_JUMP_TABLE_COPY (_bfd_generic),
21533965Sjdp       BFD_JUMP_TABLE_CORE (ptrace_unix),
21633965Sjdp       BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
21733965Sjdp       BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
21833965Sjdp       BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
21933965Sjdp       BFD_JUMP_TABLE_WRITE (_bfd_generic),
22033965Sjdp       BFD_JUMP_TABLE_LINK (_bfd_nolink),
22133965Sjdp       BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
22233965Sjdp
22360484Sobrien    NULL,
22477298Sobrien
22533965Sjdp    (PTR) 0			/* backend_data */
22633965Sjdp};
22733965Sjdp
22833965Sjdp#endif /* PTRACE_CORE */
229