xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/rs6000-core.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* IBM RS/6000 "XCOFF" back-end for BFD.
2*e992f068Schristos    Copyright (C) 1990-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Written by Metin G. Ozisik, Mimi Phuong-Thao Vo, and John Gilmore.
475fd0b74Schristos    Archive support from Damon A. Permezel.
575fd0b74Schristos    Contributed by IBM Corporation and Cygnus Support.
675fd0b74Schristos 
775fd0b74Schristos    This file is part of BFD, the Binary File Descriptor library.
875fd0b74Schristos 
975fd0b74Schristos    This program is free software; you can redistribute it and/or modify
1075fd0b74Schristos    it under the terms of the GNU General Public License as published by
1175fd0b74Schristos    the Free Software Foundation; either version 3 of the License, or
1275fd0b74Schristos    (at your option) any later version.
1375fd0b74Schristos 
1475fd0b74Schristos    This program is distributed in the hope that it will be useful,
1575fd0b74Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1675fd0b74Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1775fd0b74Schristos    GNU General Public License for more details.
1875fd0b74Schristos 
1975fd0b74Schristos    You should have received a copy of the GNU General Public License
2075fd0b74Schristos    along with this program; if not, write to the Free Software
2175fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2275fd0b74Schristos    MA 02110-1301, USA.  */
2375fd0b74Schristos 
2475fd0b74Schristos 
2575fd0b74Schristos /* This port currently only handles reading object files, except when
2675fd0b74Schristos    compiled on an RS/6000 host.  -- no archive support, no core files.
2775fd0b74Schristos    In all cases, it does not support writing.
2875fd0b74Schristos 
2975fd0b74Schristos    This is in a separate file from coff-rs6000.c, because it includes
3075fd0b74Schristos    system include files that conflict with coff/rs6000.h.  */
3175fd0b74Schristos 
3275fd0b74Schristos /* Internalcoff.h and coffcode.h modify themselves based on this flag.  */
3375fd0b74Schristos #define RS6000COFF_C 1
3475fd0b74Schristos 
3575fd0b74Schristos /* The AIX 4.1 kernel is obviously compiled with -D_LONG_LONG, so
3675fd0b74Schristos    we have to define _LONG_LONG for older versions of gcc to get the
3775fd0b74Schristos    proper alignments in the user structure.  */
3875fd0b74Schristos #if defined(_AIX41) && !defined(_LONG_LONG)
3975fd0b74Schristos #define _LONG_LONG
4075fd0b74Schristos #endif
4175fd0b74Schristos 
4275fd0b74Schristos #include "sysdep.h"
4375fd0b74Schristos #include "bfd.h"
4475fd0b74Schristos #include "libbfd.h"
4575fd0b74Schristos 
4675fd0b74Schristos #ifdef AIX_CORE
4775fd0b74Schristos 
4875fd0b74Schristos /* AOUTHDR is defined by the above.  We need another defn of it, from the
4975fd0b74Schristos    system include files.  Punt the old one and get us a new name for the
5075fd0b74Schristos    typedef in the system include files.  */
5175fd0b74Schristos #ifdef AOUTHDR
5275fd0b74Schristos #undef AOUTHDR
5375fd0b74Schristos #endif
5475fd0b74Schristos #define	AOUTHDR	second_AOUTHDR
5575fd0b74Schristos 
5675fd0b74Schristos #undef	SCNHDR
5775fd0b74Schristos 
5875fd0b74Schristos /* Support for core file stuff.  */
5975fd0b74Schristos 
6075fd0b74Schristos #include <sys/user.h>
6175fd0b74Schristos #define __LDINFO_PTRACE32__	/* for __ld_info32 */
6275fd0b74Schristos #define __LDINFO_PTRACE64__	/* for __ld_info64 */
6375fd0b74Schristos #include <sys/ldr.h>
6475fd0b74Schristos #include <sys/core.h>
6575fd0b74Schristos #include <sys/systemcfg.h>
6675fd0b74Schristos 
6775fd0b74Schristos /* Borrowed from <sys/inttypes.h> on recent AIX versions.  */
6875fd0b74Schristos typedef unsigned long ptr_to_uint;
6975fd0b74Schristos 
7075fd0b74Schristos #define	core_hdr(bfd)		((CoreHdr *) bfd->tdata.any)
7175fd0b74Schristos 
7275fd0b74Schristos /* AIX 4.1 changed the names and locations of a few items in the core file.
7375fd0b74Schristos    AIX 4.3 defined an entirely new structure, core_dumpx, but kept support for
7475fd0b74Schristos    the previous 4.1 structure, core_dump.
7575fd0b74Schristos 
7675fd0b74Schristos    AIX_CORE_DUMPX_CORE is defined (by configure) on AIX 4.3+, and
7775fd0b74Schristos    CORE_VERSION_1 is defined (by AIX core.h) as 2 on AIX 4.3+ and as 1 on AIX
7875fd0b74Schristos    4.1 and 4.2.  AIX pre-4.1 (aka 3.x) either doesn't define CORE_VERSION_1
7975fd0b74Schristos    or else defines it as 0.  */
8075fd0b74Schristos 
8175fd0b74Schristos #if defined(CORE_VERSION_1) && !CORE_VERSION_1
8275fd0b74Schristos # undef CORE_VERSION_1
8375fd0b74Schristos #endif
8475fd0b74Schristos 
8575fd0b74Schristos /* The following union and macros allow this module to compile on all AIX
8675fd0b74Schristos    versions and to handle both core_dumpx and core_dump on 4.3+.  CNEW_*()
8775fd0b74Schristos    and COLD_*() macros respectively retrieve core_dumpx and core_dump
8875fd0b74Schristos    values.  */
8975fd0b74Schristos 
9075fd0b74Schristos /* Union of 32-bit and 64-bit versions of ld_info.  */
9175fd0b74Schristos 
9275fd0b74Schristos typedef union
9375fd0b74Schristos {
9475fd0b74Schristos #if defined (__ld_info32) || defined (__ld_info64)
9575fd0b74Schristos   struct __ld_info32 l32;
9675fd0b74Schristos   struct __ld_info64 l64;
9775fd0b74Schristos #else
9875fd0b74Schristos   struct ld_info l32;
9975fd0b74Schristos   struct ld_info l64;
10075fd0b74Schristos #endif
10175fd0b74Schristos } LdInfo;
10275fd0b74Schristos 
10375fd0b74Schristos /* Union of old and new core dump structures.  */
10475fd0b74Schristos 
10575fd0b74Schristos typedef union
10675fd0b74Schristos {
10775fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
10875fd0b74Schristos   struct core_dumpx new_dump;	/* New AIX 4.3+ core dump.  */
10975fd0b74Schristos #else
11075fd0b74Schristos   struct core_dump new_dump;	/* For simpler coding.  */
11175fd0b74Schristos #endif
11275fd0b74Schristos #ifndef BFD64			/* Use old only if gdb is 32-bit.  */
11375fd0b74Schristos   struct core_dump old;		/* Old AIX 4.2- core dump, still used on
11475fd0b74Schristos 				   4.3+ with appropriate SMIT config.  */
11575fd0b74Schristos #endif
11675fd0b74Schristos } CoreHdr;
11775fd0b74Schristos 
11875fd0b74Schristos /* Union of old and new vm_info structures.  */
11975fd0b74Schristos 
12075fd0b74Schristos #ifdef CORE_VERSION_1
12175fd0b74Schristos typedef union
12275fd0b74Schristos {
12375fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
12475fd0b74Schristos   struct vm_infox new_dump;
12575fd0b74Schristos #else
12675fd0b74Schristos   struct vm_info new_dump;
12775fd0b74Schristos #endif
12875fd0b74Schristos #ifndef BFD64
12975fd0b74Schristos   struct vm_info old;
13075fd0b74Schristos #endif
13175fd0b74Schristos } VmInfo;
13275fd0b74Schristos #endif
13375fd0b74Schristos 
13475fd0b74Schristos /* Return whether CoreHdr C is in new or old format.  */
13575fd0b74Schristos 
13675fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
13775fd0b74Schristos # ifndef BFD64
13875fd0b74Schristos #  define CORE_NEW(c)	(!(c).old.c_entries)
13975fd0b74Schristos # else
140ede78133Schristos #  define CORE_NEW(c)	1
14175fd0b74Schristos # endif
14275fd0b74Schristos #else
14375fd0b74Schristos # define CORE_NEW(c)	0
14475fd0b74Schristos #endif
14575fd0b74Schristos 
14675fd0b74Schristos /* Return whether CoreHdr C usese core_dumpxx structure.
14775fd0b74Schristos 
14875fd0b74Schristos    FIXME: the core file format version number used here definitely indicates
14975fd0b74Schristos    that struct core_dumpxx should be used to represent the core file header,
15075fd0b74Schristos    but that may not be the only such format version number.  */
15175fd0b74Schristos 
15275fd0b74Schristos #ifdef AIX_5_CORE
15375fd0b74Schristos # define CORE_DUMPXX_VERSION	267312562
15475fd0b74Schristos # define CNEW_IS_CORE_DUMPXX(c) ((c).new_dump.c_version == CORE_DUMPXX_VERSION)
15575fd0b74Schristos #else
15675fd0b74Schristos # define CNEW_IS_CORE_DUMPXX(c) 0
15775fd0b74Schristos #endif
15875fd0b74Schristos 
15975fd0b74Schristos /* Return the c_stackorg field from struct core_dumpx C.  */
16075fd0b74Schristos 
16175fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
16275fd0b74Schristos # define CNEW_STACKORG(c)	(c).c_stackorg
16375fd0b74Schristos #else
16475fd0b74Schristos # define CNEW_STACKORG(c)	0
16575fd0b74Schristos #endif
16675fd0b74Schristos 
16775fd0b74Schristos /* Return the offset to the loader region from struct core_dump C.  */
16875fd0b74Schristos 
16975fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
17075fd0b74Schristos # define CNEW_LOADER(c)	(c).c_loader
17175fd0b74Schristos #else
17275fd0b74Schristos # define CNEW_LOADER(c)	0
17375fd0b74Schristos #endif
17475fd0b74Schristos 
17575fd0b74Schristos /* Return the offset to the loader region from struct core_dump C.  */
17675fd0b74Schristos 
17775fd0b74Schristos #define COLD_LOADER(c)	(c).c_tab
17875fd0b74Schristos 
17975fd0b74Schristos /* Return the c_lsize field from struct core_dumpx C.  */
18075fd0b74Schristos 
18175fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
18275fd0b74Schristos # define CNEW_LSIZE(c)	(c).c_lsize
18375fd0b74Schristos #else
18475fd0b74Schristos # define CNEW_LSIZE(c)	0
18575fd0b74Schristos #endif
18675fd0b74Schristos 
18775fd0b74Schristos /* Return the c_dataorg field from struct core_dumpx C.  */
18875fd0b74Schristos 
18975fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
19075fd0b74Schristos # define CNEW_DATAORG(c)	(c).c_dataorg
19175fd0b74Schristos #else
19275fd0b74Schristos # define CNEW_DATAORG(c)	0
19375fd0b74Schristos #endif
19475fd0b74Schristos 
19575fd0b74Schristos /* Return the c_datasize field from struct core_dumpx C.  */
19675fd0b74Schristos 
19775fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
19875fd0b74Schristos # define CNEW_DATASIZE(c)	(c).c_datasize
19975fd0b74Schristos #else
20075fd0b74Schristos # define CNEW_DATASIZE(c)	0
20175fd0b74Schristos #endif
20275fd0b74Schristos 
20375fd0b74Schristos /* Return the c_impl field from struct core_dumpx C.  */
20475fd0b74Schristos 
20575fd0b74Schristos #if defined (HAVE_ST_C_IMPL) || defined (AIX_5_CORE)
20675fd0b74Schristos # define CNEW_IMPL(c)	(c).c_impl
20775fd0b74Schristos #else
20875fd0b74Schristos # define CNEW_IMPL(c)	0
20975fd0b74Schristos #endif
21075fd0b74Schristos 
21175fd0b74Schristos /* Return the command string from struct core_dumpx C.  */
21275fd0b74Schristos 
21375fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
21475fd0b74Schristos # define CNEW_COMM(c)	(c).c_u.U_proc.pi_comm
21575fd0b74Schristos #else
21675fd0b74Schristos # define CNEW_COMM(c)	0
21775fd0b74Schristos #endif
21875fd0b74Schristos 
21975fd0b74Schristos /* Return the command string from struct core_dump C.  */
22075fd0b74Schristos 
22175fd0b74Schristos #ifdef CORE_VERSION_1
22275fd0b74Schristos # define COLD_COMM(c)	(c).c_u.U_comm
22375fd0b74Schristos #else
22475fd0b74Schristos # define COLD_COMM(c)	(c).c_u.u_comm
22575fd0b74Schristos #endif
22675fd0b74Schristos 
22775fd0b74Schristos /* Return the struct __context64 pointer from struct core_dumpx C.  */
22875fd0b74Schristos 
22975fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
23075fd0b74Schristos # define CNEW_CONTEXT64(c)	(c).c_flt.hctx.r64
23175fd0b74Schristos #else
23275fd0b74Schristos # define CNEW_CONTEXT64(c)	c
23375fd0b74Schristos #endif
23475fd0b74Schristos 
23575fd0b74Schristos /* Return the struct mstsave pointer from struct core_dumpx C.  */
23675fd0b74Schristos 
23775fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
23875fd0b74Schristos # define CNEW_MSTSAVE(c)	(c).c_flt.hctx.r32
23975fd0b74Schristos #else
24075fd0b74Schristos # define CNEW_MSTSAVE(c)	c
24175fd0b74Schristos #endif
24275fd0b74Schristos 
24375fd0b74Schristos /* Return the struct mstsave pointer from struct core_dump C.  */
24475fd0b74Schristos 
24575fd0b74Schristos #ifdef CORE_VERSION_1
24675fd0b74Schristos # define COLD_MSTSAVE(c)	(c).c_mst
24775fd0b74Schristos #else
24875fd0b74Schristos # define COLD_MSTSAVE(c)	(c).c_u.u_save
24975fd0b74Schristos #endif
25075fd0b74Schristos 
25175fd0b74Schristos /* Return whether struct core_dumpx is from a 64-bit process.  */
25275fd0b74Schristos 
25375fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
25475fd0b74Schristos # define CNEW_PROC64(c)		IS_PROC64(&(c).c_u.U_proc)
25575fd0b74Schristos #else
25675fd0b74Schristos # define CNEW_PROC64(c)		0
25775fd0b74Schristos #endif
25875fd0b74Schristos 
25975fd0b74Schristos /* Magic end-of-stack addresses for old core dumps.  This is _very_ fragile,
26075fd0b74Schristos    but I don't see any easy way to get that info right now.  */
26175fd0b74Schristos 
26275fd0b74Schristos #ifdef CORE_VERSION_1
26375fd0b74Schristos # define COLD_STACKEND	0x2ff23000
26475fd0b74Schristos #else
26575fd0b74Schristos # define COLD_STACKEND	0x2ff80000
26675fd0b74Schristos #endif
26775fd0b74Schristos 
26875fd0b74Schristos /* Size of the leading portion that old and new core dump structures have in
26975fd0b74Schristos    common.  */
27075fd0b74Schristos #ifdef AIX_CORE_DUMPX_CORE
27175fd0b74Schristos #define CORE_COMMONSZ  ((long) &((struct core_dumpx *) 0)->c_entries \
27275fd0b74Schristos 			+ sizeof (((struct core_dumpx *) 0)->c_entries))
27375fd0b74Schristos #else
27475fd0b74Schristos #define CORE_COMMONSZ  ((int) &((struct core_dump *) 0)->c_entries \
275012573ebSchristos 			+ sizeof (((struct core_dump *) 0)->c_entries))
27675fd0b74Schristos #endif
27775fd0b74Schristos /* Define prototypes for certain functions, to avoid a compiler warning
27875fd0b74Schristos    saying that they are missing.  */
27975fd0b74Schristos 
280*e992f068Schristos bfd_cleanup rs6000coff_core_p (bfd *abfd);
281*e992f068Schristos bool rs6000coff_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd);
28275fd0b74Schristos char * rs6000coff_core_file_failing_command (bfd *abfd);
28375fd0b74Schristos int rs6000coff_core_file_failing_signal (bfd *abfd);
28475fd0b74Schristos 
28575fd0b74Schristos /* Try to read into CORE the header from the core file associated with ABFD.
28675fd0b74Schristos    Return success.  */
28775fd0b74Schristos 
288*e992f068Schristos static bool
read_hdr(bfd * abfd,CoreHdr * core)28975fd0b74Schristos read_hdr (bfd *abfd, CoreHdr *core)
29075fd0b74Schristos {
29175fd0b74Schristos   bfd_size_type size;
29275fd0b74Schristos 
29375fd0b74Schristos   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
294*e992f068Schristos     return false;
29575fd0b74Schristos 
29675fd0b74Schristos   /* Read the leading portion that old and new core dump structures have in
29775fd0b74Schristos      common.  */
29875fd0b74Schristos   size = CORE_COMMONSZ;
29975fd0b74Schristos   if (bfd_bread (core, size, abfd) != size)
300*e992f068Schristos     return false;
30175fd0b74Schristos 
30275fd0b74Schristos   /* Read the trailing portion of the structure.  */
30375fd0b74Schristos   if (CORE_NEW (*core))
30475fd0b74Schristos     size = sizeof (core->new_dump);
30575fd0b74Schristos #ifndef BFD64
30675fd0b74Schristos   else
30775fd0b74Schristos     size = sizeof (core->old);
30875fd0b74Schristos #endif
30975fd0b74Schristos   size -= CORE_COMMONSZ;
31075fd0b74Schristos   return bfd_bread ((char *) core + CORE_COMMONSZ, size, abfd) == size;
31175fd0b74Schristos }
31275fd0b74Schristos 
31375fd0b74Schristos static asection *
make_bfd_asection(bfd * abfd,const char * name,flagword flags,bfd_size_type size,bfd_vma vma,file_ptr filepos)31475fd0b74Schristos make_bfd_asection (bfd *abfd, const char *name, flagword flags,
31575fd0b74Schristos 		   bfd_size_type size, bfd_vma vma, file_ptr filepos)
31675fd0b74Schristos {
31775fd0b74Schristos   asection *asect;
31875fd0b74Schristos 
31975fd0b74Schristos   asect = bfd_make_section_anyway_with_flags (abfd, name, flags);
32075fd0b74Schristos   if (!asect)
32175fd0b74Schristos     return NULL;
32275fd0b74Schristos 
32375fd0b74Schristos   asect->size = size;
32475fd0b74Schristos   asect->vma = vma;
32575fd0b74Schristos   asect->filepos = filepos;
32675fd0b74Schristos   asect->alignment_power = 8;
32775fd0b74Schristos 
32875fd0b74Schristos   return asect;
32975fd0b74Schristos }
33075fd0b74Schristos 
33175fd0b74Schristos /* Decide if a given bfd represents a `core' file or not. There really is no
33275fd0b74Schristos    magic number or anything like, in rs6000coff.  */
33375fd0b74Schristos 
334*e992f068Schristos bfd_cleanup
rs6000coff_core_p(bfd * abfd)33575fd0b74Schristos rs6000coff_core_p (bfd *abfd)
33675fd0b74Schristos {
33775fd0b74Schristos   CoreHdr core;
33875fd0b74Schristos   struct stat statbuf;
33975fd0b74Schristos   bfd_size_type size;
34075fd0b74Schristos   char *tmpptr;
34175fd0b74Schristos 
34275fd0b74Schristos   /* Values from new and old core structures.  */
34375fd0b74Schristos   int c_flag;
34475fd0b74Schristos   file_ptr c_stack, c_regoff, c_loader;
34575fd0b74Schristos   bfd_size_type c_size, c_regsize, c_lsize;
34675fd0b74Schristos   bfd_vma c_stackend;
34775fd0b74Schristos   void *c_regptr;
34875fd0b74Schristos   int proc64;
34975fd0b74Schristos 
35075fd0b74Schristos   if (!read_hdr (abfd, &core))
35175fd0b74Schristos     {
35275fd0b74Schristos       if (bfd_get_error () != bfd_error_system_call)
35375fd0b74Schristos 	bfd_set_error (bfd_error_wrong_format);
35475fd0b74Schristos       return NULL;
35575fd0b74Schristos     }
35675fd0b74Schristos 
35775fd0b74Schristos   /* This isn't the right handler for 64-bit core files on AIX 5.x.  */
35875fd0b74Schristos   if (CORE_NEW (core) && CNEW_IS_CORE_DUMPXX (core))
35975fd0b74Schristos     {
36075fd0b74Schristos       bfd_set_error (bfd_error_wrong_format);
36175fd0b74Schristos       return NULL;
36275fd0b74Schristos     }
36375fd0b74Schristos 
36475fd0b74Schristos   /* Copy fields from new or old core structure.  */
36575fd0b74Schristos   if (CORE_NEW (core))
36675fd0b74Schristos     {
36775fd0b74Schristos       c_flag = core.new_dump.c_flag;
36875fd0b74Schristos       c_stack = (file_ptr) core.new_dump.c_stack;
36975fd0b74Schristos       c_size = core.new_dump.c_size;
37075fd0b74Schristos       c_stackend = CNEW_STACKORG (core.new_dump) + c_size;
37175fd0b74Schristos       c_lsize = CNEW_LSIZE (core.new_dump);
37275fd0b74Schristos       c_loader = CNEW_LOADER (core.new_dump);
37375fd0b74Schristos #ifndef BFD64
37475fd0b74Schristos       proc64 = CNEW_PROC64 (core.new_dump);
37575fd0b74Schristos     }
37675fd0b74Schristos   else
37775fd0b74Schristos     {
37875fd0b74Schristos       c_flag = core.old.c_flag;
37975fd0b74Schristos       c_stack = (file_ptr) (ptr_to_uint) core.old.c_stack;
38075fd0b74Schristos       c_size = core.old.c_size;
38175fd0b74Schristos       c_stackend = COLD_STACKEND;
38275fd0b74Schristos       c_lsize = 0x7ffffff;
38375fd0b74Schristos       c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old);
38475fd0b74Schristos #endif
38575fd0b74Schristos       proc64 = 0;
38675fd0b74Schristos     }
38775fd0b74Schristos 
38875fd0b74Schristos   if (proc64)
38975fd0b74Schristos     {
39075fd0b74Schristos       c_regsize = sizeof (CNEW_CONTEXT64 (core.new_dump));
39175fd0b74Schristos       c_regptr = &CNEW_CONTEXT64 (core.new_dump);
39275fd0b74Schristos     }
39375fd0b74Schristos   else if (CORE_NEW (core))
39475fd0b74Schristos     {
39575fd0b74Schristos       c_regsize = sizeof (CNEW_MSTSAVE (core.new_dump));
39675fd0b74Schristos       c_regptr = &CNEW_MSTSAVE (core.new_dump);
39775fd0b74Schristos     }
39875fd0b74Schristos #ifndef BFD64
39975fd0b74Schristos   else
40075fd0b74Schristos     {
40175fd0b74Schristos       c_regsize = sizeof (COLD_MSTSAVE (core.old));
40275fd0b74Schristos       c_regptr = &COLD_MSTSAVE (core.old);
40375fd0b74Schristos     }
40475fd0b74Schristos #endif
40575fd0b74Schristos   c_regoff = (char *) c_regptr - (char *) &core;
40675fd0b74Schristos 
40775fd0b74Schristos   if (bfd_stat (abfd, &statbuf) < 0)
40875fd0b74Schristos     {
40975fd0b74Schristos       bfd_set_error (bfd_error_system_call);
41075fd0b74Schristos       return NULL;
41175fd0b74Schristos     }
41275fd0b74Schristos 
41375fd0b74Schristos   /* If the core file ulimit is too small, the system will first
41475fd0b74Schristos      omit the data segment, then omit the stack, then decline to
41575fd0b74Schristos      dump core altogether (as far as I know UBLOCK_VALID and LE_VALID
41675fd0b74Schristos      are always set) (this is based on experimentation on AIX 3.2).
41775fd0b74Schristos      Now, the thing is that GDB users will be surprised
41875fd0b74Schristos      if segments just silently don't appear (well, maybe they would
41975fd0b74Schristos      think to check "info files", I don't know).
42075fd0b74Schristos 
42175fd0b74Schristos      For the data segment, we have no choice but to keep going if it's
42275fd0b74Schristos      not there, since the default behavior is not to dump it (regardless
42375fd0b74Schristos      of the ulimit, it's based on SA_FULLDUMP).  But for the stack segment,
42475fd0b74Schristos      if it's not there, we refuse to have anything to do with this core
42575fd0b74Schristos      file.  The usefulness of a core dump without a stack segment is pretty
42675fd0b74Schristos      limited anyway.  */
42775fd0b74Schristos 
42875fd0b74Schristos   if (!(c_flag & UBLOCK_VALID)
42975fd0b74Schristos       || !(c_flag & LE_VALID))
43075fd0b74Schristos     {
43175fd0b74Schristos       bfd_set_error (bfd_error_wrong_format);
43275fd0b74Schristos       return NULL;
43375fd0b74Schristos     }
43475fd0b74Schristos 
43575fd0b74Schristos   if (!(c_flag & USTACK_VALID))
43675fd0b74Schristos     {
43775fd0b74Schristos       bfd_set_error (bfd_error_file_truncated);
43875fd0b74Schristos       return NULL;
43975fd0b74Schristos     }
44075fd0b74Schristos 
44175fd0b74Schristos   /* Don't check the core file size for a full core, AIX 4.1 includes
44275fd0b74Schristos      additional shared library sections in a full core.  */
44375fd0b74Schristos   if (!(c_flag & (FULL_CORE | CORE_TRUNC)))
44475fd0b74Schristos     {
44575fd0b74Schristos       /* If the size is wrong, it means we're misinterpreting something.  */
44675fd0b74Schristos       if (c_stack + (file_ptr) c_size != statbuf.st_size)
44775fd0b74Schristos 	{
44875fd0b74Schristos 	  bfd_set_error (bfd_error_wrong_format);
44975fd0b74Schristos 	  return NULL;
45075fd0b74Schristos 	}
45175fd0b74Schristos     }
45275fd0b74Schristos 
45375fd0b74Schristos   /* Sanity check on the c_tab field.  */
45475fd0b74Schristos   if (!CORE_NEW (core)
45575fd0b74Schristos       && (
45675fd0b74Schristos #ifndef BFD64
45775fd0b74Schristos 	  c_loader < (file_ptr) sizeof core.old
45875fd0b74Schristos #else
45975fd0b74Schristos 	  c_loader < (file_ptr) sizeof core.new_dump
46075fd0b74Schristos #endif
46175fd0b74Schristos 	  || c_loader >= statbuf.st_size
46275fd0b74Schristos 	  || c_loader >= c_stack))
46375fd0b74Schristos     {
46475fd0b74Schristos       bfd_set_error (bfd_error_wrong_format);
46575fd0b74Schristos       return NULL;
46675fd0b74Schristos     }
46775fd0b74Schristos 
46875fd0b74Schristos   /* Issue warning if the core file was truncated during writing.  */
46975fd0b74Schristos   if (c_flag & CORE_TRUNC)
470ede78133Schristos     _bfd_error_handler (_("%pB: warning core file truncated"), abfd);
47175fd0b74Schristos 
47275fd0b74Schristos   /* Allocate core file header.  */
47375fd0b74Schristos #ifndef BFD64
47475fd0b74Schristos   size = CORE_NEW (core) ? sizeof (core.new_dump) : sizeof (core.old);
47575fd0b74Schristos #else
47675fd0b74Schristos   size =  sizeof (core.new_dump);
47775fd0b74Schristos #endif
47875fd0b74Schristos   tmpptr = (char *) bfd_zalloc (abfd, (bfd_size_type) size);
47975fd0b74Schristos   if (!tmpptr)
48075fd0b74Schristos     return NULL;
48175fd0b74Schristos 
48275fd0b74Schristos   /* Copy core file header.  */
48375fd0b74Schristos   memcpy (tmpptr, &core, size);
48475fd0b74Schristos   set_tdata (abfd, tmpptr);
48575fd0b74Schristos 
48675fd0b74Schristos   /* Set architecture.  */
48775fd0b74Schristos   if (CORE_NEW (core))
48875fd0b74Schristos     {
48975fd0b74Schristos       enum bfd_architecture arch;
49075fd0b74Schristos       unsigned long mach;
49175fd0b74Schristos 
49275fd0b74Schristos       switch (CNEW_IMPL (core.new_dump))
49375fd0b74Schristos 	{
49475fd0b74Schristos 	case POWER_RS1:
49575fd0b74Schristos 	case POWER_RSC:
49675fd0b74Schristos 	case POWER_RS2:
49775fd0b74Schristos 	  arch = bfd_arch_rs6000;
49875fd0b74Schristos 	  mach = bfd_mach_rs6k;
49975fd0b74Schristos 	  break;
50075fd0b74Schristos 	default:
50175fd0b74Schristos 	  arch = bfd_arch_powerpc;
50275fd0b74Schristos 	  mach = bfd_mach_ppc;
50375fd0b74Schristos 	  break;
50475fd0b74Schristos 	}
50575fd0b74Schristos       bfd_default_set_arch_mach (abfd, arch, mach);
50675fd0b74Schristos     }
50775fd0b74Schristos 
50875fd0b74Schristos   /* .stack section.  */
50975fd0b74Schristos   if (!make_bfd_asection (abfd, ".stack",
51075fd0b74Schristos 			  SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
51175fd0b74Schristos 			  c_size, c_stackend - c_size, c_stack))
51275fd0b74Schristos     goto fail;
51375fd0b74Schristos 
51475fd0b74Schristos   /* .reg section for all registers.  */
51575fd0b74Schristos   if (!make_bfd_asection (abfd, ".reg",
51675fd0b74Schristos 			  SEC_HAS_CONTENTS,
51775fd0b74Schristos 			  c_regsize, (bfd_vma) 0, c_regoff))
51875fd0b74Schristos     goto fail;
51975fd0b74Schristos 
52075fd0b74Schristos   /* .ldinfo section.
52175fd0b74Schristos      To actually find out how long this section is in this particular
52275fd0b74Schristos      core dump would require going down the whole list of struct ld_info's.
52375fd0b74Schristos      See if we can just fake it.  */
52475fd0b74Schristos   if (!make_bfd_asection (abfd, ".ldinfo",
52575fd0b74Schristos 			  SEC_HAS_CONTENTS,
52675fd0b74Schristos 			  c_lsize, (bfd_vma) 0, c_loader))
52775fd0b74Schristos     goto fail;
52875fd0b74Schristos 
52975fd0b74Schristos #ifndef CORE_VERSION_1
53075fd0b74Schristos   /* .data section if present.
53175fd0b74Schristos      AIX 3 dumps the complete data section and sets FULL_CORE if the
53275fd0b74Schristos      ulimit is large enough, otherwise the data section is omitted.
53375fd0b74Schristos      AIX 4 sets FULL_CORE even if the core file is truncated, we have
53475fd0b74Schristos      to examine core.c_datasize below to find out the actual size of
53575fd0b74Schristos      the .data section.  */
53675fd0b74Schristos   if (c_flag & FULL_CORE)
53775fd0b74Schristos     {
53875fd0b74Schristos       if (!make_bfd_asection (abfd, ".data",
53975fd0b74Schristos 			      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
54075fd0b74Schristos 			      (bfd_size_type) core.old.c_u.u_dsize,
54175fd0b74Schristos 			      (bfd_vma)
54275fd0b74Schristos 				CDATA_ADDR (core.old.c_u.u_dsize),
54375fd0b74Schristos 			      c_stack + c_size))
54475fd0b74Schristos 	goto fail;
54575fd0b74Schristos     }
54675fd0b74Schristos #endif
54775fd0b74Schristos 
54875fd0b74Schristos #ifdef CORE_VERSION_1
54975fd0b74Schristos   /* AIX 4 adds data sections from loaded objects to the core file,
55075fd0b74Schristos      which can be found by examining ldinfo, and anonymously mmapped
55175fd0b74Schristos      regions.  */
55275fd0b74Schristos   {
55375fd0b74Schristos     LdInfo ldinfo;
55475fd0b74Schristos     bfd_size_type ldi_datasize;
55575fd0b74Schristos     file_ptr ldi_core;
55675fd0b74Schristos     uint ldi_next;
55775fd0b74Schristos     bfd_vma ldi_dataorg;
55875fd0b74Schristos     bfd_vma core_dataorg;
55975fd0b74Schristos 
56075fd0b74Schristos     /* Fields from new and old core structures.  */
56175fd0b74Schristos     bfd_size_type c_datasize, c_vmregions;
56275fd0b74Schristos     file_ptr c_data, c_vmm;
56375fd0b74Schristos 
56475fd0b74Schristos     if (CORE_NEW (core))
56575fd0b74Schristos       {
56675fd0b74Schristos 	c_datasize = CNEW_DATASIZE (core.new_dump);
56775fd0b74Schristos 	c_data = (file_ptr) core.new_dump.c_data;
56875fd0b74Schristos 	c_vmregions = core.new_dump.c_vmregions;
56975fd0b74Schristos 	c_vmm = (file_ptr) core.new_dump.c_vmm;
57075fd0b74Schristos       }
57175fd0b74Schristos #ifndef BFD64
57275fd0b74Schristos     else
57375fd0b74Schristos       {
57475fd0b74Schristos 	c_datasize = core.old.c_datasize;
57575fd0b74Schristos 	c_data = (file_ptr) (ptr_to_uint) core.old.c_data;
57675fd0b74Schristos 	c_vmregions = core.old.c_vmregions;
57775fd0b74Schristos 	c_vmm = (file_ptr) (ptr_to_uint) core.old.c_vmm;
57875fd0b74Schristos       }
57975fd0b74Schristos #endif
58075fd0b74Schristos 
58175fd0b74Schristos     /* .data section from executable.  */
58275fd0b74Schristos     if (c_datasize)
58375fd0b74Schristos       {
58475fd0b74Schristos 	/* If Large Memory Model is used, then the .data segment should start from
58575fd0b74Schristos 	   BDATAORG which has been defined in the system header files. */
58675fd0b74Schristos 
58775fd0b74Schristos 	if (c_flag & CORE_BIGDATA)
58875fd0b74Schristos 	  core_dataorg = BDATAORG;
58975fd0b74Schristos 	else
59075fd0b74Schristos 	  core_dataorg = CDATA_ADDR (c_datasize);
59175fd0b74Schristos 
59275fd0b74Schristos 	if (!make_bfd_asection (abfd, ".data",
59375fd0b74Schristos 				SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
59475fd0b74Schristos 				c_datasize,
59575fd0b74Schristos 				(bfd_vma) core_dataorg,
59675fd0b74Schristos 				c_data))
59775fd0b74Schristos 	  goto fail;
59875fd0b74Schristos       }
59975fd0b74Schristos 
60075fd0b74Schristos     /* .data sections from loaded objects.  */
60175fd0b74Schristos     if (proc64)
60275fd0b74Schristos       size = (unsigned long) ((LdInfo *) 0)->l64.ldinfo_filename;
60375fd0b74Schristos     else
60475fd0b74Schristos       size = (unsigned long) ((LdInfo *) 0)->l32.ldinfo_filename;
60575fd0b74Schristos 
60675fd0b74Schristos     while (1)
60775fd0b74Schristos       {
60875fd0b74Schristos 	if (bfd_seek (abfd, c_loader, SEEK_SET) != 0)
60975fd0b74Schristos 	  goto fail;
61075fd0b74Schristos 	if (bfd_bread (&ldinfo, size, abfd) != size)
61175fd0b74Schristos 	  goto fail;
61275fd0b74Schristos 
61375fd0b74Schristos 	if (proc64)
61475fd0b74Schristos 	  {
61575fd0b74Schristos 	    ldi_core = ldinfo.l64.ldinfo_core;
61675fd0b74Schristos 	    ldi_datasize = ldinfo.l64.ldinfo_datasize;
61775fd0b74Schristos 	    ldi_dataorg = (bfd_vma) ldinfo.l64.ldinfo_dataorg;
61875fd0b74Schristos 	    ldi_next = ldinfo.l64.ldinfo_next;
61975fd0b74Schristos 	  }
62075fd0b74Schristos 	else
62175fd0b74Schristos 	  {
62275fd0b74Schristos 	    ldi_core = ldinfo.l32.ldinfo_core;
62375fd0b74Schristos 	    ldi_datasize = ldinfo.l32.ldinfo_datasize;
62475fd0b74Schristos 	    ldi_dataorg = (bfd_vma) (ptr_to_uint) ldinfo.l32.ldinfo_dataorg;
62575fd0b74Schristos 	    ldi_next = ldinfo.l32.ldinfo_next;
62675fd0b74Schristos 	  }
62775fd0b74Schristos 
62875fd0b74Schristos 	if (ldi_core)
62975fd0b74Schristos 	  if (!make_bfd_asection (abfd, ".data",
63075fd0b74Schristos 				  SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
63175fd0b74Schristos 				  ldi_datasize, ldi_dataorg, ldi_core))
63275fd0b74Schristos 	    goto fail;
63375fd0b74Schristos 
63475fd0b74Schristos 	if (ldi_next == 0)
63575fd0b74Schristos 	  break;
63675fd0b74Schristos 	c_loader += ldi_next;
63775fd0b74Schristos       }
63875fd0b74Schristos 
63975fd0b74Schristos     /* .vmdata sections from anonymously mmapped regions.  */
64075fd0b74Schristos     if (c_vmregions)
64175fd0b74Schristos       {
64275fd0b74Schristos 	bfd_size_type i;
64375fd0b74Schristos 
64475fd0b74Schristos 	if (bfd_seek (abfd, c_vmm, SEEK_SET) != 0)
64575fd0b74Schristos 	  goto fail;
64675fd0b74Schristos 
64775fd0b74Schristos 	for (i = 0; i < c_vmregions; i++)
64875fd0b74Schristos 	  {
64975fd0b74Schristos 	    VmInfo vminfo;
65075fd0b74Schristos 	    bfd_size_type vminfo_size;
65175fd0b74Schristos 	    file_ptr vminfo_offset;
65275fd0b74Schristos 	    bfd_vma vminfo_addr;
65375fd0b74Schristos 
65475fd0b74Schristos #ifndef BFD64
65575fd0b74Schristos 	    size = CORE_NEW (core) ? sizeof (vminfo.new_dump) : sizeof (vminfo.old);
65675fd0b74Schristos #else
65775fd0b74Schristos 	    size = sizeof (vminfo.new_dump);
65875fd0b74Schristos #endif
65975fd0b74Schristos 	    if (bfd_bread (&vminfo, size, abfd) != size)
66075fd0b74Schristos 	      goto fail;
66175fd0b74Schristos 
66275fd0b74Schristos 	    if (CORE_NEW (core))
66375fd0b74Schristos 	      {
66475fd0b74Schristos 		vminfo_addr = (bfd_vma) vminfo.new_dump.vminfo_addr;
66575fd0b74Schristos 		vminfo_size = vminfo.new_dump.vminfo_size;
66675fd0b74Schristos 		vminfo_offset = vminfo.new_dump.vminfo_offset;
66775fd0b74Schristos 	      }
66875fd0b74Schristos #ifndef BFD64
66975fd0b74Schristos 	    else
67075fd0b74Schristos 	      {
67175fd0b74Schristos 		vminfo_addr = (bfd_vma) (ptr_to_uint) vminfo.old.vminfo_addr;
67275fd0b74Schristos 		vminfo_size = vminfo.old.vminfo_size;
67375fd0b74Schristos 		vminfo_offset = vminfo.old.vminfo_offset;
67475fd0b74Schristos 	      }
67575fd0b74Schristos #endif
67675fd0b74Schristos 
67775fd0b74Schristos 	    if (vminfo_offset)
67875fd0b74Schristos 	      if (!make_bfd_asection (abfd, ".vmdata",
67975fd0b74Schristos 				      SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
68075fd0b74Schristos 				      vminfo_size, vminfo_addr,
68175fd0b74Schristos 				      vminfo_offset))
68275fd0b74Schristos 		goto fail;
68375fd0b74Schristos 	  }
68475fd0b74Schristos       }
68575fd0b74Schristos   }
68675fd0b74Schristos #endif
68775fd0b74Schristos 
688*e992f068Schristos   return _bfd_no_cleanup;
68975fd0b74Schristos 
69075fd0b74Schristos  fail:
69175fd0b74Schristos   bfd_release (abfd, abfd->tdata.any);
69275fd0b74Schristos   abfd->tdata.any = NULL;
69375fd0b74Schristos   bfd_section_list_clear (abfd);
69475fd0b74Schristos   return NULL;
69575fd0b74Schristos }
69675fd0b74Schristos 
69775fd0b74Schristos /* Return `TRUE' if given core is from the given executable.  */
69875fd0b74Schristos 
699*e992f068Schristos bool
rs6000coff_core_file_matches_executable_p(bfd * core_bfd,bfd * exec_bfd)70075fd0b74Schristos rs6000coff_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
70175fd0b74Schristos {
70275fd0b74Schristos   CoreHdr core;
70375fd0b74Schristos   bfd_size_type size;
70475fd0b74Schristos   char *path, *s;
70575fd0b74Schristos   size_t alloc;
70675fd0b74Schristos   const char *str1, *str2;
707*e992f068Schristos   bool ret;
70875fd0b74Schristos   file_ptr c_loader;
70975fd0b74Schristos 
71075fd0b74Schristos   if (!read_hdr (core_bfd, &core))
711*e992f068Schristos     return false;
71275fd0b74Schristos 
71375fd0b74Schristos   if (CORE_NEW (core))
71475fd0b74Schristos     c_loader = CNEW_LOADER (core.new_dump);
71575fd0b74Schristos #ifndef BFD64
71675fd0b74Schristos   else
71775fd0b74Schristos     c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old);
71875fd0b74Schristos #endif
71975fd0b74Schristos 
72075fd0b74Schristos   if (CORE_NEW (core) && CNEW_PROC64 (core.new_dump))
72175fd0b74Schristos     size = (int) ((LdInfo *) 0)->l64.ldinfo_filename;
72275fd0b74Schristos   else
72375fd0b74Schristos     size = (int) ((LdInfo *) 0)->l32.ldinfo_filename;
72475fd0b74Schristos 
72575fd0b74Schristos   if (bfd_seek (core_bfd, c_loader + size, SEEK_SET) != 0)
726*e992f068Schristos     return false;
72775fd0b74Schristos 
72875fd0b74Schristos   alloc = 100;
72975fd0b74Schristos   path = bfd_malloc ((bfd_size_type) alloc);
73075fd0b74Schristos   if (path == NULL)
731*e992f068Schristos     return false;
73275fd0b74Schristos   s = path;
73375fd0b74Schristos 
73475fd0b74Schristos   while (1)
73575fd0b74Schristos     {
73675fd0b74Schristos       if (bfd_bread (s, (bfd_size_type) 1, core_bfd) != 1)
73775fd0b74Schristos 	{
73875fd0b74Schristos 	  free (path);
739*e992f068Schristos 	  return false;
74075fd0b74Schristos 	}
74175fd0b74Schristos       if (*s == '\0')
74275fd0b74Schristos 	break;
74375fd0b74Schristos       ++s;
74475fd0b74Schristos       if (s == path + alloc)
74575fd0b74Schristos 	{
74675fd0b74Schristos 	  char *n;
74775fd0b74Schristos 
74875fd0b74Schristos 	  alloc *= 2;
74975fd0b74Schristos 	  n = bfd_realloc (path, (bfd_size_type) alloc);
75075fd0b74Schristos 	  if (n == NULL)
75175fd0b74Schristos 	    {
75275fd0b74Schristos 	      free (path);
753*e992f068Schristos 	      return false;
75475fd0b74Schristos 	    }
75575fd0b74Schristos 	  s = n + (path - s);
75675fd0b74Schristos 	  path = n;
75775fd0b74Schristos 	}
75875fd0b74Schristos     }
75975fd0b74Schristos 
76075fd0b74Schristos   str1 = strrchr (path, '/');
761*e992f068Schristos   str2 = strrchr (bfd_get_filename (exec_bfd), '/');
76275fd0b74Schristos 
76375fd0b74Schristos   /* step over character '/' */
76475fd0b74Schristos   str1 = str1 != NULL ? str1 + 1 : path;
765*e992f068Schristos   str2 = str2 != NULL ? str2 + 1 : bfd_get_filename (exec_bfd);
76675fd0b74Schristos 
76775fd0b74Schristos   if (strcmp (str1, str2) == 0)
768*e992f068Schristos     ret = true;
76975fd0b74Schristos   else
770*e992f068Schristos     ret = false;
77175fd0b74Schristos 
77275fd0b74Schristos   free (path);
77375fd0b74Schristos 
77475fd0b74Schristos   return ret;
77575fd0b74Schristos }
77675fd0b74Schristos 
77775fd0b74Schristos char *
rs6000coff_core_file_failing_command(bfd * abfd)77875fd0b74Schristos rs6000coff_core_file_failing_command (bfd *abfd)
77975fd0b74Schristos {
78075fd0b74Schristos   CoreHdr *core = core_hdr (abfd);
78175fd0b74Schristos #ifndef BFD64
78275fd0b74Schristos   char *com = CORE_NEW (*core) ?
78375fd0b74Schristos     CNEW_COMM (core->new_dump) : COLD_COMM (core->old);
78475fd0b74Schristos #else
78575fd0b74Schristos   char *com = CNEW_COMM (core->new_dump);
78675fd0b74Schristos #endif
78775fd0b74Schristos 
78875fd0b74Schristos   if (*com)
78975fd0b74Schristos     return com;
79075fd0b74Schristos   else
79175fd0b74Schristos     return 0;
79275fd0b74Schristos }
79375fd0b74Schristos 
79475fd0b74Schristos int
rs6000coff_core_file_failing_signal(bfd * abfd)79575fd0b74Schristos rs6000coff_core_file_failing_signal (bfd *abfd)
79675fd0b74Schristos {
79775fd0b74Schristos   CoreHdr *core = core_hdr (abfd);
79875fd0b74Schristos #ifndef BFD64
79975fd0b74Schristos   return CORE_NEW (*core) ? core->new_dump.c_signo : core->old.c_signo;
80075fd0b74Schristos #else
80175fd0b74Schristos   return  core->new_dump.c_signo;
80275fd0b74Schristos #endif
80375fd0b74Schristos }
80475fd0b74Schristos 
80575fd0b74Schristos #endif /* AIX_CORE */
806