1/* BFD back-end for Irix core files. 2 Copyright 1993, 1994, 1996, 1999, 2001, 2002, 2004, 2006 3 Free Software Foundation, Inc. 4 Written by Stu Grossman, Cygnus Support. 5 Converted to back-end form by Ian Lance Taylor, Cygnus Support 6 7 This file is part of BFD, the Binary File Descriptor library. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23/* This file can only be compiled on systems which use Irix style core 24 files (namely, Irix 4 and Irix 5, so far). */ 25 26#include "bfd.h" 27#include "sysdep.h" 28#include "libbfd.h" 29 30#ifdef IRIX_CORE 31 32#include <core.out.h> 33 34struct sgi_core_struct 35{ 36 int sig; 37 char cmd[CORE_NAMESIZE]; 38}; 39 40#define core_hdr(bfd) ((bfd)->tdata.sgi_core_data) 41#define core_signal(bfd) (core_hdr(bfd)->sig) 42#define core_command(bfd) (core_hdr(bfd)->cmd) 43 44#define irix_core_core_file_matches_executable_p generic_core_file_matches_executable_p 45 46static asection *make_bfd_asection 47 (bfd *, const char *, flagword, bfd_size_type, bfd_vma, file_ptr); 48 49/* Helper function for irix_core_core_file_p: 50 32-bit and 64-bit versions. */ 51 52#ifdef CORE_MAGIC64 53static int 54do_sections64 (bfd *abfd, struct coreout *coreout) 55{ 56 struct vmap64 vmap; 57 char *secname; 58 int i, val; 59 60 for (i = 0; i < coreout->c_nvmap; i++) 61 { 62 val = bfd_bread ((PTR) &vmap, (bfd_size_type) sizeof vmap, abfd); 63 if (val != sizeof vmap) 64 break; 65 66 switch (vmap.v_type) 67 { 68 case VDATA: 69 secname = ".data"; 70 break; 71 case VSTACK: 72 secname = ".stack"; 73 break; 74#ifdef VMAPFILE 75 case VMAPFILE: 76 secname = ".mapfile"; 77 break; 78#endif 79 default: 80 continue; 81 } 82 83 /* A file offset of zero means that the 84 section is not contained in the corefile. */ 85 if (vmap.v_offset == 0) 86 continue; 87 88 if (!make_bfd_asection (abfd, secname, 89 SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, 90 vmap.v_len, vmap.v_vaddr, vmap.v_offset)) 91 /* Fail. */ 92 return 0; 93 } 94 95 return 1; 96} 97#endif 98 99/* 32-bit version. */ 100 101static int 102do_sections (bfd *abfd, struct coreout *coreout) 103{ 104 struct vmap vmap; 105 char *secname; 106 int i, val; 107 108 for (i = 0; i < coreout->c_nvmap; i++) 109 { 110 val = bfd_bread ((PTR) &vmap, (bfd_size_type) sizeof vmap, abfd); 111 if (val != sizeof vmap) 112 break; 113 114 switch (vmap.v_type) 115 { 116 case VDATA: 117 secname = ".data"; 118 break; 119 case VSTACK: 120 secname = ".stack"; 121 break; 122#ifdef VMAPFILE 123 case VMAPFILE: 124 secname = ".mapfile"; 125 break; 126#endif 127 default: 128 continue; 129 } 130 131 /* A file offset of zero means that the 132 section is not contained in the corefile. */ 133 if (vmap.v_offset == 0) 134 continue; 135 136 if (!make_bfd_asection (abfd, secname, 137 SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, 138 vmap.v_len, vmap.v_vaddr, vmap.v_offset)) 139 /* Fail. */ 140 return 0; 141 } 142 return 1; 143} 144 145static asection * 146make_bfd_asection (bfd *abfd, 147 const char *name, 148 flagword flags, 149 bfd_size_type size, 150 bfd_vma vma, 151 file_ptr filepos) 152{ 153 asection *asect; 154 155 asect = bfd_make_section_anyway_with_flags (abfd, name, flags); 156 if (!asect) 157 return NULL; 158 159 asect->size = size; 160 asect->vma = vma; 161 asect->filepos = filepos; 162 asect->alignment_power = 4; 163 164 return asect; 165} 166 167static const bfd_target * 168irix_core_core_file_p (bfd *abfd) 169{ 170 int val; 171 struct coreout coreout; 172 struct idesc *idg, *idf, *ids; 173 bfd_size_type amt; 174 175 val = bfd_bread ((PTR) &coreout, (bfd_size_type) sizeof coreout, abfd); 176 if (val != sizeof coreout) 177 { 178 if (bfd_get_error () != bfd_error_system_call) 179 bfd_set_error (bfd_error_wrong_format); 180 return 0; 181 } 182 183 if (coreout.c_version != CORE_VERSION1) 184 return 0; 185 186 /* Have we got a corefile? */ 187 switch (coreout.c_magic) 188 { 189 case CORE_MAGIC: break; 190#ifdef CORE_MAGIC64 191 case CORE_MAGIC64: break; 192#endif 193#ifdef CORE_MAGICN32 194 case CORE_MAGICN32: break; 195#endif 196 default: return 0; /* Un-identifiable or not corefile. */ 197 } 198 199 amt = sizeof (struct sgi_core_struct); 200 core_hdr (abfd) = (struct sgi_core_struct *) bfd_zalloc (abfd, amt); 201 if (!core_hdr (abfd)) 202 return NULL; 203 204 strncpy (core_command (abfd), coreout.c_name, CORE_NAMESIZE); 205 core_signal (abfd) = coreout.c_sigcause; 206 207 if (bfd_seek (abfd, coreout.c_vmapoffset, SEEK_SET) != 0) 208 goto fail; 209 210 /* Process corefile sections. */ 211#ifdef CORE_MAGIC64 212 if (coreout.c_magic == (int) CORE_MAGIC64) 213 { 214 if (! do_sections64 (abfd, & coreout)) 215 goto fail; 216 } 217 else 218#endif 219 if (! do_sections (abfd, & coreout)) 220 goto fail; 221 222 /* Make sure that the regs are contiguous within the core file. */ 223 224 idg = &coreout.c_idesc[I_GPREGS]; 225 idf = &coreout.c_idesc[I_FPREGS]; 226 ids = &coreout.c_idesc[I_SPECREGS]; 227 228 if (idg->i_offset + idg->i_len != idf->i_offset 229 || idf->i_offset + idf->i_len != ids->i_offset) 230 goto fail; /* Can't deal with non-contig regs */ 231 232 if (bfd_seek (abfd, idg->i_offset, SEEK_SET) != 0) 233 goto fail; 234 235 if (!make_bfd_asection (abfd, ".reg", 236 SEC_HAS_CONTENTS, 237 idg->i_len + idf->i_len + ids->i_len, 238 0, 239 idg->i_offset)) 240 goto fail; 241 242 /* OK, we believe you. You're a core file (sure, sure). */ 243 bfd_default_set_arch_mach (abfd, bfd_arch_mips, 0); 244 245 return abfd->xvec; 246 247 fail: 248 bfd_release (abfd, core_hdr (abfd)); 249 core_hdr (abfd) = NULL; 250 bfd_section_list_clear (abfd); 251 return NULL; 252} 253 254static char * 255irix_core_core_file_failing_command (bfd *abfd) 256{ 257 return core_command (abfd); 258} 259 260static int 261irix_core_core_file_failing_signal (bfd *abfd) 262{ 263 return core_signal (abfd); 264} 265 266/* If somebody calls any byte-swapping routines, shoot them. */ 267static void 268swap_abort(void) 269{ 270 abort(); /* This way doesn't require any declaration for ANSI to fuck up */ 271} 272 273#define NO_GET ((bfd_vma (*) (const void *)) swap_abort) 274#define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort) 275#define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort) 276#define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort) 277#define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort) 278#define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort) 279 280const bfd_target irix_core_vec = 281 { 282 "irix-core", 283 bfd_target_unknown_flavour, 284 BFD_ENDIAN_BIG, /* target byte order */ 285 BFD_ENDIAN_BIG, /* target headers byte order */ 286 (HAS_RELOC | EXEC_P | /* object flags */ 287 HAS_LINENO | HAS_DEBUG | 288 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 289 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 290 0, /* symbol prefix */ 291 ' ', /* ar_pad_char */ 292 16, /* ar_max_namelen */ 293 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data */ 294 NO_GET, NO_GETS, NO_PUT, /* 32 bit data */ 295 NO_GET, NO_GETS, NO_PUT, /* 16 bit data */ 296 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs */ 297 NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs */ 298 NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs */ 299 300 { /* bfd_check_format */ 301 _bfd_dummy_target, /* unknown format */ 302 _bfd_dummy_target, /* object file */ 303 _bfd_dummy_target, /* archive */ 304 irix_core_core_file_p /* a core file */ 305 }, 306 { /* bfd_set_format */ 307 bfd_false, bfd_false, 308 bfd_false, bfd_false 309 }, 310 { /* bfd_write_contents */ 311 bfd_false, bfd_false, 312 bfd_false, bfd_false 313 }, 314 315 BFD_JUMP_TABLE_GENERIC (_bfd_generic), 316 BFD_JUMP_TABLE_COPY (_bfd_generic), 317 BFD_JUMP_TABLE_CORE (irix_core), 318 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 319 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), 320 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 321 BFD_JUMP_TABLE_WRITE (_bfd_generic), 322 BFD_JUMP_TABLE_LINK (_bfd_nolink), 323 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 324 325 NULL, 326 327 (PTR) 0 /* backend_data */ 328 }; 329 330#endif /* IRIX_CORE */ 331