diff options
Diffstat (limited to 'bfd/rs6000-core.c')
-rw-r--r-- | bfd/rs6000-core.c | 507 |
1 files changed, 0 insertions, 507 deletions
diff --git a/bfd/rs6000-core.c b/bfd/rs6000-core.c deleted file mode 100644 index b20555f5d38..00000000000 --- a/bfd/rs6000-core.c +++ /dev/null @@ -1,507 +0,0 @@ -/* IBM RS/6000 "XCOFF" back-end for BFD. - Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998 - Free Software Foundation, Inc. - FIXME: Can someone provide a transliteration of this name into ASCII? - Using the following chars caused a compiler warning on HIUX (so I replaced - them with octal escapes), and isn't useful without an understanding of what - character set it is. - Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365, - and John Gilmore. - Archive support from Damon A. Permezel. - Contributed by IBM Corporation and Cygnus Support. - -This file is part of BFD, the Binary File Descriptor library. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* This port currently only handles reading object files, except when - compiled on an RS/6000 host. -- no archive support, no core files. - In all cases, it does not support writing. - - FIXMEmgo comments are left from Metin Ozisik's original port. - - This is in a separate file from coff-rs6000.c, because it includes - system include files that conflict with coff/rs6000.h. - */ - -/* Internalcoff.h and coffcode.h modify themselves based on this flag. */ -#define RS6000COFF_C 1 - -/* The AIX 4.1 kernel is obviously compiled with -D_LONG_LONG, so - we have to define _LONG_LONG for older versions of gcc to get the - proper alignments in the user structure. */ -#if defined(_AIX41) && !defined(_LONG_LONG) -#define _LONG_LONG -#endif - -#include "bfd.h" -#include "sysdep.h" -#include "libbfd.h" - -#ifdef AIX_CORE - -/* AOUTHDR is defined by the above. We need another defn of it, from the - system include files. Punt the old one and get us a new name for the - typedef in the system include files. */ -#ifdef AOUTHDR -#undef AOUTHDR -#endif -#define AOUTHDR second_AOUTHDR - -#undef SCNHDR - - -/* ------------------------------------------------------------------------ */ -/* Support for core file stuff.. */ -/* ------------------------------------------------------------------------ */ - -#include <sys/user.h> -#include <sys/ldr.h> -#include <sys/core.h> - - -/* Number of special purpose registers supported by gdb. This value - should match `tm.h' in gdb directory. Clean this mess up and use - the macros in sys/reg.h. FIXMEmgo. */ - -#define NUM_OF_SPEC_REGS 7 - -#define core_hdr(bfd) (((Rs6kCorData*)(bfd->tdata.any))->hdr) - -/* AIX 4.1 Changed the names and locations of a few items in the core file, - this seems to be the quickest easiet way to deal with it. - - Note however that encoding magic addresses (STACK_END_ADDR) is going - to be _very_ fragile. But I don't see any easy way to get that info - right now. */ -#ifdef CORE_VERSION_1 -#define CORE_DATA_SIZE_FIELD c_u.U_dsize -#define CORE_COMM_FIELD c_u.U_comm -#define SAVE_FIELD c_mst -#define STACK_END_ADDR 0x2ff23000 -#else -#define CORE_DATA_SIZE_FIELD c_u.u_dsize -#define CORE_COMM_FIELD c_u.u_comm -#define SAVE_FIELD c_u.u_save -#define STACK_END_ADDR 0x2ff80000 -#endif - -/* These are stored in the bfd's tdata */ -typedef struct { - struct core_dump hdr; /* core file header */ -} Rs6kCorData; - -static asection *make_bfd_asection PARAMS ((bfd *, CONST char *, flagword, - bfd_size_type, bfd_vma, file_ptr)); - -static asection * -make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos) - bfd *abfd; - CONST char *name; - flagword flags; - bfd_size_type _raw_size; - bfd_vma vma; - file_ptr filepos; -{ - asection *asect; - - asect = bfd_make_section_anyway (abfd, name); - if (!asect) - return NULL; - - asect->flags = flags; - asect->_raw_size = _raw_size; - asect->vma = vma; - asect->filepos = filepos; - asect->alignment_power = 8; - - return asect; -} - -/* Decide if a given bfd represents a `core' file or not. There really is no - magic number or anything like, in rs6000coff. */ - -const bfd_target * -rs6000coff_core_p (abfd) - bfd *abfd; -{ - struct core_dump coredata; - struct stat statbuf; - bfd_size_type nread; - char *tmpptr; - - if (bfd_seek (abfd, 0, SEEK_SET) != 0) - return NULL; - - nread = bfd_read (&coredata, 1, sizeof (struct core_dump), abfd); - if (nread != sizeof (struct core_dump)) - { - if (bfd_get_error () != bfd_error_system_call) - bfd_set_error (bfd_error_wrong_format); - return NULL; - } - - if (bfd_stat (abfd, &statbuf) < 0) - { - bfd_set_error (bfd_error_system_call); - return NULL; - } - - /* If the core file ulimit is too small, the system will first - omit the data segment, then omit the stack, then decline to - dump core altogether (as far as I know UBLOCK_VALID and LE_VALID - are always set) (this is based on experimentation on AIX 3.2). - Now, the thing is that GDB users will be surprised - if segments just silently don't appear (well, maybe they would - think to check "info files", I don't know). - - For the data segment, we have no choice but to keep going if it's - not there, since the default behavior is not to dump it (regardless - of the ulimit, it's based on SA_FULLDUMP). But for the stack segment, - if it's not there, we refuse to have anything to do with this core - file. The usefulness of a core dump without a stack segment is pretty - limited anyway. */ - - if (!(coredata.c_flag & UBLOCK_VALID) - || !(coredata.c_flag & LE_VALID)) - { - bfd_set_error (bfd_error_wrong_format); - return NULL; - } - - if (!(coredata.c_flag & USTACK_VALID)) - { - bfd_set_error (bfd_error_file_truncated); - return NULL; - } - - /* Don't check the core file size for a full core, AIX 4.1 includes - additional shared library sections in a full core. */ - if (!(coredata.c_flag & (FULL_CORE | CORE_TRUNC)) - && ((bfd_vma)coredata.c_stack + coredata.c_size) != statbuf.st_size) - { - /* If the size is wrong, it means we're misinterpreting something. */ - bfd_set_error (bfd_error_wrong_format); - return NULL; - } - - /* Sanity check on the c_tab field. */ - if ((u_long) coredata.c_tab < sizeof coredata || - (u_long) coredata.c_tab >= statbuf.st_size || - (long) coredata.c_tab >= (long)coredata.c_stack) - { - bfd_set_error (bfd_error_wrong_format); - return NULL; - } - - /* Issue warning if the core file was truncated during writing. */ - if (coredata.c_flag & CORE_TRUNC) - (*_bfd_error_handler) (_("%s: warning core file truncated"), - bfd_get_filename (abfd)); - - /* Allocate core file header. */ - tmpptr = (char*) bfd_zalloc (abfd, sizeof (Rs6kCorData)); - if (!tmpptr) - return NULL; - - set_tdata (abfd, tmpptr); - - /* Copy core file header. */ - core_hdr (abfd) = coredata; - - /* .stack section. */ - if (!make_bfd_asection (abfd, ".stack", - SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, - (bfd_size_type) coredata.c_size, - (bfd_vma) (STACK_END_ADDR - coredata.c_size), - (file_ptr) coredata.c_stack)) - return NULL; - - /* .reg section for GPRs and special registers. */ - if (!make_bfd_asection (abfd, ".reg", - SEC_HAS_CONTENTS, - (bfd_size_type) ((32 + NUM_OF_SPEC_REGS) * 4), - (bfd_vma) 0, - (file_ptr) ((char *) &coredata.SAVE_FIELD - - (char *) &coredata))) - return NULL; - - /* .reg2 section for FPRs (floating point registers). */ - if (!make_bfd_asection (abfd, ".reg2", - SEC_HAS_CONTENTS, - (bfd_size_type) 8 * 32, /* 32 FPRs. */ - (bfd_vma) 0, - (file_ptr) ((char *) &coredata.SAVE_FIELD.fpr[0] - - (char *) &coredata))) - return NULL; - - /* .ldinfo section. - To actually find out how long this section is in this particular - core dump would require going down the whole list of struct ld_info's. - See if we can just fake it. */ - if (!make_bfd_asection (abfd, ".ldinfo", - SEC_HAS_CONTENTS, - (bfd_size_type) 0x7fffffff, - (bfd_vma) 0, - (file_ptr) coredata.c_tab)) - return NULL; - -#ifndef CORE_VERSION_1 - /* .data section if present. - AIX 3 dumps the complete data section and sets FULL_CORE if the - ulimit is large enough, otherwise the data section is omitted. - AIX 4 sets FULL_CORE even if the core file is truncated, we have - to examine coredata.c_datasize below to find out the actual size of - the .data section. */ - if (coredata.c_flag & FULL_CORE) - { - if (!make_bfd_asection (abfd, ".data", - SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, - (bfd_size_type) coredata.CORE_DATA_SIZE_FIELD, - (bfd_vma) - CDATA_ADDR (coredata.CORE_DATA_SIZE_FIELD), - (file_ptr) coredata.c_stack + coredata.c_size)) - return NULL; - } -#endif - -#ifdef CORE_VERSION_1 - /* AIX 4 adds data sections from loaded objects to the core file, - which can be found by examining ldinfo, and anonymously mmapped - regions. */ - { - struct ld_info ldinfo; - bfd_size_type ldinfo_size; - file_ptr ldinfo_offset = (file_ptr) coredata.c_tab; - - /* .data section from executable. */ - if (coredata.c_datasize) - { - if (!make_bfd_asection (abfd, ".data", - SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, - (bfd_size_type) coredata.c_datasize, - (bfd_vma) - CDATA_ADDR (coredata.CORE_DATA_SIZE_FIELD), - (file_ptr) coredata.c_data)) - return NULL; - } - - /* .data sections from loaded objects. */ - ldinfo_size = (char *) &ldinfo.ldinfo_filename[0] - - (char *) &ldinfo.ldinfo_next; - while (1) - { - if (bfd_seek (abfd, ldinfo_offset, SEEK_SET) != 0) - return NULL; - if (bfd_read (&ldinfo, ldinfo_size, 1, abfd) != ldinfo_size) - return NULL; - if (ldinfo.ldinfo_core) - { - if (!make_bfd_asection (abfd, ".data", - SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, - (bfd_size_type) ldinfo.ldinfo_datasize, - (bfd_vma) ldinfo.ldinfo_dataorg, - (file_ptr) ldinfo.ldinfo_core)) - return NULL; - } - if (ldinfo.ldinfo_next == 0) - break; - ldinfo_offset += ldinfo.ldinfo_next; - } - - /* .vmdata sections from anonymously mmapped regions. */ - if (coredata.c_vmregions) - { - int i; - - if (bfd_seek (abfd, (file_ptr) coredata.c_vmm, SEEK_SET) != 0) - return NULL; - - for (i = 0; i < coredata.c_vmregions; i++) - { - struct vm_info vminfo; - - if (bfd_read (&vminfo, sizeof (vminfo), 1, abfd) != sizeof (vminfo)) - return NULL; - if (vminfo.vminfo_offset) - { - if (!make_bfd_asection (abfd, ".vmdata", - SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, - (bfd_size_type) vminfo.vminfo_size, - (bfd_vma) vminfo.vminfo_addr, - (file_ptr) vminfo.vminfo_offset)) - return NULL; - } - } - } - } -#endif - - return abfd->xvec; /* this is garbage for now. */ -} - - - -/* return `true' if given core is from the given executable.. */ -boolean -rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd) - bfd *core_bfd; - bfd *exec_bfd; -{ - struct core_dump coredata; - struct ld_info ldinfo; - bfd_size_type size; - char *path, *s; - size_t alloc; - const char *str1, *str2; - boolean ret; - - if (bfd_seek (core_bfd, 0, SEEK_SET) != 0 - || bfd_read (&coredata, sizeof coredata, 1, core_bfd) != sizeof coredata) - return false; - - if (bfd_seek (core_bfd, (long) coredata.c_tab, SEEK_SET) != 0) - return false; - - size = (char *) &ldinfo.ldinfo_filename[0] - (char *) &ldinfo.ldinfo_next; - if (bfd_read (&ldinfo, size, 1, core_bfd) != size) - return false; - - alloc = 100; - path = bfd_malloc (alloc); - if (path == NULL) - return false; - s = path; - - while (1) - { - if (bfd_read (s, 1, 1, core_bfd) != 1) - { - free (path); - return false; - } - if (*s == '\0') - break; - ++s; - if (s == path + alloc) - { - char *n; - - alloc *= 2; - n = bfd_realloc (path, alloc); - if (n == NULL) - { - free (path); - return false; - } - s = n + (path - s); - path = n; - } - } - - str1 = strrchr (path, '/'); - str2 = strrchr (exec_bfd->filename, '/'); - - /* step over character '/' */ - str1 = str1 != NULL ? str1 + 1 : path; - str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename; - - if (strcmp (str1, str2) == 0) - ret = true; - else - ret = false; - - free (path); - - return ret; -} - -char * -rs6000coff_core_file_failing_command (abfd) - bfd *abfd; -{ - char *com = core_hdr (abfd).CORE_COMM_FIELD; - if (*com) - return com; - else - return 0; -} - -int -rs6000coff_core_file_failing_signal (abfd) - bfd *abfd; -{ - return core_hdr (abfd).c_signo; -} - - -boolean -rs6000coff_get_section_contents (abfd, section, location, offset, count) - bfd *abfd; - sec_ptr section; - PTR location; - file_ptr offset; - bfd_size_type count; -{ - if (count == 0) - return true; - - /* Reading a core file's sections will be slightly different. For the - rest of them we can use bfd_generic_get_section_contents () I suppose. */ - /* Make sure this routine works for any bfd and any section. FIXMEmgo. */ - - if (abfd->format == bfd_core && strcmp (section->name, ".reg") == 0) { - - struct mstsave mstatus; - int regoffset = (char*)&mstatus.gpr[0] - (char*)&mstatus; - - /* Assert that the only way this code will be executed is reading the - whole section. */ - if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS))) - (*_bfd_error_handler) - (_("ERROR! in rs6000coff_get_section_contents()\n")); - - /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure - in the core file. */ - - /* read GPR's into the location. */ - if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1 - || bfd_read(location, sizeof (mstatus.gpr), 1, abfd) != sizeof (mstatus.gpr)) - return (false); /* on error */ - - /* increment location to the beginning of special registers in the section, - reset register offset value to the beginning of first special register - in mstsave structure, and read special registers. */ - - location = (PTR) ((char*)location + sizeof (mstatus.gpr)); - regoffset = (char*)&mstatus.iar - (char*)&mstatus; - - if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1 - || bfd_read(location, 4 * NUM_OF_SPEC_REGS, 1, abfd) != - 4 * NUM_OF_SPEC_REGS) - return (false); /* on error */ - - /* increment location address, and read the special registers.. */ - /* FIXMEmgo */ - return (true); - } - - /* else, use default bfd section content transfer. */ - else - return _bfd_generic_get_section_contents - (abfd, section, location, offset, count); -} - -#endif /* AIX_CORE */ |