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