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