1 /* BFD back end for NetBSD style core files 2 Copyright 1988, 1989, 1991, 1992, 1993, 1996, 1998, 1999, 2000, 2001, 3 2002, 2003, 2004 4 Free Software Foundation, Inc. 5 Written by Paul Kranenburg, EUR 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23 #include "bfd.h" 24 #include "sysdep.h" 25 #include "libbfd.h" 26 #include "libaout.h" /* BFD a.out internal data structures */ 27 28 #include <sys/param.h> 29 #include <sys/dir.h> 30 #include <signal.h> 31 #include <sys/core.h> 32 33 /* The machine ID for OpenBSD/sparc64 and older versions of 34 NetBSD/sparc64 overlaps with M_MIPS1. */ 35 #define M_SPARC64_OPENBSD M_MIPS1 36 37 /* Offset of StackGhost cookie within `struct md_coredump' on 38 OpenBSD/sparc. */ 39 #define SPARC_WCOOKIE_OFFSET 344 40 41 /* Offset of StackGhost cookie within `struct md_coredump' on 42 OpenBSD/sparc64. */ 43 #define SPARC64_WCOOKIE_OFFSET 832 44 45 struct netbsd_core_struct { 46 struct core core; 47 } *rawptr; 48 49 /* forward declarations */ 50 51 static const bfd_target *netbsd_core_file_p 52 PARAMS ((bfd *abfd)); 53 static char *netbsd_core_file_failing_command 54 PARAMS ((bfd *abfd)); 55 static int netbsd_core_file_failing_signal 56 PARAMS ((bfd *abfd)); 57 static bfd_boolean netbsd_core_file_matches_executable_p 58 PARAMS ((bfd *core_bfd, bfd *exec_bfd)); 59 static void swap_abort 60 PARAMS ((void)); 61 62 /* Handle NetBSD-style core dump file. */ 63 64 static const bfd_target * 65 netbsd_core_file_p (abfd) 66 bfd *abfd; 67 68 { 69 int i, val; 70 file_ptr offset; 71 asection *asect; 72 struct core core; 73 struct coreseg coreseg; 74 bfd_size_type amt = sizeof core; 75 76 val = bfd_bread ((void *) &core, amt, abfd); 77 if (val != sizeof core) 78 { 79 /* Too small to be a core file */ 80 bfd_set_error (bfd_error_wrong_format); 81 return 0; 82 } 83 84 if (CORE_GETMAGIC (core) != COREMAGIC) 85 { 86 bfd_set_error (bfd_error_wrong_format); 87 return 0; 88 } 89 90 amt = sizeof (struct netbsd_core_struct); 91 rawptr = (struct netbsd_core_struct *) bfd_zalloc (abfd, amt); 92 if (rawptr == NULL) 93 return 0; 94 95 rawptr->core = core; 96 abfd->tdata.netbsd_core_data = rawptr; 97 98 offset = core.c_hdrsize; 99 for (i = 0; i < core.c_nseg; i++) 100 { 101 const char *sname; 102 flagword flags; 103 104 if (bfd_seek (abfd, offset, SEEK_SET) != 0) 105 goto punt; 106 107 val = bfd_bread ((void *) &coreseg, (bfd_size_type) sizeof coreseg, abfd); 108 if (val != sizeof coreseg) 109 { 110 bfd_set_error (bfd_error_file_truncated); 111 goto punt; 112 } 113 if (CORE_GETMAGIC (coreseg) != CORESEGMAGIC) 114 { 115 bfd_set_error (bfd_error_wrong_format); 116 goto punt; 117 } 118 119 offset += core.c_seghdrsize; 120 121 switch (CORE_GETFLAG (coreseg)) 122 { 123 case CORE_CPU: 124 sname = ".reg"; 125 flags = SEC_ALLOC + SEC_HAS_CONTENTS; 126 break; 127 case CORE_DATA: 128 sname = ".data"; 129 flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; 130 break; 131 case CORE_STACK: 132 sname = ".stack"; 133 flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; 134 break; 135 default: 136 sname = ".unknown"; 137 flags = SEC_ALLOC + SEC_HAS_CONTENTS; 138 break; 139 } 140 asect = bfd_make_section_anyway (abfd, sname); 141 if (asect == NULL) 142 goto punt; 143 144 asect->flags = flags; 145 asect->_raw_size = coreseg.c_size; 146 asect->vma = coreseg.c_addr; 147 asect->filepos = offset; 148 asect->alignment_power = 2; 149 150 if (CORE_GETFLAG (coreseg) == CORE_CPU) 151 { 152 bfd_size_type wcookie_offset; 153 154 switch (CORE_GETMID (core)) 155 { 156 case M_SPARC_NETBSD: 157 wcookie_offset = SPARC_WCOOKIE_OFFSET; 158 break; 159 case M_SPARC64_OPENBSD: 160 wcookie_offset = SPARC64_WCOOKIE_OFFSET; 161 break; 162 default: 163 wcookie_offset = 0; 164 break; 165 } 166 167 if (wcookie_offset > 0 && coreseg.c_size > wcookie_offset) 168 { 169 /* Truncate the .reg section. */ 170 asect->_raw_size = wcookie_offset; 171 172 /* And create the .wcookie section. */ 173 asect = bfd_make_section_anyway (abfd, ".wcookie"); 174 if (asect == NULL) 175 goto punt; 176 177 asect->flags = SEC_ALLOC + SEC_HAS_CONTENTS; 178 asect->_raw_size = coreseg.c_size - wcookie_offset; 179 asect->vma = 0; 180 asect->filepos = offset + wcookie_offset; 181 asect->alignment_power = 2; 182 } 183 } 184 185 offset += coreseg.c_size; 186 } 187 188 /* Set architecture from machine ID. */ 189 switch (CORE_GETMID (core)) 190 { 191 case M_X86_64_NETBSD: 192 bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64); 193 break; 194 195 case M_386_NETBSD: 196 bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386); 197 break; 198 199 case M_68K_NETBSD: 200 case M_68K4K_NETBSD: 201 bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0); 202 break; 203 204 case M_88K_OPENBSD: 205 bfd_default_set_arch_mach (abfd, bfd_arch_m88k, 0); 206 break; 207 208 case M_HPPA_OPENBSD: 209 bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0); 210 break; 211 212 case M_POWERPC_NETBSD: 213 bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc); 214 break; 215 216 case M_SPARC_NETBSD: 217 bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc); 218 break; 219 220 case M_SPARC64_NETBSD: 221 case M_SPARC64_OPENBSD: 222 bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9); 223 break; 224 225 case M_VAX_NETBSD: 226 case M_VAX4K_NETBSD: 227 bfd_default_set_arch_mach (abfd, bfd_arch_vax, 0); 228 break; 229 } 230 231 /* OK, we believe you. You're a core file (sure, sure). */ 232 return abfd->xvec; 233 234 punt: 235 bfd_release (abfd, abfd->tdata.any); 236 abfd->tdata.any = NULL; 237 bfd_section_list_clear (abfd); 238 return 0; 239 } 240 241 static char* 242 netbsd_core_file_failing_command (abfd) 243 bfd *abfd; 244 { 245 /*return core_command (abfd);*/ 246 return abfd->tdata.netbsd_core_data->core.c_name; 247 } 248 249 static int 250 netbsd_core_file_failing_signal (abfd) 251 bfd *abfd; 252 { 253 /*return core_signal (abfd);*/ 254 return abfd->tdata.netbsd_core_data->core.c_signo; 255 } 256 257 static bfd_boolean 258 netbsd_core_file_matches_executable_p (core_bfd, exec_bfd) 259 bfd *core_bfd ATTRIBUTE_UNUSED; 260 bfd *exec_bfd ATTRIBUTE_UNUSED; 261 { 262 return TRUE; /* FIXME, We have no way of telling at this point */ 263 } 264 265 /* If somebody calls any byte-swapping routines, shoot them. */ 266 static void 267 swap_abort () 268 { 269 abort (); /* This way doesn't require any declaration for ANSI to fuck up */ 270 } 271 272 #define NO_GET ((bfd_vma (*) (const void *)) swap_abort) 273 #define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort) 274 #define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort) 275 #define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort) 276 #define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort) 277 #define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort) 278 279 const bfd_target netbsd_core_vec = 280 { 281 "netbsd-core", 282 bfd_target_unknown_flavour, 283 BFD_ENDIAN_UNKNOWN, /* target byte order */ 284 BFD_ENDIAN_UNKNOWN, /* target headers byte order */ 285 (HAS_RELOC | EXEC_P | /* object flags */ 286 HAS_LINENO | HAS_DEBUG | 287 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 288 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 289 0, /* symbol prefix */ 290 ' ', /* ar_pad_char */ 291 16, /* ar_max_namelen */ 292 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data. */ 293 NO_GET, NO_GETS, NO_PUT, /* 32 bit data. */ 294 NO_GET, NO_GETS, NO_PUT, /* 16 bit data. */ 295 NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs. */ 296 NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs. */ 297 NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs. */ 298 299 { /* bfd_check_format */ 300 _bfd_dummy_target, /* unknown format */ 301 _bfd_dummy_target, /* object file */ 302 _bfd_dummy_target, /* archive */ 303 netbsd_core_file_p /* a core file */ 304 }, 305 { /* bfd_set_format */ 306 bfd_false, bfd_false, 307 bfd_false, bfd_false 308 }, 309 { /* bfd_write_contents */ 310 bfd_false, bfd_false, 311 bfd_false, bfd_false 312 }, 313 314 BFD_JUMP_TABLE_GENERIC (_bfd_generic), 315 BFD_JUMP_TABLE_COPY (_bfd_generic), 316 BFD_JUMP_TABLE_CORE (netbsd), 317 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 318 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), 319 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 320 BFD_JUMP_TABLE_WRITE (_bfd_generic), 321 BFD_JUMP_TABLE_LINK (_bfd_nolink), 322 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 323 324 NULL, 325 326 (PTR) 0 /* backend_data */ 327 }; 328