133965Sjdp/* BFD back end for NetBSD style core files 289857Sobrien Copyright 1988, 1989, 1991, 1992, 1993, 1996, 1998, 1999, 2000, 2001, 3218822Sdim 2002, 2003, 2004, 2005, 2006, 2007 478828Sobrien Free Software Foundation, Inc. 533965Sjdp Written by Paul Kranenburg, EUR 633965Sjdp 7218822Sdim This file is part of BFD, the Binary File Descriptor library. 833965Sjdp 9218822Sdim This program is free software; you can redistribute it and/or modify 10218822Sdim it under the terms of the GNU General Public License as published by 11218822Sdim the Free Software Foundation; either version 2 of the License, or 12218822Sdim (at your option) any later version. 1333965Sjdp 14218822Sdim This program is distributed in the hope that it will be useful, 15218822Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 16218822Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17218822Sdim GNU General Public License for more details. 1833965Sjdp 19218822Sdim You should have received a copy of the GNU General Public License 20218822Sdim along with this program; if not, write to the Free Software 21218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2233965Sjdp 23218822Sdim#include "sysdep.h" 2433965Sjdp#include "bfd.h" 2533965Sjdp#include "libbfd.h" 26218822Sdim#include "libaout.h" /* BFD a.out internal data structures. */ 2733965Sjdp 2833965Sjdp#include <sys/param.h> 2933965Sjdp#include <sys/dir.h> 3033965Sjdp#include <signal.h> 3133965Sjdp#include <sys/core.h> 3233965Sjdp 33218822Sdim/* The machine ID for OpenBSD/sparc64 and older versions of 34218822Sdim NetBSD/sparc64 overlaps with M_MIPS1. */ 35218822Sdim#define M_SPARC64_OPENBSD M_MIPS1 3633965Sjdp 37130561Sobrien/* Offset of StackGhost cookie within `struct md_coredump' on 38130561Sobrien OpenBSD/sparc. */ 39218822Sdim#define SPARC_WCOOKIE_OFFSET 344 40130561Sobrien 41218822Sdim/* Offset of StackGhost cookie within `struct md_coredump' on 42218822Sdim OpenBSD/sparc64. */ 43218822Sdim#define SPARC64_WCOOKIE_OFFSET 832 4433965Sjdp 45218822Sdim#define netbsd_core_file_matches_executable_p generic_core_file_matches_executable_p 4633965Sjdp 47218822Sdimstruct netbsd_core_struct 48218822Sdim{ 49218822Sdim struct core core; 50218822Sdim} *rawptr; 5133965Sjdp 5233965Sjdp/* Handle NetBSD-style core dump file. */ 5333965Sjdp 5433965Sjdpstatic const bfd_target * 55218822Sdimnetbsd_core_file_p (bfd *abfd) 5633965Sjdp{ 57218822Sdim int val; 58218822Sdim unsigned i; 5989857Sobrien file_ptr offset; 60218822Sdim asection *asect; 6189857Sobrien struct core core; 6289857Sobrien struct coreseg coreseg; 6389857Sobrien bfd_size_type amt = sizeof core; 6433965Sjdp 65218822Sdim val = bfd_bread (&core, amt, abfd); 6689857Sobrien if (val != sizeof core) 6789857Sobrien { 68218822Sdim /* Too small to be a core file. */ 6989857Sobrien bfd_set_error (bfd_error_wrong_format); 7089857Sobrien return 0; 7189857Sobrien } 7233965Sjdp 7389857Sobrien if (CORE_GETMAGIC (core) != COREMAGIC) 7489857Sobrien { 7589857Sobrien bfd_set_error (bfd_error_wrong_format); 7689857Sobrien return 0; 7789857Sobrien } 7833965Sjdp 7989857Sobrien amt = sizeof (struct netbsd_core_struct); 8089857Sobrien rawptr = (struct netbsd_core_struct *) bfd_zalloc (abfd, amt); 8189857Sobrien if (rawptr == NULL) 8289857Sobrien return 0; 8333965Sjdp 8489857Sobrien rawptr->core = core; 8589857Sobrien abfd->tdata.netbsd_core_data = rawptr; 8633965Sjdp 8789857Sobrien offset = core.c_hdrsize; 8889857Sobrien for (i = 0; i < core.c_nseg; i++) 8989857Sobrien { 9089857Sobrien const char *sname; 9189857Sobrien flagword flags; 9233965Sjdp 9389857Sobrien if (bfd_seek (abfd, offset, SEEK_SET) != 0) 9489857Sobrien goto punt; 9533965Sjdp 96218822Sdim val = bfd_bread (&coreseg, sizeof coreseg, abfd); 9789857Sobrien if (val != sizeof coreseg) 9889857Sobrien { 9989857Sobrien bfd_set_error (bfd_error_file_truncated); 10089857Sobrien goto punt; 10189857Sobrien } 10289857Sobrien if (CORE_GETMAGIC (coreseg) != CORESEGMAGIC) 10389857Sobrien { 10489857Sobrien bfd_set_error (bfd_error_wrong_format); 10589857Sobrien goto punt; 10689857Sobrien } 10733965Sjdp 10889857Sobrien offset += core.c_seghdrsize; 10933965Sjdp 11089857Sobrien switch (CORE_GETFLAG (coreseg)) 11189857Sobrien { 11289857Sobrien case CORE_CPU: 11389857Sobrien sname = ".reg"; 11489857Sobrien flags = SEC_ALLOC + SEC_HAS_CONTENTS; 11589857Sobrien break; 11689857Sobrien case CORE_DATA: 11789857Sobrien sname = ".data"; 11889857Sobrien flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; 11989857Sobrien break; 12089857Sobrien case CORE_STACK: 12189857Sobrien sname = ".stack"; 12289857Sobrien flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; 12389857Sobrien break; 12489857Sobrien default: 12589857Sobrien sname = ".unknown"; 12689857Sobrien flags = SEC_ALLOC + SEC_HAS_CONTENTS; 12789857Sobrien break; 12889857Sobrien } 129218822Sdim asect = bfd_make_section_anyway_with_flags (abfd, sname, flags); 13089857Sobrien if (asect == NULL) 13189857Sobrien goto punt; 13233965Sjdp 133218822Sdim asect->size = coreseg.c_size; 13489857Sobrien asect->vma = coreseg.c_addr; 13589857Sobrien asect->filepos = offset; 13689857Sobrien asect->alignment_power = 2; 13733965Sjdp 138218822Sdim if (CORE_GETFLAG (coreseg) == CORE_CPU) 139130561Sobrien { 140218822Sdim bfd_size_type wcookie_offset; 141130561Sobrien 142218822Sdim switch (CORE_GETMID (core)) 143218822Sdim { 144218822Sdim case M_SPARC_NETBSD: 145218822Sdim wcookie_offset = SPARC_WCOOKIE_OFFSET; 146218822Sdim break; 147218822Sdim case M_SPARC64_OPENBSD: 148218822Sdim wcookie_offset = SPARC64_WCOOKIE_OFFSET; 149218822Sdim break; 150218822Sdim default: 151218822Sdim wcookie_offset = 0; 152218822Sdim break; 153218822Sdim } 154130561Sobrien 155218822Sdim if (wcookie_offset > 0 && coreseg.c_size > wcookie_offset) 156218822Sdim { 157218822Sdim /* Truncate the .reg section. */ 158218822Sdim asect->size = wcookie_offset; 159218822Sdim 160218822Sdim /* And create the .wcookie section. */ 161218822Sdim flags = SEC_ALLOC + SEC_HAS_CONTENTS; 162218822Sdim asect = bfd_make_section_anyway_with_flags (abfd, ".wcookie", 163218822Sdim flags); 164218822Sdim if (asect == NULL) 165218822Sdim goto punt; 166218822Sdim 167218822Sdim asect->size = coreseg.c_size - wcookie_offset; 168218822Sdim asect->vma = 0; 169218822Sdim asect->filepos = offset + wcookie_offset; 170218822Sdim asect->alignment_power = 2; 171218822Sdim } 172130561Sobrien } 173130561Sobrien 17489857Sobrien offset += coreseg.c_size; 175218822Sdim } 17689857Sobrien 177218822Sdim /* Set architecture from machine ID. */ 178218822Sdim switch (CORE_GETMID (core)) 179218822Sdim { 180218822Sdim case M_ALPHA_NETBSD: 181218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0); 182218822Sdim break; 183218822Sdim 184218822Sdim case M_ARM6_NETBSD: 185218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_3); 186218822Sdim break; 187218822Sdim 188218822Sdim case M_X86_64_NETBSD: 189218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64); 190218822Sdim break; 191218822Sdim 192218822Sdim case M_386_NETBSD: 193218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386); 194218822Sdim break; 195218822Sdim 196218822Sdim case M_68K_NETBSD: 197218822Sdim case M_68K4K_NETBSD: 198218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0); 199218822Sdim break; 200218822Sdim 201218822Sdim case M_88K_OPENBSD: 202218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_m88k, 0); 203218822Sdim break; 204218822Sdim 205218822Sdim case M_HPPA_OPENBSD: 206218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_hppa, bfd_mach_hppa11); 207218822Sdim break; 208218822Sdim 209218822Sdim case M_POWERPC_NETBSD: 210218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc); 211218822Sdim break; 212218822Sdim 213218822Sdim case M_SPARC_NETBSD: 214218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc); 215218822Sdim break; 216218822Sdim 217218822Sdim case M_SPARC64_NETBSD: 218218822Sdim case M_SPARC64_OPENBSD: 219218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9); 220218822Sdim break; 221218822Sdim 222218822Sdim case M_VAX_NETBSD: 223218822Sdim case M_VAX4K_NETBSD: 224218822Sdim bfd_default_set_arch_mach (abfd, bfd_arch_vax, 0); 225218822Sdim break; 22689857Sobrien } 22733965Sjdp 22889857Sobrien /* OK, we believe you. You're a core file (sure, sure). */ 22989857Sobrien return abfd->xvec; 23033965Sjdp 23189857Sobrien punt: 23289857Sobrien bfd_release (abfd, abfd->tdata.any); 23389857Sobrien abfd->tdata.any = NULL; 23489857Sobrien bfd_section_list_clear (abfd); 23589857Sobrien return 0; 23633965Sjdp} 23733965Sjdp 23833965Sjdpstatic char* 239218822Sdimnetbsd_core_file_failing_command (bfd *abfd) 24033965Sjdp{ 241218822Sdim /*return core_command (abfd);*/ 24233965Sjdp return abfd->tdata.netbsd_core_data->core.c_name; 24333965Sjdp} 24433965Sjdp 24533965Sjdpstatic int 246218822Sdimnetbsd_core_file_failing_signal (bfd *abfd) 24733965Sjdp{ 24833965Sjdp /*return core_signal (abfd);*/ 24933965Sjdp return abfd->tdata.netbsd_core_data->core.c_signo; 25033965Sjdp} 25133965Sjdp 25233965Sjdp/* If somebody calls any byte-swapping routines, shoot them. */ 253218822Sdim 25433965Sjdpstatic void 255218822Sdimswap_abort (void) 25633965Sjdp{ 257218822Sdim /* This way doesn't require any declaration for ANSI to fuck up. */ 258218822Sdim abort (); 25933965Sjdp} 26033965Sjdp 261130561Sobrien#define NO_GET ((bfd_vma (*) (const void *)) swap_abort) 262130561Sobrien#define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort) 263130561Sobrien#define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort) 264130561Sobrien#define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort) 265130561Sobrien#define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort) 266130561Sobrien#define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort) 267130561Sobrien 26833965Sjdpconst bfd_target netbsd_core_vec = 26933965Sjdp { 27033965Sjdp "netbsd-core", 27133965Sjdp bfd_target_unknown_flavour, 272218822Sdim BFD_ENDIAN_UNKNOWN, /* Target byte order. */ 273218822Sdim BFD_ENDIAN_UNKNOWN, /* Target headers byte order. */ 274218822Sdim (HAS_RELOC | EXEC_P | /* Object flags. */ 27533965Sjdp HAS_LINENO | HAS_DEBUG | 27638889Sjdp HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 277218822Sdim (SEC_HAS_CONTENTS | /* Section flags. */ 278218822Sdim SEC_ALLOC | SEC_LOAD | SEC_RELOC), 279218822Sdim 0, /* Symbol prefix. */ 280218822Sdim ' ', /* ar_pad_char. */ 281218822Sdim 16, /* ar_max_namelen. */ 282130561Sobrien NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit data. */ 283130561Sobrien NO_GET, NO_GETS, NO_PUT, /* 32 bit data. */ 284130561Sobrien NO_GET, NO_GETS, NO_PUT, /* 16 bit data. */ 285130561Sobrien NO_GET64, NO_GETS64, NO_PUT64, /* 64 bit hdrs. */ 286130561Sobrien NO_GET, NO_GETS, NO_PUT, /* 32 bit hdrs. */ 287130561Sobrien NO_GET, NO_GETS, NO_PUT, /* 16 bit hdrs. */ 28833965Sjdp 289218822Sdim { /* bfd_check_format. */ 290218822Sdim _bfd_dummy_target, /* Unknown format. */ 291218822Sdim _bfd_dummy_target, /* Object file. */ 292218822Sdim _bfd_dummy_target, /* Archive. */ 293218822Sdim netbsd_core_file_p /* A core file. */ 29433965Sjdp }, 295218822Sdim { /* bfd_set_format. */ 296130561Sobrien bfd_false, bfd_false, 297130561Sobrien bfd_false, bfd_false 29833965Sjdp }, 299218822Sdim { /* bfd_write_contents. */ 300130561Sobrien bfd_false, bfd_false, 301130561Sobrien bfd_false, bfd_false 30233965Sjdp }, 30377298Sobrien 304130561Sobrien BFD_JUMP_TABLE_GENERIC (_bfd_generic), 305130561Sobrien BFD_JUMP_TABLE_COPY (_bfd_generic), 306130561Sobrien BFD_JUMP_TABLE_CORE (netbsd), 307130561Sobrien BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 308130561Sobrien BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), 309130561Sobrien BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 310130561Sobrien BFD_JUMP_TABLE_WRITE (_bfd_generic), 311130561Sobrien BFD_JUMP_TABLE_LINK (_bfd_nolink), 312130561Sobrien BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 31333965Sjdp 31460484Sobrien NULL, 31577298Sobrien 316218822Sdim (PTR) 0 /* Backend_data. */ 317130561Sobrien }; 318