1/* BFD back-end for AIX on PS/2 core files. 2 This was based on trad-core.c, which was written by John Gilmore of 3 Cygnus Support. 4 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 5 2001, 2002, 2004, 2006 6 Free Software Foundation, Inc. 7 Written by Minh Tran-Le <TRANLE@INTELLICORP.COM>. 8 Converted to back end form by Ian Lance Taylor <ian@cygnus.com>. 9 10This file is part of BFD, the Binary File Descriptor library. 11 12This program is free software; you can redistribute it and/or modify 13it under the terms of the GNU General Public License as published by 14the Free Software Foundation; either version 2 of the License, or 15(at your option) any later version. 16 17This program is distributed in the hope that it will be useful, 18but WITHOUT ANY WARRANTY; without even the implied warranty of 19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20GNU General Public License for more details. 21 22You should have received a copy of the GNU General Public License 23along with this program; if not, write to the Free Software 24Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 25 26#include "bfd.h" 27#include "sysdep.h" 28#include "libbfd.h" 29#include "coff/i386.h" 30#include "coff/internal.h" 31#include "libcoff.h" 32 33#include <signal.h> 34 35#if defined (_AIX) && defined (_I386) 36#define NOCHECKS /* This is for coredump.h. */ 37#define _h_USER /* Avoid including user.h from coredump.h. */ 38#include <uinfo.h> 39#include <sys/i386/coredump.h> 40#endif /* _AIX && _I386 */ 41 42/* Maybe this could work on some other i386 but I have not tried it 43 * mtranle@paris - Tue Sep 24 12:49:35 1991 44 */ 45 46#ifndef COR_MAGIC 47# define COR_MAGIC "core" 48#endif 49 50/* Need this cast because ptr is really void *. */ 51#define core_hdr(bfd) \ 52 (((bfd->tdata.trad_core_data))->hdr) 53#define core_section(bfd,n) \ 54 (((bfd)->tdata.trad_core_data)->sections[n]) 55#define core_regsec(bfd) \ 56 (((bfd)->tdata.trad_core_data)->reg_section) 57#define core_reg2sec(bfd) \ 58 (((bfd)->tdata.trad_core_data)->reg2_section) 59 60/* These are stored in the bfd's tdata. */ 61struct trad_core_struct { 62 struct corehdr *hdr; /* core file header */ 63 asection *reg_section; 64 asection *reg2_section; 65 asection *sections[MAX_CORE_SEGS]; 66}; 67 68static void swap_abort PARAMS ((void)); 69 70static const bfd_target * 71aix386_core_file_p (abfd) 72 bfd *abfd; 73{ 74 int i, n; 75 unsigned char longbuf[4]; /* Raw bytes of various header fields */ 76 bfd_size_type core_size = sizeof (struct corehdr); 77 bfd_size_type amt; 78 struct corehdr *core; 79 struct mergem { 80 struct trad_core_struct coredata; 81 struct corehdr internal_core; 82 } *mergem; 83 flagword flags; 84 85 amt = sizeof (longbuf); 86 if (bfd_bread ((PTR) longbuf, amt, abfd) != amt) 87 { 88 if (bfd_get_error () != bfd_error_system_call) 89 bfd_set_error (bfd_error_wrong_format); 90 return 0; 91 } 92 93 if (strncmp (longbuf, COR_MAGIC, 4)) 94 return 0; 95 96 if (bfd_seek (abfd, (file_ptr) 0, 0) != 0) 97 return 0; 98 99 amt = sizeof (struct mergem); 100 mergem = (struct mergem *) bfd_zalloc (abfd, amt); 101 if (mergem == NULL) 102 return 0; 103 104 core = &mergem->internal_core; 105 106 if ((bfd_bread ((PTR) core, core_size, abfd)) != core_size) 107 { 108 if (bfd_get_error () != bfd_error_system_call) 109 bfd_set_error (bfd_error_wrong_format); 110 loser: 111 bfd_release (abfd, (char *) mergem); 112 abfd->tdata.any = NULL; 113 bfd_section_list_clear (abfd); 114 return 0; 115 } 116 117 set_tdata (abfd, &mergem->coredata); 118 core_hdr (abfd) = core; 119 120 /* Create the sections. */ 121 flags = SEC_HAS_CONTENTS; 122 core_regsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg", 123 flags); 124 if (core_regsec (abfd) == NULL) 125 goto loser; 126 127 core_regsec (abfd)->size = sizeof (core->cd_regs); 128 core_regsec (abfd)->vma = (bfd_vma) -1; 129 130 /* We'll access the regs afresh in the core file, like any section. */ 131 core_regsec (abfd)->filepos = 132 (file_ptr) offsetof (struct corehdr, cd_regs[0]); 133 134 flags = SEC_HAS_CONTENTS; 135 core_reg2sec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg2", 136 flags); 137 if (core_reg2sec (abfd) == NULL) 138 /* bfd_release frees everything allocated after it's arg. */ 139 goto loser; 140 141 core_reg2sec (abfd)->size = sizeof (core->cd_fpregs); 142 core_reg2sec (abfd)->vma = (bfd_vma) -1; 143 core_reg2sec (abfd)->filepos = 144 (file_ptr) offsetof (struct corehdr, cd_fpregs); 145 146 for (i = 0, n = 0; (i < MAX_CORE_SEGS) && (core->cd_segs[i].cs_type); i++) 147 { 148 const char *sname; 149 flagword flags; 150 151 if (core->cd_segs[i].cs_offset == 0) 152 continue; 153 154 switch (core->cd_segs[i].cs_type) 155 { 156 case COR_TYPE_DATA: 157 sname = ".data"; 158 flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; 159 break; 160 case COR_TYPE_STACK: 161 sname = ".stack"; 162 flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; 163 break; 164 case COR_TYPE_LIBDATA: 165 sname = ".libdata"; 166 flags = SEC_ALLOC + SEC_HAS_CONTENTS; 167 break; 168 case COR_TYPE_WRITE: 169 sname = ".writeable"; 170 flags = SEC_ALLOC + SEC_HAS_CONTENTS; 171 break; 172 case COR_TYPE_MSC: 173 sname = ".misc"; 174 flags = SEC_ALLOC + SEC_HAS_CONTENTS; 175 break; 176 default: 177 sname = ".unknown"; 178 flags = SEC_ALLOC + SEC_HAS_CONTENTS; 179 break; 180 } 181 core_section (abfd, n) = bfd_make_section_anyway_with_flags (abfd, 182 sname, 183 flags); 184 if (core_section (abfd, n) == NULL) 185 goto loser; 186 187 core_section (abfd, n)->size = core->cd_segs[i].cs_len; 188 core_section (abfd, n)->vma = core->cd_segs[i].cs_address; 189 core_section (abfd, n)->filepos = core->cd_segs[i].cs_offset; 190 core_section (abfd, n)->alignment_power = 2; 191 n++; 192 } 193 194 return abfd->xvec; 195} 196 197static char * 198aix386_core_file_failing_command (abfd) 199 bfd *abfd; 200{ 201 return core_hdr (abfd)->cd_comm; 202} 203 204static int 205aix386_core_file_failing_signal (abfd) 206 bfd *abfd; 207{ 208 return core_hdr (abfd)->cd_cursig; 209} 210 211#define aix386_core_file_matches_executable_p generic_core_file_matches_executable_p 212 213/* If somebody calls any byte-swapping routines, shoot them. */ 214 215static void 216swap_abort () 217{ 218 /* This way doesn't require any declaration for ANSI to fuck up. */ 219 abort (); 220} 221 222#define NO_GET ((bfd_vma (*) (const void *)) swap_abort) 223#define NO_PUT ((void (*) (bfd_vma, void *)) swap_abort) 224#define NO_GETS ((bfd_signed_vma (*) (const void *)) swap_abort) 225#define NO_GET64 ((bfd_uint64_t (*) (const void *)) swap_abort) 226#define NO_PUT64 ((void (*) (bfd_uint64_t, void *)) swap_abort) 227#define NO_GETS64 ((bfd_int64_t (*) (const void *)) swap_abort) 228 229const bfd_target aix386_core_vec = { 230 "aix386-core", 231 bfd_target_unknown_flavour, 232 BFD_ENDIAN_BIG, /* target byte order */ 233 BFD_ENDIAN_BIG, /* target headers byte order */ 234 (HAS_RELOC | EXEC_P | /* object flags */ 235 HAS_LINENO | HAS_DEBUG | 236 HAS_SYMS | HAS_LOCALS | WP_TEXT), 237 238 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 239 0, /* leading underscore */ 240 ' ', /* ar_pad_char */ 241 16, /* ar_max_namelen */ 242 NO_GET64, NO_GETS64, NO_PUT64, 243 NO_GET, NO_GETS, NO_PUT, 244 NO_GET, NO_GETS, NO_PUT, /* data */ 245 NO_GET64, NO_GETS64, NO_PUT64, 246 NO_GET, NO_GETS, NO_PUT, 247 NO_GET, NO_GETS, NO_PUT, /* hdrs */ 248 249 {_bfd_dummy_target, _bfd_dummy_target, 250 _bfd_dummy_target, aix386_core_file_p}, 251 {bfd_false, bfd_false, /* bfd_create_object */ 252 bfd_false, bfd_false}, 253 {bfd_false, bfd_false, /* bfd_write_contents */ 254 bfd_false, bfd_false}, 255 256 BFD_JUMP_TABLE_GENERIC (_bfd_generic), 257 BFD_JUMP_TABLE_COPY (_bfd_generic), 258 BFD_JUMP_TABLE_CORE (aix386), 259 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 260 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), 261 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 262 BFD_JUMP_TABLE_WRITE (_bfd_generic), 263 BFD_JUMP_TABLE_LINK (_bfd_nolink), 264 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 265 266 NULL, 267 268 (PTR) 0 269}; 270