xref: /openbsd-src/gnu/usr.bin/binutils/bfd/rs6000-core.c (revision c074d1c999f3e07019cd5e9a2f190b057ef3b935)
12159047fSniklas /* IBM RS/6000 "XCOFF" back-end for BFD.
2b55d4692Sfgsch    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
3*c074d1c9Sdrahn    2001, 2002
4b305b0f1Sespie    Free Software Foundation, Inc.
52159047fSniklas    FIXME: Can someone provide a transliteration of this name into ASCII?
62159047fSniklas    Using the following chars caused a compiler warning on HIUX (so I replaced
72159047fSniklas    them with octal escapes), and isn't useful without an understanding of what
82159047fSniklas    character set it is.
92159047fSniklas    Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
102159047fSniklas      and John Gilmore.
112159047fSniklas    Archive support from Damon A. Permezel.
122159047fSniklas    Contributed by IBM Corporation and Cygnus Support.
132159047fSniklas 
142159047fSniklas    This file is part of BFD, the Binary File Descriptor library.
152159047fSniklas 
162159047fSniklas    This program is free software; you can redistribute it and/or modify
172159047fSniklas    it under the terms of the GNU General Public License as published by
182159047fSniklas    the Free Software Foundation; either version 2 of the License, or
192159047fSniklas    (at your option) any later version.
202159047fSniklas 
212159047fSniklas    This program is distributed in the hope that it will be useful,
222159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
232159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
242159047fSniklas    GNU General Public License for more details.
252159047fSniklas 
262159047fSniklas    You should have received a copy of the GNU General Public License
272159047fSniklas    along with this program; if not, write to the Free Software
282159047fSniklas    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
292159047fSniklas 
302159047fSniklas /* This port currently only handles reading object files, except when
312159047fSniklas    compiled on an RS/6000 host.  -- no archive support, no core files.
322159047fSniklas    In all cases, it does not support writing.
332159047fSniklas 
342159047fSniklas    This is in a separate file from coff-rs6000.c, because it includes
35b55d4692Sfgsch    system include files that conflict with coff/rs6000.h.  */
362159047fSniklas 
372159047fSniklas /* Internalcoff.h and coffcode.h modify themselves based on this flag.  */
382159047fSniklas #define RS6000COFF_C 1
392159047fSniklas 
40b305b0f1Sespie /* The AIX 4.1 kernel is obviously compiled with -D_LONG_LONG, so
41b305b0f1Sespie    we have to define _LONG_LONG for older versions of gcc to get the
42b305b0f1Sespie    proper alignments in the user structure.  */
43b305b0f1Sespie #if defined(_AIX41) && !defined(_LONG_LONG)
44b305b0f1Sespie #define _LONG_LONG
45b305b0f1Sespie #endif
46b305b0f1Sespie 
472159047fSniklas #include "bfd.h"
482159047fSniklas #include "sysdep.h"
492159047fSniklas #include "libbfd.h"
502159047fSniklas 
512159047fSniklas #ifdef AIX_CORE
522159047fSniklas 
532159047fSniklas /* AOUTHDR is defined by the above.  We need another defn of it, from the
542159047fSniklas    system include files.  Punt the old one and get us a new name for the
552159047fSniklas    typedef in the system include files.  */
562159047fSniklas #ifdef AOUTHDR
572159047fSniklas #undef AOUTHDR
582159047fSniklas #endif
592159047fSniklas #define	AOUTHDR	second_AOUTHDR
602159047fSniklas 
612159047fSniklas #undef	SCNHDR
622159047fSniklas 
632159047fSniklas /* ------------------------------------------------------------------------ */
642159047fSniklas /*	Support for core file stuff..					    */
652159047fSniklas /* ------------------------------------------------------------------------ */
662159047fSniklas 
672159047fSniklas #include <sys/user.h>
68b55d4692Sfgsch #define __LDINFO_PTRACE32__	/* for __ld_info32 */
69b55d4692Sfgsch #define __LDINFO_PTRACE64__	/* for __ld_info64 */
702159047fSniklas #include <sys/ldr.h>
712159047fSniklas #include <sys/core.h>
72b55d4692Sfgsch #include <sys/systemcfg.h>
732159047fSniklas 
74b55d4692Sfgsch #define	core_hdr(bfd)		((CoreHdr *) bfd->tdata.any)
752159047fSniklas 
76b55d4692Sfgsch /* AIX 4.1 changed the names and locations of a few items in the core file.
77b55d4692Sfgsch    AIX 4.3 defined an entirely new structure, core_dumpx, but kept support for
78b55d4692Sfgsch    the previous 4.1 structure, core_dump.
792159047fSniklas 
80b55d4692Sfgsch    AIX_CORE_DUMPX_CORE is defined (by configure) on AIX 4.3+, and
81b55d4692Sfgsch    CORE_VERSION_1 is defined (by AIX core.h) as 2 on AIX 4.3+ and as 1 on AIX
82b55d4692Sfgsch    4.1 and 4.2.  AIX pre-4.1 (aka 3.x) either doesn't define CORE_VERSION_1
83b55d4692Sfgsch    or else defines it as 0.  */
842159047fSniklas 
85b55d4692Sfgsch #if defined(CORE_VERSION_1) && !CORE_VERSION_1
86b55d4692Sfgsch # undef CORE_VERSION_1
87b55d4692Sfgsch #endif
882159047fSniklas 
89b55d4692Sfgsch /* The following union and macros allow this module to compile on all AIX
90b55d4692Sfgsch    versions and to handle both core_dumpx and core_dump on 4.3+.  CNEW_*()
91b55d4692Sfgsch    and COLD_*() macros respectively retrieve core_dumpx and core_dump
92b55d4692Sfgsch    values.  */
932159047fSniklas 
94b55d4692Sfgsch /* Union of 32-bit and 64-bit versions of ld_info.  */
95b305b0f1Sespie 
96b55d4692Sfgsch typedef union {
97b55d4692Sfgsch #ifdef __ld_info32
98b55d4692Sfgsch   struct __ld_info32 l32;
99b55d4692Sfgsch   struct __ld_info64 l64;
100b55d4692Sfgsch #else
101b55d4692Sfgsch   struct ld_info l32;
102b55d4692Sfgsch   struct ld_info l64;
103b55d4692Sfgsch #endif
104b55d4692Sfgsch } LdInfo;
105b55d4692Sfgsch 
106b55d4692Sfgsch /* Union of old and new core dump structures.  */
107b55d4692Sfgsch 
108b55d4692Sfgsch typedef union {
109b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
110b55d4692Sfgsch   struct core_dumpx new;	/* new AIX 4.3+ core dump */
111b55d4692Sfgsch #else
112b55d4692Sfgsch   struct core_dump new;		/* for simpler coding */
113b55d4692Sfgsch #endif
114b55d4692Sfgsch   struct core_dump old;		/* old AIX 4.2- core dump, still used on
115b55d4692Sfgsch 				   4.3+ with appropriate SMIT config */
116b55d4692Sfgsch } CoreHdr;
117b55d4692Sfgsch 
118b55d4692Sfgsch /* Union of old and new vm_info structures.  */
119b55d4692Sfgsch 
120b55d4692Sfgsch #ifdef CORE_VERSION_1
121b55d4692Sfgsch typedef union {
122b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
123b55d4692Sfgsch   struct vm_infox new;
124b55d4692Sfgsch #else
125b55d4692Sfgsch   struct vm_info new;
126b55d4692Sfgsch #endif
127b55d4692Sfgsch   struct vm_info old;
128b55d4692Sfgsch } VmInfo;
129b55d4692Sfgsch #endif
130b55d4692Sfgsch 
131b55d4692Sfgsch /* Return whether CoreHdr C is in new or old format.  */
132b305b0f1Sespie 
133b305b0f1Sespie #ifdef AIX_CORE_DUMPX_CORE
134b55d4692Sfgsch # define CORE_NEW(c)	(!(c).old.c_entries)
135b305b0f1Sespie #else
136b55d4692Sfgsch # define CORE_NEW(c)	0
137b55d4692Sfgsch #endif
138b55d4692Sfgsch 
139b55d4692Sfgsch /* Return the c_stackorg field from struct core_dumpx C.  */
140b55d4692Sfgsch 
141b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
142b55d4692Sfgsch # define CNEW_STACKORG(c)	(c).c_stackorg
143b55d4692Sfgsch #else
144b55d4692Sfgsch # define CNEW_STACKORG(c)	0
145b55d4692Sfgsch #endif
146b55d4692Sfgsch 
147b55d4692Sfgsch /* Return the offset to the loader region from struct core_dump C.  */
148b55d4692Sfgsch 
149b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
150b55d4692Sfgsch # define CNEW_LOADER(c)	(c).c_loader
151b55d4692Sfgsch #else
152b55d4692Sfgsch # define CNEW_LOADER(c)	0
153b55d4692Sfgsch #endif
154b55d4692Sfgsch 
155b55d4692Sfgsch /* Return the offset to the loader region from struct core_dump C.  */
156b55d4692Sfgsch 
157b55d4692Sfgsch #define COLD_LOADER(c)	(c).c_tab
158b55d4692Sfgsch 
159b55d4692Sfgsch /* Return the c_lsize field from struct core_dumpx C.  */
160b55d4692Sfgsch 
161b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
162b55d4692Sfgsch # define CNEW_LSIZE(c)	(c).c_lsize
163b55d4692Sfgsch #else
164b55d4692Sfgsch # define CNEW_LSIZE(c)	0
165b55d4692Sfgsch #endif
166b55d4692Sfgsch 
167b55d4692Sfgsch /* Return the c_dataorg field from struct core_dumpx C.  */
168b55d4692Sfgsch 
169b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
170b55d4692Sfgsch # define CNEW_DATAORG(c)	(c).c_dataorg
171b55d4692Sfgsch #else
172b55d4692Sfgsch # define CNEW_DATAORG(c)	0
173b55d4692Sfgsch #endif
174b55d4692Sfgsch 
175b55d4692Sfgsch /* Return the c_datasize field from struct core_dumpx C.  */
176b55d4692Sfgsch 
177b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
178b55d4692Sfgsch # define CNEW_DATASIZE(c)	(c).c_datasize
179b55d4692Sfgsch #else
180b55d4692Sfgsch # define CNEW_DATASIZE(c)	0
181b55d4692Sfgsch #endif
182b55d4692Sfgsch 
183b55d4692Sfgsch /* Return the c_impl field from struct core_dumpx C.  */
184b55d4692Sfgsch 
185*c074d1c9Sdrahn #if defined (HAVE_ST_C_IMPL) || defined (AIX_5_CORE)
186b55d4692Sfgsch # define CNEW_IMPL(c)	(c).c_impl
187b55d4692Sfgsch #else
188b55d4692Sfgsch # define CNEW_IMPL(c)	0
189b55d4692Sfgsch #endif
190b55d4692Sfgsch 
191b55d4692Sfgsch /* Return the command string from struct core_dumpx C.  */
192b55d4692Sfgsch 
193b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
194b55d4692Sfgsch # define CNEW_COMM(c)	(c).c_u.U_proc.pi_comm
195b55d4692Sfgsch #else
196b55d4692Sfgsch # define CNEW_COMM(c)	0
197b55d4692Sfgsch #endif
198b55d4692Sfgsch 
199b55d4692Sfgsch /* Return the command string from struct core_dump C.  */
200b55d4692Sfgsch 
2012159047fSniklas #ifdef CORE_VERSION_1
202b55d4692Sfgsch # define COLD_COMM(c)	(c).c_u.U_comm
2032159047fSniklas #else
204b55d4692Sfgsch # define COLD_COMM(c)	(c).c_u.u_comm
2052159047fSniklas #endif
2062159047fSniklas 
207b55d4692Sfgsch /* Return the struct __context64 pointer from struct core_dumpx C.  */
2082159047fSniklas 
209b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
210b55d4692Sfgsch # define CNEW_CONTEXT64(c)	(c).c_flt.hctx.r64
211b55d4692Sfgsch #else
212b55d4692Sfgsch # define CNEW_CONTEXT64(c)	c
213b55d4692Sfgsch #endif
214b55d4692Sfgsch 
215b55d4692Sfgsch /* Return the struct mstsave pointer from struct core_dumpx C.  */
216b55d4692Sfgsch 
217b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
218b55d4692Sfgsch # define CNEW_MSTSAVE(c)	(c).c_flt.hctx.r32
219b55d4692Sfgsch #else
220b55d4692Sfgsch # define CNEW_MSTSAVE(c)	c
221b55d4692Sfgsch #endif
222b55d4692Sfgsch 
223b55d4692Sfgsch /* Return the struct mstsave pointer from struct core_dump C.  */
224b55d4692Sfgsch 
225b55d4692Sfgsch #ifdef CORE_VERSION_1
226b55d4692Sfgsch # define COLD_MSTSAVE(c)	(c).c_mst
227b55d4692Sfgsch #else
228b55d4692Sfgsch # define COLD_MSTSAVE(c)	(c).c_u.u_save
229b55d4692Sfgsch #endif
230b55d4692Sfgsch 
231b55d4692Sfgsch /* Return whether struct core_dumpx is from a 64-bit process.  */
232b55d4692Sfgsch 
233b55d4692Sfgsch #ifdef AIX_CORE_DUMPX_CORE
234b55d4692Sfgsch # define CNEW_PROC64(c)		IS_PROC64(&(c).c_u.U_proc)
235b55d4692Sfgsch #else
236b55d4692Sfgsch # define CNEW_PROC64(c)		0
237b55d4692Sfgsch #endif
238b55d4692Sfgsch 
239b55d4692Sfgsch /* Magic end-of-stack addresses for old core dumps.  This is _very_ fragile,
240b55d4692Sfgsch    but I don't see any easy way to get that info right now.  */
241b55d4692Sfgsch 
242b55d4692Sfgsch #ifdef CORE_VERSION_1
243b55d4692Sfgsch # define COLD_STACKEND	0x2ff23000
244b55d4692Sfgsch #else
245b55d4692Sfgsch # define COLD_STACKEND	0x2ff80000
246b55d4692Sfgsch #endif
247b55d4692Sfgsch 
248b55d4692Sfgsch /* Size of the leading portion that old and new core dump structures have in
249b55d4692Sfgsch    common.  */
250b55d4692Sfgsch #define CORE_COMMONSZ	((int) &((struct core_dump *) 0)->c_entries \
251b55d4692Sfgsch 			 + sizeof (((struct core_dump *) 0)->c_entries))
252b55d4692Sfgsch 
253b55d4692Sfgsch /* Try to read into CORE the header from the core file associated with ABFD.
254b55d4692Sfgsch    Return success.  */
255b55d4692Sfgsch 
256*c074d1c9Sdrahn static bfd_boolean
read_hdr(bfd * abfd,CoreHdr * core)257b55d4692Sfgsch read_hdr (bfd *abfd, CoreHdr *core)
258b55d4692Sfgsch {
259b55d4692Sfgsch   bfd_size_type size;
260b55d4692Sfgsch 
261*c074d1c9Sdrahn   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
262*c074d1c9Sdrahn     return FALSE;
263b55d4692Sfgsch 
264b55d4692Sfgsch   /* Read the leading portion that old and new core dump structures have in
265b55d4692Sfgsch      common.  */
266*c074d1c9Sdrahn   size = CORE_COMMONSZ;
267*c074d1c9Sdrahn   if (bfd_bread (core, size, abfd) != size)
268*c074d1c9Sdrahn     return FALSE;
269b55d4692Sfgsch 
270b55d4692Sfgsch   /* Read the trailing portion of the structure.  */
271*c074d1c9Sdrahn   if (CORE_NEW (*core))
272*c074d1c9Sdrahn     size = sizeof (core->new);
273*c074d1c9Sdrahn   else
274*c074d1c9Sdrahn     size = sizeof (core->old);
275*c074d1c9Sdrahn   size -= CORE_COMMONSZ;
276*c074d1c9Sdrahn   return bfd_bread ((char *) core + CORE_COMMONSZ, size, abfd) == size;
277b55d4692Sfgsch }
278b305b0f1Sespie 
279b305b0f1Sespie static asection *
make_bfd_asection(abfd,name,flags,_raw_size,vma,filepos)280b305b0f1Sespie make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
281b305b0f1Sespie      bfd *abfd;
282*c074d1c9Sdrahn      const char *name;
283b305b0f1Sespie      flagword flags;
284b305b0f1Sespie      bfd_size_type _raw_size;
285b305b0f1Sespie      bfd_vma vma;
286b305b0f1Sespie      file_ptr filepos;
287b305b0f1Sespie {
288b305b0f1Sespie   asection *asect;
289b305b0f1Sespie 
290b305b0f1Sespie   asect = bfd_make_section_anyway (abfd, name);
291b305b0f1Sespie   if (!asect)
292b305b0f1Sespie     return NULL;
293b305b0f1Sespie 
294b305b0f1Sespie   asect->flags = flags;
295b305b0f1Sespie   asect->_raw_size = _raw_size;
296b305b0f1Sespie   asect->vma = vma;
297b305b0f1Sespie   asect->filepos = filepos;
298b305b0f1Sespie   asect->alignment_power = 8;
299b305b0f1Sespie 
300b305b0f1Sespie   return asect;
301b305b0f1Sespie }
3022159047fSniklas 
3032159047fSniklas /* Decide if a given bfd represents a `core' file or not. There really is no
3042159047fSniklas    magic number or anything like, in rs6000coff.  */
3052159047fSniklas 
3062159047fSniklas const bfd_target *
rs6000coff_core_p(abfd)3072159047fSniklas rs6000coff_core_p (abfd)
3082159047fSniklas      bfd *abfd;
3092159047fSniklas {
310b55d4692Sfgsch   CoreHdr core;
3112159047fSniklas   struct stat statbuf;
312b55d4692Sfgsch   bfd_size_type size;
3132159047fSniklas   char *tmpptr;
3142159047fSniklas 
315b55d4692Sfgsch   /* Values from new and old core structures.  */
316b55d4692Sfgsch   int c_flag;
317b55d4692Sfgsch   file_ptr c_stack, c_regoff, c_loader;
318b55d4692Sfgsch   bfd_size_type c_size, c_regsize, c_lsize;
319b55d4692Sfgsch   bfd_vma c_stackend;
320b55d4692Sfgsch   void *c_regptr;
321b55d4692Sfgsch   int proc64;
3222159047fSniklas 
323b55d4692Sfgsch   if (!read_hdr (abfd, &core))
3242159047fSniklas     {
325b305b0f1Sespie       if (bfd_get_error () != bfd_error_system_call)
3262159047fSniklas 	bfd_set_error (bfd_error_wrong_format);
3272159047fSniklas       return NULL;
3282159047fSniklas     }
3292159047fSniklas 
330b55d4692Sfgsch   /* Copy fields from new or old core structure.  */
331b55d4692Sfgsch   if (CORE_NEW (core))
332b55d4692Sfgsch     {
333b55d4692Sfgsch       c_flag = core.new.c_flag;
334b55d4692Sfgsch       c_stack = (file_ptr) core.new.c_stack;
335b55d4692Sfgsch       c_size = core.new.c_size;
336b55d4692Sfgsch       c_stackend = CNEW_STACKORG (core.new) + c_size;
337b55d4692Sfgsch       c_lsize = CNEW_LSIZE (core.new);
338b55d4692Sfgsch       c_loader = CNEW_LOADER (core.new);
339b55d4692Sfgsch       proc64 = CNEW_PROC64 (core.new);
340b55d4692Sfgsch     }
341b55d4692Sfgsch   else
342b55d4692Sfgsch     {
343b55d4692Sfgsch       c_flag = core.old.c_flag;
344b55d4692Sfgsch       c_stack = (file_ptr) core.old.c_stack;
345b55d4692Sfgsch       c_size = core.old.c_size;
346b55d4692Sfgsch       c_stackend = COLD_STACKEND;
347b55d4692Sfgsch       c_lsize = 0x7ffffff;
348b55d4692Sfgsch       c_loader = (file_ptr) COLD_LOADER (core.old);
349b55d4692Sfgsch       proc64 = 0;
350b55d4692Sfgsch     }
351b55d4692Sfgsch 
352b55d4692Sfgsch   if (proc64)
353b55d4692Sfgsch     {
354b55d4692Sfgsch       c_regsize = sizeof (CNEW_CONTEXT64 (core.new));
355b55d4692Sfgsch       c_regptr = &CNEW_CONTEXT64 (core.new);
356b55d4692Sfgsch     }
357b55d4692Sfgsch   else if (CORE_NEW (core))
358b55d4692Sfgsch     {
359b55d4692Sfgsch       c_regsize = sizeof (CNEW_MSTSAVE (core.new));
360b55d4692Sfgsch       c_regptr = &CNEW_MSTSAVE (core.new);
361b55d4692Sfgsch     }
362b55d4692Sfgsch   else
363b55d4692Sfgsch     {
364b55d4692Sfgsch       c_regsize = sizeof (COLD_MSTSAVE (core.old));
365b55d4692Sfgsch       c_regptr = &COLD_MSTSAVE (core.old);
366b55d4692Sfgsch     }
367b55d4692Sfgsch   c_regoff = (char *) c_regptr - (char *) &core;
368b55d4692Sfgsch 
369b305b0f1Sespie   if (bfd_stat (abfd, &statbuf) < 0)
3702159047fSniklas     {
3712159047fSniklas       bfd_set_error (bfd_error_system_call);
3722159047fSniklas       return NULL;
3732159047fSniklas     }
3742159047fSniklas 
3752159047fSniklas   /* If the core file ulimit is too small, the system will first
3762159047fSniklas      omit the data segment, then omit the stack, then decline to
3772159047fSniklas      dump core altogether (as far as I know UBLOCK_VALID and LE_VALID
3782159047fSniklas      are always set) (this is based on experimentation on AIX 3.2).
3792159047fSniklas      Now, the thing is that GDB users will be surprised
3802159047fSniklas      if segments just silently don't appear (well, maybe they would
381b305b0f1Sespie      think to check "info files", I don't know).
3822159047fSniklas 
3832159047fSniklas      For the data segment, we have no choice but to keep going if it's
3842159047fSniklas      not there, since the default behavior is not to dump it (regardless
3852159047fSniklas      of the ulimit, it's based on SA_FULLDUMP).  But for the stack segment,
3862159047fSniklas      if it's not there, we refuse to have anything to do with this core
3872159047fSniklas      file.  The usefulness of a core dump without a stack segment is pretty
3882159047fSniklas      limited anyway.  */
3892159047fSniklas 
390b55d4692Sfgsch   if (!(c_flag & UBLOCK_VALID)
391b55d4692Sfgsch       || !(c_flag & LE_VALID))
3922159047fSniklas     {
3932159047fSniklas       bfd_set_error (bfd_error_wrong_format);
3942159047fSniklas       return NULL;
3952159047fSniklas     }
3962159047fSniklas 
397b55d4692Sfgsch   if (!(c_flag & USTACK_VALID))
3982159047fSniklas     {
3992159047fSniklas       bfd_set_error (bfd_error_file_truncated);
4002159047fSniklas       return NULL;
4012159047fSniklas     }
4022159047fSniklas 
4032159047fSniklas   /* Don't check the core file size for a full core, AIX 4.1 includes
4042159047fSniklas      additional shared library sections in a full core.  */
405b55d4692Sfgsch   if (!(c_flag & (FULL_CORE | CORE_TRUNC)))
4062159047fSniklas     {
4072159047fSniklas       /* If the size is wrong, it means we're misinterpreting something.  */
408b55d4692Sfgsch       if (c_stack + (file_ptr) c_size != statbuf.st_size)
409b55d4692Sfgsch 	{
4102159047fSniklas 	  bfd_set_error (bfd_error_wrong_format);
4112159047fSniklas 	  return NULL;
4122159047fSniklas 	}
413b55d4692Sfgsch     }
4142159047fSniklas 
4152159047fSniklas   /* Sanity check on the c_tab field.  */
416b55d4692Sfgsch   if (!CORE_NEW (core) && (c_loader < (file_ptr) sizeof core.old ||
417b55d4692Sfgsch 			   c_loader >= statbuf.st_size ||
418b55d4692Sfgsch 			   c_loader >= c_stack))
4192159047fSniklas     {
4202159047fSniklas       bfd_set_error (bfd_error_wrong_format);
4212159047fSniklas       return NULL;
4222159047fSniklas     }
4232159047fSniklas 
424b305b0f1Sespie   /* Issue warning if the core file was truncated during writing.  */
425b55d4692Sfgsch   if (c_flag & CORE_TRUNC)
426b305b0f1Sespie     (*_bfd_error_handler) (_("%s: warning core file truncated"),
427b305b0f1Sespie 			   bfd_get_filename (abfd));
428b305b0f1Sespie 
429b305b0f1Sespie   /* Allocate core file header.  */
430b55d4692Sfgsch   size = CORE_NEW (core) ? sizeof (core.new) : sizeof (core.old);
431*c074d1c9Sdrahn   tmpptr = (char *) bfd_zalloc (abfd, (bfd_size_type) size);
4322159047fSniklas   if (!tmpptr)
4332159047fSniklas     return NULL;
4342159047fSniklas 
435b55d4692Sfgsch   /* Copy core file header.  */
436b55d4692Sfgsch   memcpy (tmpptr, &core, size);
4372159047fSniklas   set_tdata (abfd, tmpptr);
4382159047fSniklas 
439b55d4692Sfgsch   /* Set architecture.  */
440b55d4692Sfgsch   if (CORE_NEW (core))
441b55d4692Sfgsch     {
442b55d4692Sfgsch       enum bfd_architecture arch;
443b55d4692Sfgsch       unsigned long mach;
444b55d4692Sfgsch 
445b55d4692Sfgsch       switch (CNEW_IMPL (core.new))
446b55d4692Sfgsch 	{
447b55d4692Sfgsch 	case POWER_RS1:
448b55d4692Sfgsch 	case POWER_RSC:
449b55d4692Sfgsch 	case POWER_RS2:
450b55d4692Sfgsch 	  arch = bfd_arch_rs6000;
451b55d4692Sfgsch 	  mach = bfd_mach_rs6k;
452b55d4692Sfgsch 	  break;
453b55d4692Sfgsch 	default:
454b55d4692Sfgsch 	  arch = bfd_arch_powerpc;
455b55d4692Sfgsch 	  mach = bfd_mach_ppc;
456b55d4692Sfgsch 	  break;
457b55d4692Sfgsch 	}
458b55d4692Sfgsch       bfd_default_set_arch_mach (abfd, arch, mach);
459b55d4692Sfgsch     }
4602159047fSniklas 
4612159047fSniklas   /* .stack section.  */
462b305b0f1Sespie   if (!make_bfd_asection (abfd, ".stack",
463b305b0f1Sespie 			  SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
464b55d4692Sfgsch 			  c_size, c_stackend - c_size, c_stack))
465*c074d1c9Sdrahn     goto fail;
4662159047fSniklas 
467b55d4692Sfgsch   /* .reg section for all registers.  */
468b305b0f1Sespie   if (!make_bfd_asection (abfd, ".reg",
469b305b0f1Sespie 			  SEC_HAS_CONTENTS,
470b55d4692Sfgsch 			  c_regsize, (bfd_vma) 0, c_regoff))
471*c074d1c9Sdrahn     goto fail;
4722159047fSniklas 
473b305b0f1Sespie   /* .ldinfo section.
474b305b0f1Sespie      To actually find out how long this section is in this particular
4752159047fSniklas      core dump would require going down the whole list of struct ld_info's.
4762159047fSniklas      See if we can just fake it.  */
477b305b0f1Sespie   if (!make_bfd_asection (abfd, ".ldinfo",
478b305b0f1Sespie 			  SEC_HAS_CONTENTS,
479b55d4692Sfgsch 			  c_lsize, (bfd_vma) 0, c_loader))
480*c074d1c9Sdrahn     goto fail;
4812159047fSniklas 
482b305b0f1Sespie #ifndef CORE_VERSION_1
483b305b0f1Sespie   /* .data section if present.
484b305b0f1Sespie      AIX 3 dumps the complete data section and sets FULL_CORE if the
485b305b0f1Sespie      ulimit is large enough, otherwise the data section is omitted.
486b305b0f1Sespie      AIX 4 sets FULL_CORE even if the core file is truncated, we have
487b55d4692Sfgsch      to examine core.c_datasize below to find out the actual size of
488b305b0f1Sespie      the .data section.  */
489b55d4692Sfgsch   if (c_flag & FULL_CORE)
4902159047fSniklas     {
491b305b0f1Sespie       if (!make_bfd_asection (abfd, ".data",
492b305b0f1Sespie 			      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
493b55d4692Sfgsch 			      (bfd_size_type) core.old.c_u.u_dsize,
494b305b0f1Sespie 			      (bfd_vma)
495b55d4692Sfgsch 				CDATA_ADDR (core.old.c_u.u_dsize),
496b55d4692Sfgsch 			      c_stack + c_size))
497*c074d1c9Sdrahn 	goto fail;
4982159047fSniklas     }
499b305b0f1Sespie #endif
500b305b0f1Sespie 
501b305b0f1Sespie #ifdef CORE_VERSION_1
502b305b0f1Sespie   /* AIX 4 adds data sections from loaded objects to the core file,
503b305b0f1Sespie      which can be found by examining ldinfo, and anonymously mmapped
504b305b0f1Sespie      regions.  */
505b305b0f1Sespie   {
506b55d4692Sfgsch     LdInfo ldinfo;
507b55d4692Sfgsch     bfd_size_type ldi_datasize;
508b55d4692Sfgsch     file_ptr ldi_core;
509b55d4692Sfgsch     uint ldi_next;
510b55d4692Sfgsch     bfd_vma ldi_dataorg;
511b55d4692Sfgsch 
512b55d4692Sfgsch     /* Fields from new and old core structures.  */
513b55d4692Sfgsch     bfd_size_type c_datasize, c_vmregions;
514b55d4692Sfgsch     file_ptr c_data, c_vmm;
515b55d4692Sfgsch 
516b55d4692Sfgsch     if (CORE_NEW (core))
517b55d4692Sfgsch       {
518b55d4692Sfgsch 	c_datasize = CNEW_DATASIZE (core.new);
519b55d4692Sfgsch 	c_data = (file_ptr) core.new.c_data;
520b55d4692Sfgsch 	c_vmregions = core.new.c_vmregions;
521b55d4692Sfgsch 	c_vmm = (file_ptr) core.new.c_vmm;
522b55d4692Sfgsch       }
523b55d4692Sfgsch     else
524b55d4692Sfgsch       {
525b55d4692Sfgsch 	c_datasize = core.old.c_datasize;
526b55d4692Sfgsch 	c_data = (file_ptr) core.old.c_data;
527b55d4692Sfgsch 	c_vmregions = core.old.c_vmregions;
528b55d4692Sfgsch 	c_vmm = (file_ptr) core.old.c_vmm;
529b55d4692Sfgsch       }
530b305b0f1Sespie 
531b305b0f1Sespie     /* .data section from executable.  */
532b55d4692Sfgsch     if (c_datasize)
533b305b0f1Sespie       {
534b305b0f1Sespie 	if (!make_bfd_asection (abfd, ".data",
535b305b0f1Sespie 				SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
536b55d4692Sfgsch 				c_datasize,
537b55d4692Sfgsch 				(bfd_vma) CDATA_ADDR (c_datasize),
538b55d4692Sfgsch 				c_data))
539*c074d1c9Sdrahn 	  goto fail;
540b305b0f1Sespie       }
541b305b0f1Sespie 
542b305b0f1Sespie     /* .data sections from loaded objects.  */
543b55d4692Sfgsch     if (proc64)
544b55d4692Sfgsch       size = (int) ((LdInfo *) 0)->l64.ldinfo_filename;
545b55d4692Sfgsch     else
546b55d4692Sfgsch       size = (int) ((LdInfo *) 0)->l32.ldinfo_filename;
547b55d4692Sfgsch 
548b305b0f1Sespie     while (1)
549b305b0f1Sespie       {
550b55d4692Sfgsch 	if (bfd_seek (abfd, c_loader, SEEK_SET) != 0)
551*c074d1c9Sdrahn 	  goto fail;
552*c074d1c9Sdrahn 	if (bfd_bread (&ldinfo, size, abfd) != size)
553*c074d1c9Sdrahn 	  goto fail;
554b55d4692Sfgsch 
555b55d4692Sfgsch 	if (proc64)
556b305b0f1Sespie 	  {
557b55d4692Sfgsch 	    ldi_core = ldinfo.l64.ldinfo_core;
558b55d4692Sfgsch 	    ldi_datasize = ldinfo.l64.ldinfo_datasize;
559b55d4692Sfgsch 	    ldi_dataorg = (bfd_vma) ldinfo.l64.ldinfo_dataorg;
560b55d4692Sfgsch 	    ldi_next = ldinfo.l64.ldinfo_next;
561b55d4692Sfgsch 	  }
562b55d4692Sfgsch 	else
563b55d4692Sfgsch 	  {
564b55d4692Sfgsch 	    ldi_core = ldinfo.l32.ldinfo_core;
565b55d4692Sfgsch 	    ldi_datasize = ldinfo.l32.ldinfo_datasize;
566b55d4692Sfgsch 	    ldi_dataorg = (bfd_vma) (long) ldinfo.l32.ldinfo_dataorg;
567b55d4692Sfgsch 	    ldi_next = ldinfo.l32.ldinfo_next;
568b55d4692Sfgsch 	  }
569b55d4692Sfgsch 
570b55d4692Sfgsch 	if (ldi_core)
571b305b0f1Sespie 	  if (!make_bfd_asection (abfd, ".data",
572b305b0f1Sespie 				  SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
573b55d4692Sfgsch 				  ldi_datasize, ldi_dataorg, ldi_core))
574*c074d1c9Sdrahn 	    goto fail;
575b55d4692Sfgsch 
576b55d4692Sfgsch 	if (ldi_next == 0)
577b305b0f1Sespie 	  break;
578b55d4692Sfgsch 	c_loader += ldi_next;
579b305b0f1Sespie       }
580b305b0f1Sespie 
581b305b0f1Sespie     /* .vmdata sections from anonymously mmapped regions.  */
582b55d4692Sfgsch     if (c_vmregions)
583b305b0f1Sespie       {
584b55d4692Sfgsch 	bfd_size_type i;
585b305b0f1Sespie 
586b55d4692Sfgsch 	if (bfd_seek (abfd, c_vmm, SEEK_SET) != 0)
587*c074d1c9Sdrahn 	  goto fail;
588b305b0f1Sespie 
589b55d4692Sfgsch 	for (i = 0; i < c_vmregions; i++)
590b305b0f1Sespie 	  {
591b55d4692Sfgsch 	    VmInfo vminfo;
592b55d4692Sfgsch 	    bfd_size_type vminfo_size;
593b55d4692Sfgsch 	    file_ptr vminfo_offset;
594b55d4692Sfgsch 	    bfd_vma vminfo_addr;
595b305b0f1Sespie 
596b55d4692Sfgsch 	    size = CORE_NEW (core) ? sizeof (vminfo.new) : sizeof (vminfo.old);
597*c074d1c9Sdrahn 	    if (bfd_bread (&vminfo, size, abfd) != size)
598*c074d1c9Sdrahn 	      goto fail;
599b55d4692Sfgsch 
600b55d4692Sfgsch 	    if (CORE_NEW (core))
601b305b0f1Sespie 	      {
602b55d4692Sfgsch 		vminfo_addr = (bfd_vma) vminfo.new.vminfo_addr;
603b55d4692Sfgsch 		vminfo_size = vminfo.new.vminfo_size;
604b55d4692Sfgsch 		vminfo_offset = vminfo.new.vminfo_offset;
605b55d4692Sfgsch 	      }
606b55d4692Sfgsch 	    else
607b55d4692Sfgsch 	      {
608b55d4692Sfgsch 		vminfo_addr = (bfd_vma) (long) vminfo.old.vminfo_addr;
609b55d4692Sfgsch 		vminfo_size = vminfo.old.vminfo_size;
610b55d4692Sfgsch 		vminfo_offset = vminfo.old.vminfo_offset;
611b55d4692Sfgsch 	      }
612b55d4692Sfgsch 
613b55d4692Sfgsch 	    if (vminfo_offset)
614b305b0f1Sespie 	      if (!make_bfd_asection (abfd, ".vmdata",
615b305b0f1Sespie 				      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
616b55d4692Sfgsch 				      vminfo_size, vminfo_addr,
617b55d4692Sfgsch 				      vminfo_offset))
618*c074d1c9Sdrahn 		goto fail;
619b305b0f1Sespie 	  }
620b305b0f1Sespie       }
621b305b0f1Sespie   }
622b305b0f1Sespie #endif
6232159047fSniklas 
624b55d4692Sfgsch   return abfd->xvec;		/* This is garbage for now.  */
625*c074d1c9Sdrahn 
626*c074d1c9Sdrahn  fail:
627*c074d1c9Sdrahn   bfd_release (abfd, abfd->tdata.any);
628*c074d1c9Sdrahn   abfd->tdata.any = NULL;
629*c074d1c9Sdrahn   bfd_section_list_clear (abfd);
630*c074d1c9Sdrahn   return NULL;
6312159047fSniklas }
6322159047fSniklas 
633*c074d1c9Sdrahn /* Return `TRUE' if given core is from the given executable.  */
6342159047fSniklas 
635*c074d1c9Sdrahn bfd_boolean
rs6000coff_core_file_matches_executable_p(core_bfd,exec_bfd)6362159047fSniklas rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd)
6372159047fSniklas      bfd *core_bfd;
6382159047fSniklas      bfd *exec_bfd;
6392159047fSniklas {
640b55d4692Sfgsch   CoreHdr core;
641b305b0f1Sespie   bfd_size_type size;
6420c6d0228Sniklas   char *path, *s;
6430c6d0228Sniklas   size_t alloc;
6442159047fSniklas   const char *str1, *str2;
645*c074d1c9Sdrahn   bfd_boolean ret;
646b55d4692Sfgsch   file_ptr c_loader;
6472159047fSniklas 
648b55d4692Sfgsch   if (!read_hdr (core_bfd, &core))
649*c074d1c9Sdrahn     return FALSE;
6502159047fSniklas 
651b55d4692Sfgsch   if (CORE_NEW (core))
652b55d4692Sfgsch     c_loader = CNEW_LOADER (core.new);
653b55d4692Sfgsch   else
654b55d4692Sfgsch     c_loader = (file_ptr) COLD_LOADER (core.old);
6552159047fSniklas 
656b55d4692Sfgsch   if (CORE_NEW (core) && CNEW_PROC64 (core.new))
657b55d4692Sfgsch     size = (int) ((LdInfo *) 0)->l64.ldinfo_filename;
658b55d4692Sfgsch   else
659b55d4692Sfgsch     size = (int) ((LdInfo *) 0)->l32.ldinfo_filename;
660b55d4692Sfgsch 
661b55d4692Sfgsch   if (bfd_seek (core_bfd, c_loader + size, SEEK_SET) != 0)
662*c074d1c9Sdrahn     return FALSE;
6630c6d0228Sniklas 
6640c6d0228Sniklas   alloc = 100;
665*c074d1c9Sdrahn   path = bfd_malloc ((bfd_size_type) alloc);
6660c6d0228Sniklas   if (path == NULL)
667*c074d1c9Sdrahn     return FALSE;
6680c6d0228Sniklas   s = path;
6690c6d0228Sniklas 
6700c6d0228Sniklas   while (1)
6710c6d0228Sniklas     {
672*c074d1c9Sdrahn       if (bfd_bread (s, (bfd_size_type) 1, core_bfd) != 1)
6730c6d0228Sniklas 	{
6740c6d0228Sniklas 	  free (path);
675*c074d1c9Sdrahn 	  return FALSE;
6760c6d0228Sniklas 	}
6770c6d0228Sniklas       if (*s == '\0')
6780c6d0228Sniklas 	break;
6790c6d0228Sniklas       ++s;
6800c6d0228Sniklas       if (s == path + alloc)
6810c6d0228Sniklas 	{
6820c6d0228Sniklas 	  char *n;
6830c6d0228Sniklas 
6840c6d0228Sniklas 	  alloc *= 2;
685*c074d1c9Sdrahn 	  n = bfd_realloc (path, (bfd_size_type) alloc);
6860c6d0228Sniklas 	  if (n == NULL)
6870c6d0228Sniklas 	    {
6880c6d0228Sniklas 	      free (path);
689*c074d1c9Sdrahn 	      return FALSE;
6900c6d0228Sniklas 	    }
6910c6d0228Sniklas 	  s = n + (path - s);
6920c6d0228Sniklas 	  path = n;
6930c6d0228Sniklas 	}
6940c6d0228Sniklas     }
6950c6d0228Sniklas 
6960c6d0228Sniklas   str1 = strrchr (path, '/');
6972159047fSniklas   str2 = strrchr (exec_bfd->filename, '/');
6982159047fSniklas 
6992159047fSniklas   /* step over character '/' */
7000c6d0228Sniklas   str1 = str1 != NULL ? str1 + 1 : path;
7010c6d0228Sniklas   str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
7022159047fSniklas 
7030c6d0228Sniklas   if (strcmp (str1, str2) == 0)
704*c074d1c9Sdrahn     ret = TRUE;
7050c6d0228Sniklas   else
706*c074d1c9Sdrahn     ret = FALSE;
7070c6d0228Sniklas 
7080c6d0228Sniklas   free (path);
7090c6d0228Sniklas 
7100c6d0228Sniklas   return ret;
7112159047fSniklas }
7122159047fSniklas 
7132159047fSniklas char *
rs6000coff_core_file_failing_command(abfd)7142159047fSniklas rs6000coff_core_file_failing_command (abfd)
7152159047fSniklas      bfd *abfd;
7162159047fSniklas {
717b55d4692Sfgsch   CoreHdr *core = core_hdr (abfd);
718b55d4692Sfgsch   char *com = CORE_NEW (*core) ?
719b55d4692Sfgsch     CNEW_COMM (core->new) : COLD_COMM (core->old);
720b55d4692Sfgsch 
7212159047fSniklas   if (*com)
7222159047fSniklas     return com;
7232159047fSniklas   else
7242159047fSniklas     return 0;
7252159047fSniklas }
7262159047fSniklas 
7272159047fSniklas int
rs6000coff_core_file_failing_signal(abfd)7282159047fSniklas rs6000coff_core_file_failing_signal (abfd)
7292159047fSniklas      bfd *abfd;
7302159047fSniklas {
731b55d4692Sfgsch   CoreHdr *core = core_hdr (abfd);
732b55d4692Sfgsch   return CORE_NEW (*core) ? core->new.c_signo : core->old.c_signo;
7332159047fSniklas }
7342159047fSniklas 
7352159047fSniklas #endif /* AIX_CORE */
736