191041Sobrien/* IBM RS/6000 "XCOFF" back-end for BFD. 291041Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 3218822Sdim 2001, 2002, 2004, 2006, 2007 491041Sobrien Free Software Foundation, Inc. 5218822Sdim Written by Metin G. Ozisik, Mimi Phuong-Thao Vo, and John Gilmore. 691041Sobrien Archive support from Damon A. Permezel. 791041Sobrien Contributed by IBM Corporation and Cygnus Support. 891041Sobrien 9104834Sobrien This file is part of BFD, the Binary File Descriptor library. 1091041Sobrien 11104834Sobrien This program is free software; you can redistribute it and/or modify 12104834Sobrien it under the terms of the GNU General Public License as published by 13104834Sobrien the Free Software Foundation; either version 2 of the License, or 14104834Sobrien (at your option) any later version. 1591041Sobrien 16104834Sobrien This program is distributed in the hope that it will be useful, 17104834Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 18104834Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19104834Sobrien GNU General Public License for more details. 2091041Sobrien 21104834Sobrien You should have received a copy of the GNU General Public License 22104834Sobrien along with this program; if not, write to the Free Software 23218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2491041Sobrien 2591041Sobrien/* This port currently only handles reading object files, except when 2691041Sobrien compiled on an RS/6000 host. -- no archive support, no core files. 2791041Sobrien In all cases, it does not support writing. 2891041Sobrien 2991041Sobrien This is in a separate file from coff-rs6000.c, because it includes 3091041Sobrien system include files that conflict with coff/rs6000.h. */ 3191041Sobrien 3291041Sobrien/* Internalcoff.h and coffcode.h modify themselves based on this flag. */ 3391041Sobrien#define RS6000COFF_C 1 3491041Sobrien 3591041Sobrien/* The AIX 4.1 kernel is obviously compiled with -D_LONG_LONG, so 3691041Sobrien we have to define _LONG_LONG for older versions of gcc to get the 3791041Sobrien proper alignments in the user structure. */ 3891041Sobrien#if defined(_AIX41) && !defined(_LONG_LONG) 3991041Sobrien#define _LONG_LONG 4091041Sobrien#endif 4191041Sobrien 42218822Sdim#include "sysdep.h" 4391041Sobrien#include "bfd.h" 4491041Sobrien#include "libbfd.h" 4591041Sobrien 4691041Sobrien#ifdef AIX_CORE 4791041Sobrien 4891041Sobrien/* AOUTHDR is defined by the above. We need another defn of it, from the 4991041Sobrien system include files. Punt the old one and get us a new name for the 5091041Sobrien typedef in the system include files. */ 5191041Sobrien#ifdef AOUTHDR 5291041Sobrien#undef AOUTHDR 5391041Sobrien#endif 5491041Sobrien#define AOUTHDR second_AOUTHDR 5591041Sobrien 5691041Sobrien#undef SCNHDR 5791041Sobrien 5891041Sobrien/* ------------------------------------------------------------------------ */ 5991041Sobrien/* Support for core file stuff.. */ 6091041Sobrien/* ------------------------------------------------------------------------ */ 6191041Sobrien 6291041Sobrien#include <sys/user.h> 6391041Sobrien#define __LDINFO_PTRACE32__ /* for __ld_info32 */ 6491041Sobrien#define __LDINFO_PTRACE64__ /* for __ld_info64 */ 6591041Sobrien#include <sys/ldr.h> 6691041Sobrien#include <sys/core.h> 6791041Sobrien#include <sys/systemcfg.h> 6891041Sobrien 69218822Sdim/* Borrowed from <sys/inttypes.h> on recent AIX versions. */ 70218822Sdimtypedef unsigned long ptr_to_uint; 71218822Sdim 7291041Sobrien#define core_hdr(bfd) ((CoreHdr *) bfd->tdata.any) 7391041Sobrien 7491041Sobrien/* AIX 4.1 changed the names and locations of a few items in the core file. 7591041Sobrien AIX 4.3 defined an entirely new structure, core_dumpx, but kept support for 7691041Sobrien the previous 4.1 structure, core_dump. 7791041Sobrien 7891041Sobrien AIX_CORE_DUMPX_CORE is defined (by configure) on AIX 4.3+, and 7991041Sobrien CORE_VERSION_1 is defined (by AIX core.h) as 2 on AIX 4.3+ and as 1 on AIX 8091041Sobrien 4.1 and 4.2. AIX pre-4.1 (aka 3.x) either doesn't define CORE_VERSION_1 8191041Sobrien or else defines it as 0. */ 8291041Sobrien 8391041Sobrien#if defined(CORE_VERSION_1) && !CORE_VERSION_1 8491041Sobrien# undef CORE_VERSION_1 8591041Sobrien#endif 8691041Sobrien 8791041Sobrien/* The following union and macros allow this module to compile on all AIX 8891041Sobrien versions and to handle both core_dumpx and core_dump on 4.3+. CNEW_*() 8991041Sobrien and COLD_*() macros respectively retrieve core_dumpx and core_dump 9091041Sobrien values. */ 9191041Sobrien 9291041Sobrien/* Union of 32-bit and 64-bit versions of ld_info. */ 9391041Sobrien 9491041Sobrientypedef union { 9591041Sobrien#ifdef __ld_info32 9691041Sobrien struct __ld_info32 l32; 9791041Sobrien struct __ld_info64 l64; 9891041Sobrien#else 9991041Sobrien struct ld_info l32; 10091041Sobrien struct ld_info l64; 10191041Sobrien#endif 10291041Sobrien} LdInfo; 10391041Sobrien 10491041Sobrien/* Union of old and new core dump structures. */ 10591041Sobrien 10691041Sobrientypedef union { 10791041Sobrien#ifdef AIX_CORE_DUMPX_CORE 10891041Sobrien struct core_dumpx new; /* new AIX 4.3+ core dump */ 10991041Sobrien#else 11091041Sobrien struct core_dump new; /* for simpler coding */ 11191041Sobrien#endif 11291041Sobrien struct core_dump old; /* old AIX 4.2- core dump, still used on 11391041Sobrien 4.3+ with appropriate SMIT config */ 11491041Sobrien} CoreHdr; 11591041Sobrien 11691041Sobrien/* Union of old and new vm_info structures. */ 11791041Sobrien 11891041Sobrien#ifdef CORE_VERSION_1 11991041Sobrientypedef union { 12091041Sobrien#ifdef AIX_CORE_DUMPX_CORE 12191041Sobrien struct vm_infox new; 12291041Sobrien#else 12391041Sobrien struct vm_info new; 12491041Sobrien#endif 12591041Sobrien struct vm_info old; 12691041Sobrien} VmInfo; 12791041Sobrien#endif 12891041Sobrien 12991041Sobrien/* Return whether CoreHdr C is in new or old format. */ 13091041Sobrien 13191041Sobrien#ifdef AIX_CORE_DUMPX_CORE 13291041Sobrien# define CORE_NEW(c) (!(c).old.c_entries) 13391041Sobrien#else 13491041Sobrien# define CORE_NEW(c) 0 13591041Sobrien#endif 13691041Sobrien 13791041Sobrien/* Return the c_stackorg field from struct core_dumpx C. */ 13891041Sobrien 13991041Sobrien#ifdef AIX_CORE_DUMPX_CORE 14091041Sobrien# define CNEW_STACKORG(c) (c).c_stackorg 14191041Sobrien#else 14291041Sobrien# define CNEW_STACKORG(c) 0 14391041Sobrien#endif 14491041Sobrien 14591041Sobrien/* Return the offset to the loader region from struct core_dump C. */ 14691041Sobrien 14791041Sobrien#ifdef AIX_CORE_DUMPX_CORE 14891041Sobrien# define CNEW_LOADER(c) (c).c_loader 14991041Sobrien#else 15091041Sobrien# define CNEW_LOADER(c) 0 15191041Sobrien#endif 15291041Sobrien 15391041Sobrien/* Return the offset to the loader region from struct core_dump C. */ 15491041Sobrien 15591041Sobrien#define COLD_LOADER(c) (c).c_tab 15691041Sobrien 15791041Sobrien/* Return the c_lsize field from struct core_dumpx C. */ 15891041Sobrien 15991041Sobrien#ifdef AIX_CORE_DUMPX_CORE 16091041Sobrien# define CNEW_LSIZE(c) (c).c_lsize 16191041Sobrien#else 16291041Sobrien# define CNEW_LSIZE(c) 0 16391041Sobrien#endif 16491041Sobrien 16591041Sobrien/* Return the c_dataorg field from struct core_dumpx C. */ 16691041Sobrien 16791041Sobrien#ifdef AIX_CORE_DUMPX_CORE 16891041Sobrien# define CNEW_DATAORG(c) (c).c_dataorg 16991041Sobrien#else 17091041Sobrien# define CNEW_DATAORG(c) 0 17191041Sobrien#endif 17291041Sobrien 17391041Sobrien/* Return the c_datasize field from struct core_dumpx C. */ 17491041Sobrien 17591041Sobrien#ifdef AIX_CORE_DUMPX_CORE 17691041Sobrien# define CNEW_DATASIZE(c) (c).c_datasize 17791041Sobrien#else 17891041Sobrien# define CNEW_DATASIZE(c) 0 17991041Sobrien#endif 18091041Sobrien 18191041Sobrien/* Return the c_impl field from struct core_dumpx C. */ 18291041Sobrien 18399461Sobrien#if defined (HAVE_ST_C_IMPL) || defined (AIX_5_CORE) 18491041Sobrien# define CNEW_IMPL(c) (c).c_impl 18591041Sobrien#else 18691041Sobrien# define CNEW_IMPL(c) 0 18791041Sobrien#endif 18891041Sobrien 18991041Sobrien/* Return the command string from struct core_dumpx C. */ 19091041Sobrien 19191041Sobrien#ifdef AIX_CORE_DUMPX_CORE 19291041Sobrien# define CNEW_COMM(c) (c).c_u.U_proc.pi_comm 19391041Sobrien#else 19491041Sobrien# define CNEW_COMM(c) 0 19591041Sobrien#endif 19691041Sobrien 19791041Sobrien/* Return the command string from struct core_dump C. */ 19891041Sobrien 19991041Sobrien#ifdef CORE_VERSION_1 20091041Sobrien# define COLD_COMM(c) (c).c_u.U_comm 20191041Sobrien#else 20291041Sobrien# define COLD_COMM(c) (c).c_u.u_comm 20391041Sobrien#endif 20491041Sobrien 20591041Sobrien/* Return the struct __context64 pointer from struct core_dumpx C. */ 20691041Sobrien 20791041Sobrien#ifdef AIX_CORE_DUMPX_CORE 20891041Sobrien# define CNEW_CONTEXT64(c) (c).c_flt.hctx.r64 20991041Sobrien#else 21091041Sobrien# define CNEW_CONTEXT64(c) c 21191041Sobrien#endif 21291041Sobrien 21391041Sobrien/* Return the struct mstsave pointer from struct core_dumpx C. */ 21491041Sobrien 21591041Sobrien#ifdef AIX_CORE_DUMPX_CORE 21691041Sobrien# define CNEW_MSTSAVE(c) (c).c_flt.hctx.r32 21791041Sobrien#else 21891041Sobrien# define CNEW_MSTSAVE(c) c 21991041Sobrien#endif 22091041Sobrien 22191041Sobrien/* Return the struct mstsave pointer from struct core_dump C. */ 22291041Sobrien 22391041Sobrien#ifdef CORE_VERSION_1 22491041Sobrien# define COLD_MSTSAVE(c) (c).c_mst 22591041Sobrien#else 22691041Sobrien# define COLD_MSTSAVE(c) (c).c_u.u_save 22791041Sobrien#endif 22891041Sobrien 22991041Sobrien/* Return whether struct core_dumpx is from a 64-bit process. */ 23091041Sobrien 23191041Sobrien#ifdef AIX_CORE_DUMPX_CORE 23291041Sobrien# define CNEW_PROC64(c) IS_PROC64(&(c).c_u.U_proc) 23391041Sobrien#else 23491041Sobrien# define CNEW_PROC64(c) 0 23591041Sobrien#endif 23691041Sobrien 23791041Sobrien/* Magic end-of-stack addresses for old core dumps. This is _very_ fragile, 23891041Sobrien but I don't see any easy way to get that info right now. */ 23991041Sobrien 24091041Sobrien#ifdef CORE_VERSION_1 24191041Sobrien# define COLD_STACKEND 0x2ff23000 24291041Sobrien#else 24391041Sobrien# define COLD_STACKEND 0x2ff80000 24491041Sobrien#endif 24591041Sobrien 24691041Sobrien/* Size of the leading portion that old and new core dump structures have in 24791041Sobrien common. */ 24891041Sobrien#define CORE_COMMONSZ ((int) &((struct core_dump *) 0)->c_entries \ 24991041Sobrien + sizeof (((struct core_dump *) 0)->c_entries)) 25091041Sobrien 251218822Sdim/* Define prototypes for certain functions, to avoid a compiler warning 252218822Sdim saying that they are missing. */ 253218822Sdim 254218822Sdimconst bfd_target * rs6000coff_core_p (bfd *abfd); 255218822Sdimbfd_boolean rs6000coff_core_file_matches_executable_p (bfd *core_bfd, 256218822Sdim bfd *exec_bfd); 257218822Sdimchar * rs6000coff_core_file_failing_command (bfd *abfd); 258218822Sdimint rs6000coff_core_file_failing_signal (bfd *abfd); 259218822Sdim 26091041Sobrien/* Try to read into CORE the header from the core file associated with ABFD. 26191041Sobrien Return success. */ 26291041Sobrien 263130561Sobrienstatic bfd_boolean 26491041Sobrienread_hdr (bfd *abfd, CoreHdr *core) 26591041Sobrien{ 26691041Sobrien bfd_size_type size; 26791041Sobrien 26891041Sobrien if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 269130561Sobrien return FALSE; 27091041Sobrien 27191041Sobrien /* Read the leading portion that old and new core dump structures have in 27291041Sobrien common. */ 27391041Sobrien size = CORE_COMMONSZ; 27491041Sobrien if (bfd_bread (core, size, abfd) != size) 275130561Sobrien return FALSE; 27691041Sobrien 27791041Sobrien /* Read the trailing portion of the structure. */ 27891041Sobrien if (CORE_NEW (*core)) 27991041Sobrien size = sizeof (core->new); 28091041Sobrien else 28191041Sobrien size = sizeof (core->old); 28291041Sobrien size -= CORE_COMMONSZ; 28391041Sobrien return bfd_bread ((char *) core + CORE_COMMONSZ, size, abfd) == size; 28491041Sobrien} 28591041Sobrien 28691041Sobrienstatic asection * 287218822Sdimmake_bfd_asection (bfd *abfd, const char *name, flagword flags, 288218822Sdim bfd_size_type size, bfd_vma vma, file_ptr filepos) 28991041Sobrien{ 29091041Sobrien asection *asect; 29191041Sobrien 292218822Sdim asect = bfd_make_section_anyway_with_flags (abfd, name, flags); 29391041Sobrien if (!asect) 29491041Sobrien return NULL; 29591041Sobrien 296218822Sdim asect->size = size; 29791041Sobrien asect->vma = vma; 29891041Sobrien asect->filepos = filepos; 29991041Sobrien asect->alignment_power = 8; 30091041Sobrien 30191041Sobrien return asect; 30291041Sobrien} 30391041Sobrien 30491041Sobrien/* Decide if a given bfd represents a `core' file or not. There really is no 30591041Sobrien magic number or anything like, in rs6000coff. */ 30691041Sobrien 30791041Sobrienconst bfd_target * 308218822Sdimrs6000coff_core_p (bfd *abfd) 30991041Sobrien{ 31091041Sobrien CoreHdr core; 31191041Sobrien struct stat statbuf; 31291041Sobrien bfd_size_type size; 31391041Sobrien char *tmpptr; 31491041Sobrien 31591041Sobrien /* Values from new and old core structures. */ 31691041Sobrien int c_flag; 31791041Sobrien file_ptr c_stack, c_regoff, c_loader; 31891041Sobrien bfd_size_type c_size, c_regsize, c_lsize; 31991041Sobrien bfd_vma c_stackend; 32091041Sobrien void *c_regptr; 32191041Sobrien int proc64; 32291041Sobrien 32391041Sobrien if (!read_hdr (abfd, &core)) 32491041Sobrien { 32591041Sobrien if (bfd_get_error () != bfd_error_system_call) 32691041Sobrien bfd_set_error (bfd_error_wrong_format); 32791041Sobrien return NULL; 32891041Sobrien } 32991041Sobrien 33091041Sobrien /* Copy fields from new or old core structure. */ 33191041Sobrien if (CORE_NEW (core)) 33291041Sobrien { 33391041Sobrien c_flag = core.new.c_flag; 33491041Sobrien c_stack = (file_ptr) core.new.c_stack; 33591041Sobrien c_size = core.new.c_size; 33691041Sobrien c_stackend = CNEW_STACKORG (core.new) + c_size; 33791041Sobrien c_lsize = CNEW_LSIZE (core.new); 33891041Sobrien c_loader = CNEW_LOADER (core.new); 33991041Sobrien proc64 = CNEW_PROC64 (core.new); 34091041Sobrien } 34191041Sobrien else 34291041Sobrien { 34391041Sobrien c_flag = core.old.c_flag; 344218822Sdim c_stack = (file_ptr) (ptr_to_uint) core.old.c_stack; 34591041Sobrien c_size = core.old.c_size; 34691041Sobrien c_stackend = COLD_STACKEND; 34791041Sobrien c_lsize = 0x7ffffff; 348218822Sdim c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old); 34991041Sobrien proc64 = 0; 35091041Sobrien } 35191041Sobrien 35291041Sobrien if (proc64) 35391041Sobrien { 35491041Sobrien c_regsize = sizeof (CNEW_CONTEXT64 (core.new)); 35591041Sobrien c_regptr = &CNEW_CONTEXT64 (core.new); 35691041Sobrien } 35791041Sobrien else if (CORE_NEW (core)) 35891041Sobrien { 35991041Sobrien c_regsize = sizeof (CNEW_MSTSAVE (core.new)); 36091041Sobrien c_regptr = &CNEW_MSTSAVE (core.new); 36191041Sobrien } 36291041Sobrien else 36391041Sobrien { 36491041Sobrien c_regsize = sizeof (COLD_MSTSAVE (core.old)); 36591041Sobrien c_regptr = &COLD_MSTSAVE (core.old); 36691041Sobrien } 36791041Sobrien c_regoff = (char *) c_regptr - (char *) &core; 36891041Sobrien 36991041Sobrien if (bfd_stat (abfd, &statbuf) < 0) 37091041Sobrien { 37191041Sobrien bfd_set_error (bfd_error_system_call); 37291041Sobrien return NULL; 37391041Sobrien } 37491041Sobrien 37591041Sobrien /* If the core file ulimit is too small, the system will first 37691041Sobrien omit the data segment, then omit the stack, then decline to 37791041Sobrien dump core altogether (as far as I know UBLOCK_VALID and LE_VALID 37891041Sobrien are always set) (this is based on experimentation on AIX 3.2). 37991041Sobrien Now, the thing is that GDB users will be surprised 38091041Sobrien if segments just silently don't appear (well, maybe they would 38191041Sobrien think to check "info files", I don't know). 38291041Sobrien 38391041Sobrien For the data segment, we have no choice but to keep going if it's 38491041Sobrien not there, since the default behavior is not to dump it (regardless 38591041Sobrien of the ulimit, it's based on SA_FULLDUMP). But for the stack segment, 38691041Sobrien if it's not there, we refuse to have anything to do with this core 38791041Sobrien file. The usefulness of a core dump without a stack segment is pretty 38891041Sobrien limited anyway. */ 38991041Sobrien 39091041Sobrien if (!(c_flag & UBLOCK_VALID) 39191041Sobrien || !(c_flag & LE_VALID)) 39291041Sobrien { 39391041Sobrien bfd_set_error (bfd_error_wrong_format); 39491041Sobrien return NULL; 39591041Sobrien } 39691041Sobrien 39791041Sobrien if (!(c_flag & USTACK_VALID)) 39891041Sobrien { 39991041Sobrien bfd_set_error (bfd_error_file_truncated); 40091041Sobrien return NULL; 40191041Sobrien } 40291041Sobrien 40391041Sobrien /* Don't check the core file size for a full core, AIX 4.1 includes 40491041Sobrien additional shared library sections in a full core. */ 40591041Sobrien if (!(c_flag & (FULL_CORE | CORE_TRUNC))) 40691041Sobrien { 40791041Sobrien /* If the size is wrong, it means we're misinterpreting something. */ 40891041Sobrien if (c_stack + (file_ptr) c_size != statbuf.st_size) 40991041Sobrien { 41091041Sobrien bfd_set_error (bfd_error_wrong_format); 41191041Sobrien return NULL; 41291041Sobrien } 41391041Sobrien } 41491041Sobrien 41591041Sobrien /* Sanity check on the c_tab field. */ 41691041Sobrien if (!CORE_NEW (core) && (c_loader < (file_ptr) sizeof core.old || 41791041Sobrien c_loader >= statbuf.st_size || 41891041Sobrien c_loader >= c_stack)) 41991041Sobrien { 42091041Sobrien bfd_set_error (bfd_error_wrong_format); 42191041Sobrien return NULL; 42291041Sobrien } 42391041Sobrien 42491041Sobrien /* Issue warning if the core file was truncated during writing. */ 42591041Sobrien if (c_flag & CORE_TRUNC) 42691041Sobrien (*_bfd_error_handler) (_("%s: warning core file truncated"), 42791041Sobrien bfd_get_filename (abfd)); 42891041Sobrien 42991041Sobrien /* Allocate core file header. */ 43091041Sobrien size = CORE_NEW (core) ? sizeof (core.new) : sizeof (core.old); 43191041Sobrien tmpptr = (char *) bfd_zalloc (abfd, (bfd_size_type) size); 43291041Sobrien if (!tmpptr) 43391041Sobrien return NULL; 43491041Sobrien 43591041Sobrien /* Copy core file header. */ 43691041Sobrien memcpy (tmpptr, &core, size); 43791041Sobrien set_tdata (abfd, tmpptr); 43891041Sobrien 43991041Sobrien /* Set architecture. */ 44091041Sobrien if (CORE_NEW (core)) 44191041Sobrien { 44291041Sobrien enum bfd_architecture arch; 44391041Sobrien unsigned long mach; 44491041Sobrien 44591041Sobrien switch (CNEW_IMPL (core.new)) 44691041Sobrien { 44791041Sobrien case POWER_RS1: 44891041Sobrien case POWER_RSC: 44991041Sobrien case POWER_RS2: 45091041Sobrien arch = bfd_arch_rs6000; 45191041Sobrien mach = bfd_mach_rs6k; 45291041Sobrien break; 45391041Sobrien default: 45491041Sobrien arch = bfd_arch_powerpc; 45591041Sobrien mach = bfd_mach_ppc; 45691041Sobrien break; 45791041Sobrien } 45891041Sobrien bfd_default_set_arch_mach (abfd, arch, mach); 45991041Sobrien } 46091041Sobrien 46191041Sobrien /* .stack section. */ 46291041Sobrien if (!make_bfd_asection (abfd, ".stack", 46391041Sobrien SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, 46491041Sobrien c_size, c_stackend - c_size, c_stack)) 46591041Sobrien goto fail; 46691041Sobrien 46791041Sobrien /* .reg section for all registers. */ 46891041Sobrien if (!make_bfd_asection (abfd, ".reg", 46991041Sobrien SEC_HAS_CONTENTS, 47091041Sobrien c_regsize, (bfd_vma) 0, c_regoff)) 47191041Sobrien goto fail; 47291041Sobrien 47391041Sobrien /* .ldinfo section. 47491041Sobrien To actually find out how long this section is in this particular 47591041Sobrien core dump would require going down the whole list of struct ld_info's. 47691041Sobrien See if we can just fake it. */ 47791041Sobrien if (!make_bfd_asection (abfd, ".ldinfo", 47891041Sobrien SEC_HAS_CONTENTS, 47991041Sobrien c_lsize, (bfd_vma) 0, c_loader)) 48091041Sobrien goto fail; 48191041Sobrien 48291041Sobrien#ifndef CORE_VERSION_1 48391041Sobrien /* .data section if present. 48491041Sobrien AIX 3 dumps the complete data section and sets FULL_CORE if the 48591041Sobrien ulimit is large enough, otherwise the data section is omitted. 48691041Sobrien AIX 4 sets FULL_CORE even if the core file is truncated, we have 48791041Sobrien to examine core.c_datasize below to find out the actual size of 48891041Sobrien the .data section. */ 48991041Sobrien if (c_flag & FULL_CORE) 49091041Sobrien { 49191041Sobrien if (!make_bfd_asection (abfd, ".data", 49291041Sobrien SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, 49391041Sobrien (bfd_size_type) core.old.c_u.u_dsize, 49491041Sobrien (bfd_vma) 49591041Sobrien CDATA_ADDR (core.old.c_u.u_dsize), 49691041Sobrien c_stack + c_size)) 49791041Sobrien goto fail; 49891041Sobrien } 49991041Sobrien#endif 50091041Sobrien 50191041Sobrien#ifdef CORE_VERSION_1 50291041Sobrien /* AIX 4 adds data sections from loaded objects to the core file, 50391041Sobrien which can be found by examining ldinfo, and anonymously mmapped 50491041Sobrien regions. */ 50591041Sobrien { 50691041Sobrien LdInfo ldinfo; 50791041Sobrien bfd_size_type ldi_datasize; 50891041Sobrien file_ptr ldi_core; 50991041Sobrien uint ldi_next; 51091041Sobrien bfd_vma ldi_dataorg; 51191041Sobrien 51291041Sobrien /* Fields from new and old core structures. */ 51391041Sobrien bfd_size_type c_datasize, c_vmregions; 51491041Sobrien file_ptr c_data, c_vmm; 51591041Sobrien 51691041Sobrien if (CORE_NEW (core)) 51791041Sobrien { 51891041Sobrien c_datasize = CNEW_DATASIZE (core.new); 51991041Sobrien c_data = (file_ptr) core.new.c_data; 52091041Sobrien c_vmregions = core.new.c_vmregions; 52191041Sobrien c_vmm = (file_ptr) core.new.c_vmm; 52291041Sobrien } 52391041Sobrien else 52491041Sobrien { 52591041Sobrien c_datasize = core.old.c_datasize; 526218822Sdim c_data = (file_ptr) (ptr_to_uint) core.old.c_data; 52791041Sobrien c_vmregions = core.old.c_vmregions; 528218822Sdim c_vmm = (file_ptr) (ptr_to_uint) core.old.c_vmm; 52991041Sobrien } 53091041Sobrien 53191041Sobrien /* .data section from executable. */ 53291041Sobrien if (c_datasize) 53391041Sobrien { 53491041Sobrien if (!make_bfd_asection (abfd, ".data", 53591041Sobrien SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, 53691041Sobrien c_datasize, 53791041Sobrien (bfd_vma) CDATA_ADDR (c_datasize), 53891041Sobrien c_data)) 53991041Sobrien goto fail; 54091041Sobrien } 54191041Sobrien 54291041Sobrien /* .data sections from loaded objects. */ 54391041Sobrien if (proc64) 54491041Sobrien size = (int) ((LdInfo *) 0)->l64.ldinfo_filename; 54591041Sobrien else 54691041Sobrien size = (int) ((LdInfo *) 0)->l32.ldinfo_filename; 54791041Sobrien 54891041Sobrien while (1) 54991041Sobrien { 55091041Sobrien if (bfd_seek (abfd, c_loader, SEEK_SET) != 0) 55191041Sobrien goto fail; 55291041Sobrien if (bfd_bread (&ldinfo, size, abfd) != size) 55391041Sobrien goto fail; 55491041Sobrien 55591041Sobrien if (proc64) 55691041Sobrien { 55791041Sobrien ldi_core = ldinfo.l64.ldinfo_core; 55891041Sobrien ldi_datasize = ldinfo.l64.ldinfo_datasize; 55991041Sobrien ldi_dataorg = (bfd_vma) ldinfo.l64.ldinfo_dataorg; 56091041Sobrien ldi_next = ldinfo.l64.ldinfo_next; 56191041Sobrien } 56291041Sobrien else 56391041Sobrien { 56491041Sobrien ldi_core = ldinfo.l32.ldinfo_core; 56591041Sobrien ldi_datasize = ldinfo.l32.ldinfo_datasize; 56691041Sobrien ldi_dataorg = (bfd_vma) (long) ldinfo.l32.ldinfo_dataorg; 56791041Sobrien ldi_next = ldinfo.l32.ldinfo_next; 56891041Sobrien } 56991041Sobrien 57091041Sobrien if (ldi_core) 57191041Sobrien if (!make_bfd_asection (abfd, ".data", 57291041Sobrien SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, 57391041Sobrien ldi_datasize, ldi_dataorg, ldi_core)) 57491041Sobrien goto fail; 57591041Sobrien 57691041Sobrien if (ldi_next == 0) 57791041Sobrien break; 57891041Sobrien c_loader += ldi_next; 57991041Sobrien } 58091041Sobrien 58191041Sobrien /* .vmdata sections from anonymously mmapped regions. */ 58291041Sobrien if (c_vmregions) 58391041Sobrien { 58491041Sobrien bfd_size_type i; 58591041Sobrien 58691041Sobrien if (bfd_seek (abfd, c_vmm, SEEK_SET) != 0) 58791041Sobrien goto fail; 58891041Sobrien 58991041Sobrien for (i = 0; i < c_vmregions; i++) 59091041Sobrien { 59191041Sobrien VmInfo vminfo; 59291041Sobrien bfd_size_type vminfo_size; 59391041Sobrien file_ptr vminfo_offset; 59491041Sobrien bfd_vma vminfo_addr; 59591041Sobrien 59691041Sobrien size = CORE_NEW (core) ? sizeof (vminfo.new) : sizeof (vminfo.old); 59791041Sobrien if (bfd_bread (&vminfo, size, abfd) != size) 59891041Sobrien goto fail; 59991041Sobrien 60091041Sobrien if (CORE_NEW (core)) 60191041Sobrien { 60291041Sobrien vminfo_addr = (bfd_vma) vminfo.new.vminfo_addr; 60391041Sobrien vminfo_size = vminfo.new.vminfo_size; 60491041Sobrien vminfo_offset = vminfo.new.vminfo_offset; 60591041Sobrien } 60691041Sobrien else 60791041Sobrien { 60891041Sobrien vminfo_addr = (bfd_vma) (long) vminfo.old.vminfo_addr; 60991041Sobrien vminfo_size = vminfo.old.vminfo_size; 61091041Sobrien vminfo_offset = vminfo.old.vminfo_offset; 61191041Sobrien } 61291041Sobrien 61391041Sobrien if (vminfo_offset) 61491041Sobrien if (!make_bfd_asection (abfd, ".vmdata", 61591041Sobrien SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, 61691041Sobrien vminfo_size, vminfo_addr, 61791041Sobrien vminfo_offset)) 61891041Sobrien goto fail; 61991041Sobrien } 62091041Sobrien } 62191041Sobrien } 62291041Sobrien#endif 62391041Sobrien 62491041Sobrien return abfd->xvec; /* This is garbage for now. */ 62591041Sobrien 62691041Sobrien fail: 62791041Sobrien bfd_release (abfd, abfd->tdata.any); 62891041Sobrien abfd->tdata.any = NULL; 62991041Sobrien bfd_section_list_clear (abfd); 63091041Sobrien return NULL; 63191041Sobrien} 63291041Sobrien 633130561Sobrien/* Return `TRUE' if given core is from the given executable. */ 63491041Sobrien 635130561Sobrienbfd_boolean 636218822Sdimrs6000coff_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd) 63791041Sobrien{ 63891041Sobrien CoreHdr core; 63991041Sobrien bfd_size_type size; 64091041Sobrien char *path, *s; 64191041Sobrien size_t alloc; 64291041Sobrien const char *str1, *str2; 643130561Sobrien bfd_boolean ret; 64491041Sobrien file_ptr c_loader; 64591041Sobrien 64691041Sobrien if (!read_hdr (core_bfd, &core)) 647130561Sobrien return FALSE; 64891041Sobrien 64991041Sobrien if (CORE_NEW (core)) 65091041Sobrien c_loader = CNEW_LOADER (core.new); 65191041Sobrien else 652218822Sdim c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old); 65391041Sobrien 65491041Sobrien if (CORE_NEW (core) && CNEW_PROC64 (core.new)) 65591041Sobrien size = (int) ((LdInfo *) 0)->l64.ldinfo_filename; 65691041Sobrien else 65791041Sobrien size = (int) ((LdInfo *) 0)->l32.ldinfo_filename; 65891041Sobrien 65991041Sobrien if (bfd_seek (core_bfd, c_loader + size, SEEK_SET) != 0) 660130561Sobrien return FALSE; 66191041Sobrien 66291041Sobrien alloc = 100; 66391041Sobrien path = bfd_malloc ((bfd_size_type) alloc); 66491041Sobrien if (path == NULL) 665130561Sobrien return FALSE; 66691041Sobrien s = path; 66791041Sobrien 66891041Sobrien while (1) 66991041Sobrien { 67091041Sobrien if (bfd_bread (s, (bfd_size_type) 1, core_bfd) != 1) 67191041Sobrien { 67291041Sobrien free (path); 673130561Sobrien return FALSE; 67491041Sobrien } 67591041Sobrien if (*s == '\0') 67691041Sobrien break; 67791041Sobrien ++s; 67891041Sobrien if (s == path + alloc) 67991041Sobrien { 68091041Sobrien char *n; 68191041Sobrien 68291041Sobrien alloc *= 2; 68391041Sobrien n = bfd_realloc (path, (bfd_size_type) alloc); 68491041Sobrien if (n == NULL) 68591041Sobrien { 68691041Sobrien free (path); 687130561Sobrien return FALSE; 68891041Sobrien } 68991041Sobrien s = n + (path - s); 69091041Sobrien path = n; 69191041Sobrien } 69291041Sobrien } 69391041Sobrien 69491041Sobrien str1 = strrchr (path, '/'); 69591041Sobrien str2 = strrchr (exec_bfd->filename, '/'); 69691041Sobrien 69791041Sobrien /* step over character '/' */ 69891041Sobrien str1 = str1 != NULL ? str1 + 1 : path; 69991041Sobrien str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename; 70091041Sobrien 70191041Sobrien if (strcmp (str1, str2) == 0) 702130561Sobrien ret = TRUE; 70391041Sobrien else 704130561Sobrien ret = FALSE; 70591041Sobrien 70691041Sobrien free (path); 70791041Sobrien 70891041Sobrien return ret; 70991041Sobrien} 71091041Sobrien 71191041Sobrienchar * 712218822Sdimrs6000coff_core_file_failing_command (bfd *abfd) 71391041Sobrien{ 71491041Sobrien CoreHdr *core = core_hdr (abfd); 71591041Sobrien char *com = CORE_NEW (*core) ? 71691041Sobrien CNEW_COMM (core->new) : COLD_COMM (core->old); 71791041Sobrien 71891041Sobrien if (*com) 71991041Sobrien return com; 72091041Sobrien else 72191041Sobrien return 0; 72291041Sobrien} 72391041Sobrien 72491041Sobrienint 725218822Sdimrs6000coff_core_file_failing_signal (bfd *abfd) 72691041Sobrien{ 72791041Sobrien CoreHdr *core = core_hdr (abfd); 72891041Sobrien return CORE_NEW (*core) ? core->new.c_signo : core->old.c_signo; 72991041Sobrien} 73091041Sobrien 73191041Sobrien#endif /* AIX_CORE */ 732