| 1 | /* IBM RS/6000 "XCOFF" back-end for BFD. |
| 2 | Copyright (C) 1990, 1991, 1995 Free Software Foundation, Inc. |
| 3 | FIXME: Can someone provide a transliteration of this name into ASCII? |
| 4 | Using the following chars caused a compiler warning on HIUX (so I replaced |
| 5 | them with octal escapes), and isn't useful without an understanding of what |
| 6 | character set it is. |
| 7 | Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365, |
| 8 | and John Gilmore. |
| 9 | Archive support from Damon A. Permezel. |
| 10 | Contributed by IBM Corporation and Cygnus Support. |
| 11 | |
| 12 | This file is part of BFD, the Binary File Descriptor library. |
| 13 | |
| 14 | This program is free software; you can redistribute it and/or modify |
| 15 | it under the terms of the GNU General Public License as published by |
| 16 | the Free Software Foundation; either version 2 of the License, or |
| 17 | (at your option) any later version. |
| 18 | |
| 19 | This program is distributed in the hope that it will be useful, |
| 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 22 | GNU General Public License for more details. |
| 23 | |
| 24 | You should have received a copy of the GNU General Public License |
| 25 | along with this program; if not, write to the Free Software |
| 26 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
| 27 | |
| 28 | /* This port currently only handles reading object files, except when |
| 29 | compiled on an RS/6000 host. -- no archive support, no core files. |
| 30 | In all cases, it does not support writing. |
| 31 | |
| 32 | FIXMEmgo comments are left from Metin Ozisik's original port. |
| 33 | |
| 34 | This is in a separate file from coff-rs6000.c, because it includes |
| 35 | system include files that conflict with coff/rs6000.h. |
| 36 | */ |
| 37 | |
| 38 | /* Internalcoff.h and coffcode.h modify themselves based on this flag. */ |
| 39 | #define RS6000COFF_C 1 |
| 40 | |
| 41 | #include "bfd.h" |
| 42 | #include "sysdep.h" |
| 43 | #include "libbfd.h" |
| 44 | |
| 45 | #ifdef AIX_CORE |
| 46 | |
| 47 | /* AOUTHDR is defined by the above. We need another defn of it, from the |
| 48 | system include files. Punt the old one and get us a new name for the |
| 49 | typedef in the system include files. */ |
| 50 | #ifdef AOUTHDR |
| 51 | #undef AOUTHDR |
| 52 | #endif |
| 53 | #define AOUTHDR second_AOUTHDR |
| 54 | |
| 55 | #undef SCNHDR |
| 56 | |
| 57 | |
| 58 | /* ------------------------------------------------------------------------ */ |
| 59 | /* Support for core file stuff.. */ |
| 60 | /* ------------------------------------------------------------------------ */ |
| 61 | |
| 62 | #include <sys/user.h> |
| 63 | #include <sys/ldr.h> |
| 64 | #include <sys/core.h> |
| 65 | |
| 66 | |
| 67 | /* Number of special purpose registers supported by gdb. This value |
| 68 | should match `tm.h' in gdb directory. Clean this mess up and use |
| 69 | the macros in sys/reg.h. FIXMEmgo. */ |
| 70 | |
| 71 | #define NUM_OF_SPEC_REGS 7 |
| 72 | |
| 73 | #define core_hdr(bfd) (((Rs6kCorData*)(bfd->tdata.any))->hdr) |
| 74 | #define core_datasec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->data_section) |
| 75 | #define core_stacksec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->stack_section) |
| 76 | #define core_regsec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->reg_section) |
| 77 | #define core_reg2sec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->reg2_section) |
| 78 | |
| 79 | /* AIX 4.1 Changed the names and locations of a few items in the core file, |
| 80 | this seems to be the quickest easiet way to deal with it. |
| 81 | |
| 82 | Note however that encoding magic addresses (STACK_END_ADDR) is going |
| 83 | to be _very_ fragile. But I don't see any easy way to get that info |
| 84 | right now. */ |
| 85 | #ifdef ALTERNATE_AIX_CORE_FORMAT |
| 86 | #define CORE_DATA_SIZE_FIELD c_u.U_dsize |
| 87 | #define CORE_COMM_FIELD c_u.U_comm |
| 88 | #define SAVE_FIELD c_mst |
| 89 | #define STACK_END_ADDR 0x2ff23000 |
| 90 | #else |
| 91 | #define CORE_DATA_SIZE_FIELD c_u.u_dsize |
| 92 | #define CORE_COMM_FIELD c_u.u_comm |
| 93 | #define SAVE_FIELD c_u.u_save |
| 94 | #define STACK_END_ADDR 0x2ff80000 |
| 95 | #endif |
| 96 | |
| 97 | /* These are stored in the bfd's tdata */ |
| 98 | typedef struct { |
| 99 | struct core_dump hdr; /* core file header */ |
| 100 | asection *data_section, |
| 101 | *stack_section, |
| 102 | *reg_section, /* section for GPRs and special registers. */ |
| 103 | *reg2_section; /* section for FPRs. */ |
| 104 | |
| 105 | /* This tells us where everything is mapped (shared libraries and so on). |
| 106 | GDB needs it. */ |
| 107 | asection *ldinfo_section; |
| 108 | #define core_ldinfosec(bfd) (((Rs6kCorData *)(bfd->tdata.any))->ldinfo_section) |
| 109 | } Rs6kCorData; |
| 110 | |
| 111 | |
| 112 | /* Decide if a given bfd represents a `core' file or not. There really is no |
| 113 | magic number or anything like, in rs6000coff. */ |
| 114 | |
| 115 | const bfd_target * |
| 116 | rs6000coff_core_p (abfd) |
| 117 | bfd *abfd; |
| 118 | { |
| 119 | int fd; |
| 120 | struct core_dump coredata; |
| 121 | struct stat statbuf; |
| 122 | char *tmpptr; |
| 123 | |
| 124 | /* Use bfd_xxx routines, rather than O/S primitives to read coredata. FIXMEmgo */ |
| 125 | fd = open (abfd->filename, O_RDONLY); |
| 126 | if (fd < 0) |
| 127 | { |
| 128 | bfd_set_error (bfd_error_system_call); |
| 129 | return NULL; |
| 130 | } |
| 131 | |
| 132 | if (fstat (fd, &statbuf) < 0) |
| 133 | { |
| 134 | bfd_set_error (bfd_error_system_call); |
| 135 | close (fd); |
| 136 | return NULL; |
| 137 | } |
| 138 | if (read (fd, &coredata, sizeof (struct core_dump)) |
| 139 | != sizeof (struct core_dump)) |
| 140 | { |
| 141 | bfd_set_error (bfd_error_wrong_format); |
| 142 | close (fd); |
| 143 | return NULL; |
| 144 | } |
| 145 | |
| 146 | if (close (fd) < 0) |
| 147 | { |
| 148 | bfd_set_error (bfd_error_system_call); |
| 149 | return NULL; |
| 150 | } |
| 151 | |
| 152 | /* If the core file ulimit is too small, the system will first |
| 153 | omit the data segment, then omit the stack, then decline to |
| 154 | dump core altogether (as far as I know UBLOCK_VALID and LE_VALID |
| 155 | are always set) (this is based on experimentation on AIX 3.2). |
| 156 | Now, the thing is that GDB users will be surprised |
| 157 | if segments just silently don't appear (well, maybe they would |
| 158 | think to check "info files", I don't know), but we have no way of |
| 159 | returning warnings (as opposed to errors). |
| 160 | |
| 161 | For the data segment, we have no choice but to keep going if it's |
| 162 | not there, since the default behavior is not to dump it (regardless |
| 163 | of the ulimit, it's based on SA_FULLDUMP). But for the stack segment, |
| 164 | if it's not there, we refuse to have anything to do with this core |
| 165 | file. The usefulness of a core dump without a stack segment is pretty |
| 166 | limited anyway. */ |
| 167 | |
| 168 | if (!(coredata.c_flag & UBLOCK_VALID) |
| 169 | || !(coredata.c_flag & LE_VALID)) |
| 170 | { |
| 171 | bfd_set_error (bfd_error_wrong_format); |
| 172 | return NULL; |
| 173 | } |
| 174 | |
| 175 | if ((coredata.c_flag & CORE_TRUNC) |
| 176 | || !(coredata.c_flag & USTACK_VALID)) |
| 177 | { |
| 178 | bfd_set_error (bfd_error_file_truncated); |
| 179 | return NULL; |
| 180 | } |
| 181 | |
| 182 | /* Don't check the core file size for a full core, AIX 4.1 includes |
| 183 | additional shared library sections in a full core. */ |
| 184 | if (!(coredata.c_flag & FULL_CORE) |
| 185 | && ((bfd_vma)coredata.c_stack + coredata.c_size) != statbuf.st_size) |
| 186 | { |
| 187 | /* If the size is wrong, it means we're misinterpreting something. */ |
| 188 | bfd_set_error (bfd_error_wrong_format); |
| 189 | return NULL; |
| 190 | } |
| 191 | |
| 192 | /* Sanity check on the c_tab field. */ |
| 193 | if ((u_long) coredata.c_tab < sizeof coredata || |
| 194 | (u_long) coredata.c_tab >= statbuf.st_size || |
| 195 | (long) coredata.c_tab >= (long)coredata.c_stack) |
| 196 | { |
| 197 | bfd_set_error (bfd_error_wrong_format); |
| 198 | return NULL; |
| 199 | } |
| 200 | |
| 201 | /* maybe you should alloc space for the whole core chunk over here!! FIXMEmgo */ |
| 202 | tmpptr = (char*)bfd_zalloc (abfd, sizeof (Rs6kCorData)); |
| 203 | if (!tmpptr) |
| 204 | { |
| 205 | bfd_set_error (bfd_error_no_memory); |
| 206 | return NULL; |
| 207 | } |
| 208 | |
| 209 | set_tdata (abfd, tmpptr); |
| 210 | |
| 211 | /* Copy core file header. */ |
| 212 | core_hdr (abfd) = coredata; |
| 213 | |
| 214 | /* .stack section. */ |
| 215 | if ((core_stacksec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection))) |
| 216 | == NULL) { |
| 217 | bfd_set_error (bfd_error_no_memory); |
| 218 | /* bfd_release (abfd, ???? ) */ |
| 219 | return NULL; |
| 220 | } |
| 221 | core_stacksec (abfd)->name = ".stack"; |
| 222 | core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; |
| 223 | core_stacksec (abfd)->_raw_size = coredata.c_size; |
| 224 | core_stacksec (abfd)->vma = STACK_END_ADDR - coredata.c_size; |
| 225 | core_stacksec (abfd)->filepos = (int)coredata.c_stack; /*???? */ |
| 226 | |
| 227 | /* .reg section for GPRs and special registers. */ |
| 228 | if ((core_regsec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection))) |
| 229 | == NULL) { |
| 230 | bfd_set_error (bfd_error_no_memory); |
| 231 | /* bfd_release (abfd, ???? ) */ |
| 232 | return NULL; |
| 233 | } |
| 234 | core_regsec (abfd)->name = ".reg"; |
| 235 | core_regsec (abfd)->flags = SEC_HAS_CONTENTS; |
| 236 | core_regsec (abfd)->_raw_size = (32 + NUM_OF_SPEC_REGS) * 4; |
| 237 | core_regsec (abfd)->vma = 0; /* not used?? */ |
| 238 | core_regsec (abfd)->filepos = |
| 239 | (char*)&coredata.SAVE_FIELD - (char*)&coredata; |
| 240 | |
| 241 | /* .reg2 section for FPRs (floating point registers). */ |
| 242 | if ((core_reg2sec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection))) |
| 243 | == NULL) { |
| 244 | bfd_set_error (bfd_error_no_memory); |
| 245 | /* bfd_release (abfd, ???? ) */ |
| 246 | return NULL; |
| 247 | } |
| 248 | core_reg2sec (abfd)->name = ".reg2"; |
| 249 | core_reg2sec (abfd)->flags = SEC_HAS_CONTENTS; |
| 250 | core_reg2sec (abfd)->_raw_size = 8 * 32; /* 32 FPRs. */ |
| 251 | core_reg2sec (abfd)->vma = 0; /* not used?? */ |
| 252 | core_reg2sec (abfd)->filepos = |
| 253 | (char*)&coredata.SAVE_FIELD.fpr[0] - (char*)&coredata; |
| 254 | |
| 255 | if ((core_ldinfosec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection))) |
| 256 | == NULL) { |
| 257 | bfd_set_error (bfd_error_no_memory); |
| 258 | /* bfd_release (abfd, ???? ) */ |
| 259 | return NULL; |
| 260 | } |
| 261 | core_ldinfosec (abfd)->name = ".ldinfo"; |
| 262 | core_ldinfosec (abfd)->flags = SEC_HAS_CONTENTS; |
| 263 | /* To actually find out how long this section is in this particular |
| 264 | core dump would require going down the whole list of struct ld_info's. |
| 265 | See if we can just fake it. */ |
| 266 | core_ldinfosec (abfd)->_raw_size = 0x7fffffff; |
| 267 | /* Not relevant for ldinfo section. */ |
| 268 | core_ldinfosec (abfd)->vma = 0; |
| 269 | core_ldinfosec (abfd)->filepos = (file_ptr) coredata.c_tab; |
| 270 | |
| 271 | /* set up section chain here. */ |
| 272 | abfd->section_count = 4; |
| 273 | abfd->sections = core_stacksec (abfd); |
| 274 | core_stacksec (abfd)->next = core_regsec(abfd); |
| 275 | core_regsec (abfd)->next = core_reg2sec (abfd); |
| 276 | core_reg2sec (abfd)->next = core_ldinfosec (abfd); |
| 277 | core_ldinfosec (abfd)->next = NULL; |
| 278 | |
| 279 | if (coredata.c_flag & FULL_CORE) |
| 280 | { |
| 281 | asection *sec = (asection *) bfd_zalloc (abfd, sizeof (asection)); |
| 282 | if (sec == NULL) |
| 283 | { |
| 284 | bfd_set_error (bfd_error_no_memory); |
| 285 | return NULL; |
| 286 | } |
| 287 | sec->name = ".data"; |
| 288 | sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; |
| 289 | sec->_raw_size = coredata.CORE_DATA_SIZE_FIELD; |
| 290 | sec->vma = CDATA_ADDR (coredata.CORE_DATA_SIZE_FIELD); |
| 291 | sec->filepos = (int)coredata.c_stack + coredata.c_size; |
| 292 | |
| 293 | sec->next = abfd->sections; |
| 294 | abfd->sections = sec; |
| 295 | ++abfd->section_count; |
| 296 | } |
| 297 | |
| 298 | return abfd->xvec; /* this is garbage for now. */ |
| 299 | } |
| 300 | |
| 301 | |
| 302 | |
| 303 | /* return `true' if given core is from the given executable.. */ |
| 304 | boolean |
| 305 | rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd) |
| 306 | bfd *core_bfd; |
| 307 | bfd *exec_bfd; |
| 308 | { |
| 309 | FILE *fd; |
| 310 | struct core_dump coredata; |
| 311 | struct ld_info ldinfo; |
| 312 | char pathname [1024]; |
| 313 | const char *str1, *str2; |
| 314 | |
| 315 | /* Use bfd_xxx routines, rather than O/S primitives, do error checking!! |
| 316 | FIXMEmgo */ |
| 317 | /* Actually should be able to use bfd_get_section_contents now that |
| 318 | we have a .ldinfo section. */ |
| 319 | fd = fopen (core_bfd->filename, FOPEN_RB); |
| 320 | |
| 321 | fread (&coredata, sizeof (struct core_dump), 1, fd); |
| 322 | fseek (fd, (long)coredata.c_tab, 0); |
| 323 | fread (&ldinfo, (char*)&ldinfo.ldinfo_filename[0] - (char*)&ldinfo.ldinfo_next, |
| 324 | 1, fd); |
| 325 | fscanf (fd, "%s", pathname); |
| 326 | |
| 327 | str1 = strrchr (pathname, '/'); |
| 328 | str2 = strrchr (exec_bfd->filename, '/'); |
| 329 | |
| 330 | /* step over character '/' */ |
| 331 | str1 = str1 ? str1+1 : &pathname[0]; |
| 332 | str2 = str2 ? str2+1 : exec_bfd->filename; |
| 333 | |
| 334 | fclose (fd); |
| 335 | return strcmp (str1, str2) == 0; |
| 336 | } |
| 337 | |
| 338 | char * |
| 339 | rs6000coff_core_file_failing_command (abfd) |
| 340 | bfd *abfd; |
| 341 | { |
| 342 | char *com = core_hdr (abfd).CORE_COMM_FIELD; |
| 343 | if (*com) |
| 344 | return com; |
| 345 | else |
| 346 | return 0; |
| 347 | } |
| 348 | |
| 349 | int |
| 350 | rs6000coff_core_file_failing_signal (abfd) |
| 351 | bfd *abfd; |
| 352 | { |
| 353 | return core_hdr (abfd).c_signo; |
| 354 | } |
| 355 | |
| 356 | |
| 357 | boolean |
| 358 | rs6000coff_get_section_contents (abfd, section, location, offset, count) |
| 359 | bfd *abfd; |
| 360 | sec_ptr section; |
| 361 | PTR location; |
| 362 | file_ptr offset; |
| 363 | int count; |
| 364 | { |
| 365 | if (count == 0) |
| 366 | return true; |
| 367 | |
| 368 | /* Reading a core file's sections will be slightly different. For the |
| 369 | rest of them we can use bfd_generic_get_section_contents () I suppose. */ |
| 370 | /* Make sure this routine works for any bfd and any section. FIXMEmgo. */ |
| 371 | |
| 372 | if (abfd->format == bfd_core && strcmp (section->name, ".reg") == 0) { |
| 373 | |
| 374 | struct mstsave mstatus; |
| 375 | int regoffset = (char*)&mstatus.gpr[0] - (char*)&mstatus; |
| 376 | |
| 377 | /* Assert that the only way this code will be executed is reading the |
| 378 | whole section. */ |
| 379 | if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS))) |
| 380 | fprintf (stderr, "ERROR! in rs6000coff_get_section_contents()\n"); |
| 381 | |
| 382 | /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure |
| 383 | in the core file. */ |
| 384 | |
| 385 | /* read GPR's into the location. */ |
| 386 | if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1 |
| 387 | || bfd_read(location, sizeof (mstatus.gpr), 1, abfd) != sizeof (mstatus.gpr)) |
| 388 | return (false); /* on error */ |
| 389 | |
| 390 | /* increment location to the beginning of special registers in the section, |
| 391 | reset register offset value to the beginning of first special register |
| 392 | in mstsave structure, and read special registers. */ |
| 393 | |
| 394 | location = (PTR) ((char*)location + sizeof (mstatus.gpr)); |
| 395 | regoffset = (char*)&mstatus.iar - (char*)&mstatus; |
| 396 | |
| 397 | if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1 |
| 398 | || bfd_read(location, 4 * NUM_OF_SPEC_REGS, 1, abfd) != |
| 399 | 4 * NUM_OF_SPEC_REGS) |
| 400 | return (false); /* on error */ |
| 401 | |
| 402 | /* increment location address, and read the special registers.. */ |
| 403 | /* FIXMEmgo */ |
| 404 | return (true); |
| 405 | } |
| 406 | |
| 407 | /* else, use default bfd section content transfer. */ |
| 408 | else |
| 409 | return _bfd_generic_get_section_contents |
| 410 | (abfd, section, location, offset, count); |
| 411 | } |
| 412 | |
| 413 | #endif /* AIX_CORE */ |