int rs6000coff_core_file_failing_signal (bfd *abfd) { CoreHdr *core = core_hdr (abfd); #ifndef BFD64 return CORE_NEW (*core) ? core->new_dump.c_signo : core->old.c_signo; #else return core->new_dump.c_signo; #endif }
char * rs6000coff_core_file_failing_command (bfd *abfd) { CoreHdr *core = core_hdr (abfd); char *com = CORE_NEW (*core) ? CNEW_COMM (core->new_dump) : COLD_COMM (core->old); if (*com) return com; else return 0; }
static bfd_boolean read_hdr (bfd *abfd, CoreHdr *core) { bfd_size_type size; if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return FALSE; /* Read the leading portion that old and new core dump structures have in common. */ size = CORE_COMMONSZ; if (bfd_bread (core, size, abfd) != size) return FALSE; /* Read the trailing portion of the structure. */ if (CORE_NEW (*core)) size = sizeof (core->new_dump); else size = sizeof (core->old); size -= CORE_COMMONSZ; return bfd_bread ((char *) core + CORE_COMMONSZ, size, abfd) == size; }
bfd_boolean rs6000coff_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd) { CoreHdr core; bfd_size_type size; char *path, *s; size_t alloc; const char *str1, *str2; bfd_boolean ret; file_ptr c_loader; if (!read_hdr (core_bfd, &core)) return FALSE; if (CORE_NEW (core)) c_loader = CNEW_LOADER (core.new_dump); #ifndef BFD64 else c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old); #endif if (CORE_NEW (core) && CNEW_PROC64 (core.new_dump)) size = (int) ((LdInfo *) 0)->l64.ldinfo_filename; else size = (int) ((LdInfo *) 0)->l32.ldinfo_filename; if (bfd_seek (core_bfd, c_loader + size, SEEK_SET) != 0) return FALSE; alloc = 100; path = bfd_malloc ((bfd_size_type) alloc); if (path == NULL) return FALSE; s = path; while (1) { if (bfd_bread (s, (bfd_size_type) 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, (bfd_size_type) 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; }
const bfd_target * rs6000coff_core_p (bfd *abfd) { CoreHdr core; struct stat statbuf; bfd_size_type size; char *tmpptr; /* Values from new and old core structures. */ int c_flag; file_ptr c_stack, c_regoff, c_loader; bfd_size_type c_size, c_regsize, c_lsize; bfd_vma c_stackend; void *c_regptr; int proc64; if (!read_hdr (abfd, &core)) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } /* This isn't the right handler for 64-bit core files on AIX 5.x. */ if (CORE_NEW (core) && CNEW_IS_CORE_DUMPXX (core)) { bfd_set_error (bfd_error_wrong_format); return NULL; } /* Copy fields from new or old core structure. */ if (CORE_NEW (core)) { c_flag = core.new_dump.c_flag; c_stack = (file_ptr) core.new_dump.c_stack; c_size = core.new_dump.c_size; c_stackend = CNEW_STACKORG (core.new_dump) + c_size; c_lsize = CNEW_LSIZE (core.new_dump); c_loader = CNEW_LOADER (core.new_dump); #ifndef BFD64 proc64 = CNEW_PROC64 (core.new_dump); } else { c_flag = core.old.c_flag; c_stack = (file_ptr) (ptr_to_uint) core.old.c_stack; c_size = core.old.c_size; c_stackend = COLD_STACKEND; c_lsize = 0x7ffffff; c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old); #endif proc64 = 0; } if (proc64) { c_regsize = sizeof (CNEW_CONTEXT64 (core.new_dump)); c_regptr = &CNEW_CONTEXT64 (core.new_dump); } else if (CORE_NEW (core)) { c_regsize = sizeof (CNEW_MSTSAVE (core.new_dump)); c_regptr = &CNEW_MSTSAVE (core.new_dump); } #ifndef BFD64 else { c_regsize = sizeof (COLD_MSTSAVE (core.old)); c_regptr = &COLD_MSTSAVE (core.old); } #endif c_regoff = (char *) c_regptr - (char *) &core; 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 (!(c_flag & UBLOCK_VALID) || !(c_flag & LE_VALID)) { bfd_set_error (bfd_error_wrong_format); return NULL; } if (!(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 (!(c_flag & (FULL_CORE | CORE_TRUNC))) { /* If the size is wrong, it means we're misinterpreting something. */ if (c_stack + (file_ptr) c_size != statbuf.st_size) { bfd_set_error (bfd_error_wrong_format); return NULL; } } /* Sanity check on the c_tab field. */ if (!CORE_NEW (core) && ( #ifndef BFD64 c_loader < (file_ptr) sizeof core.old #else c_loader < (file_ptr) sizeof core.new_dump #endif || c_loader >= statbuf.st_size || c_loader >= c_stack)) { bfd_set_error (bfd_error_wrong_format); return NULL; } /* Issue warning if the core file was truncated during writing. */ if (c_flag & CORE_TRUNC) _bfd_error_handler (_("%s: warning core file truncated"), bfd_get_filename (abfd)); /* Allocate core file header. */ #ifndef BFD64 size = CORE_NEW (core) ? sizeof (core.new_dump) : sizeof (core.old); #else size = sizeof (core.new_dump); #endif tmpptr = (char *) bfd_zalloc (abfd, (bfd_size_type) size); if (!tmpptr) return NULL; /* Copy core file header. */ memcpy (tmpptr, &core, size); set_tdata (abfd, tmpptr); /* Set architecture. */ if (CORE_NEW (core)) { enum bfd_architecture arch; unsigned long mach; switch (CNEW_IMPL (core.new_dump)) { case POWER_RS1: case POWER_RSC: case POWER_RS2: arch = bfd_arch_rs6000; mach = bfd_mach_rs6k; break; default: arch = bfd_arch_powerpc; mach = bfd_mach_ppc; break; } bfd_default_set_arch_mach (abfd, arch, mach); } /* .stack section. */ if (!make_bfd_asection (abfd, ".stack", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, c_size, c_stackend - c_size, c_stack)) goto fail; /* .reg section for all registers. */ if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS, c_regsize, (bfd_vma) 0, c_regoff)) goto fail; /* .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, c_lsize, (bfd_vma) 0, c_loader)) goto fail; #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 core.c_datasize below to find out the actual size of the .data section. */ if (c_flag & FULL_CORE) { if (!make_bfd_asection (abfd, ".data", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, (bfd_size_type) core.old.c_u.u_dsize, (bfd_vma) CDATA_ADDR (core.old.c_u.u_dsize), c_stack + c_size)) goto fail; } #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. */ { LdInfo ldinfo; bfd_size_type ldi_datasize; file_ptr ldi_core; uint ldi_next; bfd_vma ldi_dataorg; bfd_vma core_dataorg; /* Fields from new and old core structures. */ bfd_size_type c_datasize, c_vmregions; file_ptr c_data, c_vmm; if (CORE_NEW (core)) { c_datasize = CNEW_DATASIZE (core.new_dump); c_data = (file_ptr) core.new_dump.c_data; c_vmregions = core.new_dump.c_vmregions; c_vmm = (file_ptr) core.new_dump.c_vmm; } #ifndef BFD64 else { c_datasize = core.old.c_datasize; c_data = (file_ptr) (ptr_to_uint) core.old.c_data; c_vmregions = core.old.c_vmregions; c_vmm = (file_ptr) (ptr_to_uint) core.old.c_vmm; } #endif /* .data section from executable. */ if (c_datasize) { /* If Large Memory Model is used, then the .data segment should start from BDATAORG which has been defined in the system header files. */ if (c_flag & CORE_BIGDATA) core_dataorg = BDATAORG; else core_dataorg = CDATA_ADDR (c_datasize); if (!make_bfd_asection (abfd, ".data", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, c_datasize, (bfd_vma) core_dataorg, c_data)) goto fail; } /* .data sections from loaded objects. */ if (proc64) size = (unsigned long) ((LdInfo *) 0)->l64.ldinfo_filename; else size = (unsigned long) ((LdInfo *) 0)->l32.ldinfo_filename; while (1) { if (bfd_seek (abfd, c_loader, SEEK_SET) != 0) goto fail; if (bfd_bread (&ldinfo, size, abfd) != size) goto fail; if (proc64) { ldi_core = ldinfo.l64.ldinfo_core; ldi_datasize = ldinfo.l64.ldinfo_datasize; ldi_dataorg = (bfd_vma) ldinfo.l64.ldinfo_dataorg; ldi_next = ldinfo.l64.ldinfo_next; } else { ldi_core = ldinfo.l32.ldinfo_core; ldi_datasize = ldinfo.l32.ldinfo_datasize; ldi_dataorg = (bfd_vma) (ptr_to_uint) ldinfo.l32.ldinfo_dataorg; ldi_next = ldinfo.l32.ldinfo_next; } if (ldi_core) if (!make_bfd_asection (abfd, ".data", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, ldi_datasize, ldi_dataorg, ldi_core)) goto fail; if (ldi_next == 0) break; c_loader += ldi_next; } /* .vmdata sections from anonymously mmapped regions. */ if (c_vmregions) { bfd_size_type i; if (bfd_seek (abfd, c_vmm, SEEK_SET) != 0) goto fail; for (i = 0; i < c_vmregions; i++) { VmInfo vminfo; bfd_size_type vminfo_size; file_ptr vminfo_offset; bfd_vma vminfo_addr; #ifndef BFD64 size = CORE_NEW (core) ? sizeof (vminfo.new_dump) : sizeof (vminfo.old); #else size = sizeof (vminfo.new_dump); #endif if (bfd_bread (&vminfo, size, abfd) != size) goto fail; if (CORE_NEW (core)) { vminfo_addr = (bfd_vma) vminfo.new_dump.vminfo_addr; vminfo_size = vminfo.new_dump.vminfo_size; vminfo_offset = vminfo.new_dump.vminfo_offset; } #ifndef BFD64 else { vminfo_addr = (bfd_vma) (ptr_to_uint) vminfo.old.vminfo_addr; vminfo_size = vminfo.old.vminfo_size; vminfo_offset = vminfo.old.vminfo_offset; } #endif if (vminfo_offset) if (!make_bfd_asection (abfd, ".vmdata", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, vminfo_size, vminfo_addr, vminfo_offset)) goto fail; } } } #endif return abfd->xvec; /* This is garbage for now. */ fail: bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = NULL; bfd_section_list_clear (abfd); return NULL; }
int rs6000coff_core_file_failing_signal (bfd *abfd) { CoreHdr *core = core_hdr (abfd); return CORE_NEW (*core) ? core->new_dump.c_signo : core->old.c_signo; }