xref: /openbsd-src/gnu/usr.bin/binutils/bfd/irix-core.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* BFD back-end for Irix core files.
2*007c2a45Smiod    Copyright 1993, 1994, 1996, 1999, 2001, 2002, 2004
3c074d1c9Sdrahn    Free Software Foundation, Inc.
42159047fSniklas    Written by Stu Grossman, Cygnus Support.
52159047fSniklas    Converted to back-end form by Ian Lance Taylor, Cygnus Support
62159047fSniklas 
72159047fSniklas    This file is part of BFD, the Binary File Descriptor library.
82159047fSniklas 
92159047fSniklas    This program is free software; you can redistribute it and/or modify
102159047fSniklas    it under the terms of the GNU General Public License as published by
112159047fSniklas    the Free Software Foundation; either version 2 of the License, or
122159047fSniklas    (at your option) any later version.
132159047fSniklas 
142159047fSniklas    This program is distributed in the hope that it will be useful,
152159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
162159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
172159047fSniklas    GNU General Public License for more details.
182159047fSniklas 
192159047fSniklas    You should have received a copy of the GNU General Public License
202159047fSniklas    along with this program; if not, write to the Free Software
212159047fSniklas    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
222159047fSniklas 
232159047fSniklas /* This file can only be compiled on systems which use Irix style core
242159047fSniklas    files (namely, Irix 4 and Irix 5, so far).  */
252159047fSniklas 
262159047fSniklas #include "bfd.h"
272159047fSniklas #include "sysdep.h"
282159047fSniklas #include "libbfd.h"
292159047fSniklas 
302159047fSniklas #ifdef IRIX_CORE
312159047fSniklas 
322159047fSniklas #include <core.out.h>
332159047fSniklas 
342159047fSniklas struct sgi_core_struct
352159047fSniklas {
362159047fSniklas   int sig;
372159047fSniklas   char cmd[CORE_NAMESIZE];
382159047fSniklas };
392159047fSniklas 
402159047fSniklas #define core_hdr(bfd) ((bfd)->tdata.sgi_core_data)
412159047fSniklas #define core_signal(bfd) (core_hdr(bfd)->sig)
422159047fSniklas #define core_command(bfd) (core_hdr(bfd)->cmd)
432159047fSniklas 
44e93f7393Sniklas static asection *make_bfd_asection
45c074d1c9Sdrahn   PARAMS ((bfd *, const char *, flagword, bfd_size_type, bfd_vma, file_ptr));
46c074d1c9Sdrahn static const bfd_target *irix_core_core_file_p
47c074d1c9Sdrahn   PARAMS ((bfd *));
48c074d1c9Sdrahn static char *irix_core_core_file_failing_command
49c074d1c9Sdrahn   PARAMS ((bfd *));
50c074d1c9Sdrahn static int irix_core_core_file_failing_signal
51c074d1c9Sdrahn   PARAMS ((bfd *));
52c074d1c9Sdrahn static bfd_boolean irix_core_core_file_matches_executable_p
53e93f7393Sniklas   PARAMS ((bfd *, bfd *));
54c074d1c9Sdrahn static void swap_abort
55c074d1c9Sdrahn   PARAMS ((void));
56c074d1c9Sdrahn #ifdef CORE_MAGIC64
57c074d1c9Sdrahn static int do_sections64
58c074d1c9Sdrahn   PARAMS ((bfd *, struct coreout *));
59c074d1c9Sdrahn #endif
60c074d1c9Sdrahn static int do_sections
61c074d1c9Sdrahn   PARAMS ((bfd *, struct coreout *));
62c074d1c9Sdrahn 
63c074d1c9Sdrahn /* Helper function for irix_core_core_file_p:
64c074d1c9Sdrahn    32-bit and 64-bit versions.  */
65c074d1c9Sdrahn 
66c074d1c9Sdrahn #ifdef CORE_MAGIC64
67c074d1c9Sdrahn static int
do_sections64(abfd,coreout)68c074d1c9Sdrahn do_sections64 (abfd, coreout)
69c074d1c9Sdrahn      bfd * abfd;
70c074d1c9Sdrahn      struct coreout * coreout;
71c074d1c9Sdrahn {
72c074d1c9Sdrahn   struct vmap64 vmap;
73c074d1c9Sdrahn   char *secname;
74c074d1c9Sdrahn   int i, val;
75c074d1c9Sdrahn 
76c074d1c9Sdrahn   for (i = 0; i < coreout->c_nvmap; i++)
77c074d1c9Sdrahn     {
78c074d1c9Sdrahn       val = bfd_bread ((PTR) &vmap, (bfd_size_type) sizeof vmap, abfd);
79c074d1c9Sdrahn       if (val != sizeof vmap)
80c074d1c9Sdrahn 	break;
81c074d1c9Sdrahn 
82c074d1c9Sdrahn       switch (vmap.v_type)
83c074d1c9Sdrahn 	{
84c074d1c9Sdrahn 	case VDATA:
85c074d1c9Sdrahn 	  secname = ".data";
86c074d1c9Sdrahn 	  break;
87c074d1c9Sdrahn 	case VSTACK:
88c074d1c9Sdrahn 	  secname = ".stack";
89c074d1c9Sdrahn 	  break;
90c074d1c9Sdrahn #ifdef VMAPFILE
91c074d1c9Sdrahn 	case VMAPFILE:
92c074d1c9Sdrahn 	  secname = ".mapfile";
93c074d1c9Sdrahn 	  break;
94c074d1c9Sdrahn #endif
95c074d1c9Sdrahn 	default:
96c074d1c9Sdrahn 	  continue;
97c074d1c9Sdrahn 	}
98c074d1c9Sdrahn 
99c074d1c9Sdrahn       /* A file offset of zero means that the
100c074d1c9Sdrahn 	 section is not contained in the corefile.  */
101c074d1c9Sdrahn       if (vmap.v_offset == 0)
102c074d1c9Sdrahn 	continue;
103c074d1c9Sdrahn 
104c074d1c9Sdrahn       if (!make_bfd_asection (abfd, secname,
105c074d1c9Sdrahn 			      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
106c074d1c9Sdrahn 			      vmap.v_len, vmap.v_vaddr, vmap.v_offset))
107c074d1c9Sdrahn 	/* Fail.  */
108c074d1c9Sdrahn 	return 0;
109c074d1c9Sdrahn     }
110c074d1c9Sdrahn 
111c074d1c9Sdrahn   return 1;
112c074d1c9Sdrahn }
113c074d1c9Sdrahn #endif
114c074d1c9Sdrahn 
115c074d1c9Sdrahn /* 32-bit version.  */
116c074d1c9Sdrahn 
117c074d1c9Sdrahn static int
do_sections(abfd,coreout)118c074d1c9Sdrahn do_sections (abfd, coreout)
119c074d1c9Sdrahn      bfd * abfd;
120c074d1c9Sdrahn      struct coreout *coreout;
121c074d1c9Sdrahn {
122c074d1c9Sdrahn   struct vmap vmap;
123c074d1c9Sdrahn   char *secname;
124c074d1c9Sdrahn   int i, val;
125c074d1c9Sdrahn 
126c074d1c9Sdrahn   for (i = 0; i < coreout->c_nvmap; i++)
127c074d1c9Sdrahn     {
128c074d1c9Sdrahn       val = bfd_bread ((PTR) &vmap, (bfd_size_type) sizeof vmap, abfd);
129c074d1c9Sdrahn       if (val != sizeof vmap)
130c074d1c9Sdrahn 	break;
131c074d1c9Sdrahn 
132c074d1c9Sdrahn       switch (vmap.v_type)
133c074d1c9Sdrahn 	{
134c074d1c9Sdrahn 	case VDATA:
135c074d1c9Sdrahn 	  secname = ".data";
136c074d1c9Sdrahn 	  break;
137c074d1c9Sdrahn 	case VSTACK:
138c074d1c9Sdrahn 	  secname = ".stack";
139c074d1c9Sdrahn 	  break;
140c074d1c9Sdrahn #ifdef VMAPFILE
141c074d1c9Sdrahn 	case VMAPFILE:
142c074d1c9Sdrahn 	  secname = ".mapfile";
143c074d1c9Sdrahn 	  break;
144c074d1c9Sdrahn #endif
145c074d1c9Sdrahn 	default:
146c074d1c9Sdrahn 	  continue;
147c074d1c9Sdrahn 	}
148c074d1c9Sdrahn 
149c074d1c9Sdrahn       /* A file offset of zero means that the
150c074d1c9Sdrahn 	 section is not contained in the corefile.  */
151c074d1c9Sdrahn       if (vmap.v_offset == 0)
152c074d1c9Sdrahn 	continue;
153c074d1c9Sdrahn 
154c074d1c9Sdrahn       if (!make_bfd_asection (abfd, secname,
155c074d1c9Sdrahn 			      SEC_ALLOC | SEC_LOAD+SEC_HAS_CONTENTS,
156c074d1c9Sdrahn 			      vmap.v_len, vmap.v_vaddr, vmap.v_offset))
157c074d1c9Sdrahn 	/* Fail.  */
158c074d1c9Sdrahn 	return 0;
159c074d1c9Sdrahn     }
160c074d1c9Sdrahn   return 1;
161c074d1c9Sdrahn }
162e93f7393Sniklas 
1632159047fSniklas static asection *
make_bfd_asection(abfd,name,flags,_raw_size,vma,filepos)1642159047fSniklas make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
1652159047fSniklas      bfd *abfd;
166c074d1c9Sdrahn      const char *name;
1672159047fSniklas      flagword flags;
1682159047fSniklas      bfd_size_type _raw_size;
1692159047fSniklas      bfd_vma vma;
1702159047fSniklas      file_ptr filepos;
1712159047fSniklas {
1722159047fSniklas   asection *asect;
1732159047fSniklas 
1742159047fSniklas   asect = bfd_make_section_anyway (abfd, name);
1752159047fSniklas   if (!asect)
1762159047fSniklas     return NULL;
1772159047fSniklas 
1782159047fSniklas   asect->flags = flags;
1792159047fSniklas   asect->_raw_size = _raw_size;
1802159047fSniklas   asect->vma = vma;
1812159047fSniklas   asect->filepos = filepos;
1822159047fSniklas   asect->alignment_power = 4;
1832159047fSniklas 
1842159047fSniklas   return asect;
1852159047fSniklas }
1862159047fSniklas 
1872159047fSniklas static const bfd_target *
irix_core_core_file_p(abfd)1882159047fSniklas irix_core_core_file_p (abfd)
1892159047fSniklas      bfd *abfd;
1902159047fSniklas {
1912159047fSniklas   int val;
1922159047fSniklas   struct coreout coreout;
1932159047fSniklas   struct idesc *idg, *idf, *ids;
194c074d1c9Sdrahn   bfd_size_type amt;
1952159047fSniklas 
196c074d1c9Sdrahn   val = bfd_bread ((PTR) &coreout, (bfd_size_type) sizeof coreout, abfd);
1972159047fSniklas   if (val != sizeof coreout)
1982159047fSniklas     {
1992159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
2002159047fSniklas 	bfd_set_error (bfd_error_wrong_format);
2012159047fSniklas       return 0;
2022159047fSniklas     }
2032159047fSniklas 
204c074d1c9Sdrahn   if (coreout.c_version != CORE_VERSION1)
2052159047fSniklas     return 0;
2062159047fSniklas 
207c074d1c9Sdrahn   /* Have we got a corefile?  */
208c074d1c9Sdrahn   switch (coreout.c_magic)
209c074d1c9Sdrahn     {
210c074d1c9Sdrahn     case CORE_MAGIC:	break;
211c074d1c9Sdrahn #ifdef CORE_MAGIC64
212c074d1c9Sdrahn     case CORE_MAGIC64:	break;
213c074d1c9Sdrahn #endif
214c074d1c9Sdrahn #ifdef CORE_MAGICN32
215c074d1c9Sdrahn     case CORE_MAGICN32:	break;
216c074d1c9Sdrahn #endif
217c074d1c9Sdrahn     default:		return 0;	/* Un-identifiable or not corefile.  */
218c074d1c9Sdrahn     }
219c074d1c9Sdrahn 
220c074d1c9Sdrahn   amt = sizeof (struct sgi_core_struct);
221c074d1c9Sdrahn   core_hdr (abfd) = (struct sgi_core_struct *) bfd_zalloc (abfd, amt);
2222159047fSniklas   if (!core_hdr (abfd))
2232159047fSniklas     return NULL;
2242159047fSniklas 
2252159047fSniklas   strncpy (core_command (abfd), coreout.c_name, CORE_NAMESIZE);
2262159047fSniklas   core_signal (abfd) = coreout.c_sigcause;
2272159047fSniklas 
2282159047fSniklas   if (bfd_seek (abfd, coreout.c_vmapoffset, SEEK_SET) != 0)
229c074d1c9Sdrahn     goto fail;
2302159047fSniklas 
231c074d1c9Sdrahn   /* Process corefile sections.  */
232c074d1c9Sdrahn #ifdef CORE_MAGIC64
233c074d1c9Sdrahn   if (coreout.c_magic == (int) CORE_MAGIC64)
2342159047fSniklas     {
235c074d1c9Sdrahn       if (! do_sections64 (abfd, & coreout))
236c074d1c9Sdrahn 	goto fail;
237c074d1c9Sdrahn     }
238c074d1c9Sdrahn   else
2392159047fSniklas #endif
240c074d1c9Sdrahn     if (! do_sections (abfd, & coreout))
241c074d1c9Sdrahn       goto fail;
2422159047fSniklas 
2432159047fSniklas   /* Make sure that the regs are contiguous within the core file.  */
2442159047fSniklas 
2452159047fSniklas   idg = &coreout.c_idesc[I_GPREGS];
2462159047fSniklas   idf = &coreout.c_idesc[I_FPREGS];
2472159047fSniklas   ids = &coreout.c_idesc[I_SPECREGS];
2482159047fSniklas 
2492159047fSniklas   if (idg->i_offset + idg->i_len != idf->i_offset
2502159047fSniklas       || idf->i_offset + idf->i_len != ids->i_offset)
251c074d1c9Sdrahn     goto fail;			/* Can't deal with non-contig regs */
2522159047fSniklas 
2532159047fSniklas   if (bfd_seek (abfd, idg->i_offset, SEEK_SET) != 0)
254c074d1c9Sdrahn     goto fail;
2552159047fSniklas 
256c074d1c9Sdrahn   if (!make_bfd_asection (abfd, ".reg",
2572159047fSniklas 			  SEC_HAS_CONTENTS,
2582159047fSniklas 			  idg->i_len + idf->i_len + ids->i_len,
2592159047fSniklas 			  0,
260c074d1c9Sdrahn 			  idg->i_offset))
261c074d1c9Sdrahn     goto fail;
2622159047fSniklas 
2632159047fSniklas   /* OK, we believe you.  You're a core file (sure, sure).  */
264b55d4692Sfgsch   bfd_default_set_arch_mach (abfd, bfd_arch_mips, 0);
2652159047fSniklas 
2662159047fSniklas   return abfd->xvec;
267c074d1c9Sdrahn 
268c074d1c9Sdrahn  fail:
269c074d1c9Sdrahn   bfd_release (abfd, core_hdr (abfd));
270c074d1c9Sdrahn   core_hdr (abfd) = NULL;
271c074d1c9Sdrahn   bfd_section_list_clear (abfd);
272c074d1c9Sdrahn   return NULL;
2732159047fSniklas }
2742159047fSniklas 
2752159047fSniklas static char *
irix_core_core_file_failing_command(abfd)2762159047fSniklas irix_core_core_file_failing_command (abfd)
2772159047fSniklas      bfd *abfd;
2782159047fSniklas {
2792159047fSniklas   return core_command (abfd);
2802159047fSniklas }
2812159047fSniklas 
2822159047fSniklas static int
irix_core_core_file_failing_signal(abfd)2832159047fSniklas irix_core_core_file_failing_signal (abfd)
2842159047fSniklas      bfd *abfd;
2852159047fSniklas {
2862159047fSniklas   return core_signal (abfd);
2872159047fSniklas }
2882159047fSniklas 
289c074d1c9Sdrahn static bfd_boolean
irix_core_core_file_matches_executable_p(core_bfd,exec_bfd)2902159047fSniklas irix_core_core_file_matches_executable_p (core_bfd, exec_bfd)
2912159047fSniklas      bfd *core_bfd, *exec_bfd;
2922159047fSniklas {
293c074d1c9Sdrahn   return TRUE;			/* XXX - FIXME */
2942159047fSniklas }
2952159047fSniklas 
2962159047fSniklas /* If somebody calls any byte-swapping routines, shoot them.  */
297e93f7393Sniklas static void
swap_abort()2982159047fSniklas swap_abort()
2992159047fSniklas {
3002159047fSniklas   abort(); /* This way doesn't require any declaration for ANSI to fuck up */
3012159047fSniklas }
302*007c2a45Smiod 
303*007c2a45Smiod #define	NO_GET ((bfd_vma (*) (const void *)) swap_abort)
304*007c2a45Smiod #define	NO_PUT ((void (*) (bfd_vma, void *)) swap_abort)
305*007c2a45Smiod #define	NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort)
306*007c2a45Smiod #define	NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort)
307*007c2a45Smiod #define	NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort)
308*007c2a45Smiod #define	NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort)
3092159047fSniklas 
3102159047fSniklas const bfd_target irix_core_vec =
3112159047fSniklas   {
3122159047fSniklas     "irix-core",
3132159047fSniklas     bfd_target_unknown_flavour,
314c88b1d6cSniklas     BFD_ENDIAN_BIG,		/* target byte order */
315c88b1d6cSniklas     BFD_ENDIAN_BIG,		/* target headers byte order */
3162159047fSniklas     (HAS_RELOC | EXEC_P |	/* object flags */
3172159047fSniklas      HAS_LINENO | HAS_DEBUG |
3182159047fSniklas      HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
3192159047fSniklas     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
3202159047fSniklas     0,			                                   /* symbol prefix */
3212159047fSniklas     ' ',						   /* ar_pad_char */
3222159047fSniklas     16,							   /* ar_max_namelen */
323*007c2a45Smiod     NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit data */
324*007c2a45Smiod     NO_GET, NO_GETS, NO_PUT,		/* 32 bit data */
325*007c2a45Smiod     NO_GET, NO_GETS, NO_PUT,		/* 16 bit data */
326*007c2a45Smiod     NO_GET64, NO_GETS64, NO_PUT64,	/* 64 bit hdrs */
327*007c2a45Smiod     NO_GET, NO_GETS, NO_PUT,		/* 32 bit hdrs */
328*007c2a45Smiod     NO_GET, NO_GETS, NO_PUT,		/* 16 bit hdrs */
3292159047fSniklas 
3302159047fSniklas     {				/* bfd_check_format */
3312159047fSniklas       _bfd_dummy_target,		/* unknown format */
3322159047fSniklas       _bfd_dummy_target,		/* object file */
3332159047fSniklas       _bfd_dummy_target,		/* archive */
3342159047fSniklas       irix_core_core_file_p		/* a core file */
3352159047fSniklas     },
3362159047fSniklas     {				/* bfd_set_format */
3372159047fSniklas       bfd_false, bfd_false,
3382159047fSniklas       bfd_false, bfd_false
3392159047fSniklas     },
3402159047fSniklas     {				/* bfd_write_contents */
3412159047fSniklas       bfd_false, bfd_false,
3422159047fSniklas       bfd_false, bfd_false
3432159047fSniklas     },
3442159047fSniklas 
3452159047fSniklas     BFD_JUMP_TABLE_GENERIC (_bfd_generic),
3462159047fSniklas     BFD_JUMP_TABLE_COPY (_bfd_generic),
3472159047fSniklas     BFD_JUMP_TABLE_CORE (irix_core),
3482159047fSniklas     BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
349c074d1c9Sdrahn     BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
3502159047fSniklas     BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
3512159047fSniklas     BFD_JUMP_TABLE_WRITE (_bfd_generic),
3522159047fSniklas     BFD_JUMP_TABLE_LINK (_bfd_nolink),
3532159047fSniklas     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
3542159047fSniklas 
355b305b0f1Sespie     NULL,
356b305b0f1Sespie 
3572159047fSniklas     (PTR) 0			/* backend_data */
3582159047fSniklas   };
3592159047fSniklas 
3602159047fSniklas #endif /* IRIX_CORE */
361