1*3d8817e4Smiod /* IBM RS/6000 "XCOFF" back-end for BFD.
2*3d8817e4Smiod Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
3*3d8817e4Smiod 2001, 2002, 2004
4*3d8817e4Smiod Free Software Foundation, Inc.
5*3d8817e4Smiod FIXME: Can someone provide a transliteration of this name into ASCII?
6*3d8817e4Smiod Using the following chars caused a compiler warning on HIUX (so I replaced
7*3d8817e4Smiod them with octal escapes), and isn't useful without an understanding of what
8*3d8817e4Smiod character set it is.
9*3d8817e4Smiod Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
10*3d8817e4Smiod and John Gilmore.
11*3d8817e4Smiod Archive support from Damon A. Permezel.
12*3d8817e4Smiod Contributed by IBM Corporation and Cygnus Support.
13*3d8817e4Smiod
14*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
15*3d8817e4Smiod
16*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
17*3d8817e4Smiod it under the terms of the GNU General Public License as published by
18*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
19*3d8817e4Smiod (at your option) any later version.
20*3d8817e4Smiod
21*3d8817e4Smiod This program is distributed in the hope that it will be useful,
22*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
23*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24*3d8817e4Smiod GNU General Public License for more details.
25*3d8817e4Smiod
26*3d8817e4Smiod You should have received a copy of the GNU General Public License
27*3d8817e4Smiod along with this program; if not, write to the Free Software
28*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
29*3d8817e4Smiod
30*3d8817e4Smiod /* This port currently only handles reading object files, except when
31*3d8817e4Smiod compiled on an RS/6000 host. -- no archive support, no core files.
32*3d8817e4Smiod In all cases, it does not support writing.
33*3d8817e4Smiod
34*3d8817e4Smiod This is in a separate file from coff-rs6000.c, because it includes
35*3d8817e4Smiod system include files that conflict with coff/rs6000.h. */
36*3d8817e4Smiod
37*3d8817e4Smiod /* Internalcoff.h and coffcode.h modify themselves based on this flag. */
38*3d8817e4Smiod #define RS6000COFF_C 1
39*3d8817e4Smiod
40*3d8817e4Smiod /* The AIX 4.1 kernel is obviously compiled with -D_LONG_LONG, so
41*3d8817e4Smiod we have to define _LONG_LONG for older versions of gcc to get the
42*3d8817e4Smiod proper alignments in the user structure. */
43*3d8817e4Smiod #if defined(_AIX41) && !defined(_LONG_LONG)
44*3d8817e4Smiod #define _LONG_LONG
45*3d8817e4Smiod #endif
46*3d8817e4Smiod
47*3d8817e4Smiod #include "bfd.h"
48*3d8817e4Smiod #include "sysdep.h"
49*3d8817e4Smiod #include "libbfd.h"
50*3d8817e4Smiod
51*3d8817e4Smiod #ifdef AIX_CORE
52*3d8817e4Smiod
53*3d8817e4Smiod /* AOUTHDR is defined by the above. We need another defn of it, from the
54*3d8817e4Smiod system include files. Punt the old one and get us a new name for the
55*3d8817e4Smiod typedef in the system include files. */
56*3d8817e4Smiod #ifdef AOUTHDR
57*3d8817e4Smiod #undef AOUTHDR
58*3d8817e4Smiod #endif
59*3d8817e4Smiod #define AOUTHDR second_AOUTHDR
60*3d8817e4Smiod
61*3d8817e4Smiod #undef SCNHDR
62*3d8817e4Smiod
63*3d8817e4Smiod /* ------------------------------------------------------------------------ */
64*3d8817e4Smiod /* Support for core file stuff.. */
65*3d8817e4Smiod /* ------------------------------------------------------------------------ */
66*3d8817e4Smiod
67*3d8817e4Smiod #include <sys/user.h>
68*3d8817e4Smiod #define __LDINFO_PTRACE32__ /* for __ld_info32 */
69*3d8817e4Smiod #define __LDINFO_PTRACE64__ /* for __ld_info64 */
70*3d8817e4Smiod #include <sys/ldr.h>
71*3d8817e4Smiod #include <sys/core.h>
72*3d8817e4Smiod #include <sys/systemcfg.h>
73*3d8817e4Smiod
74*3d8817e4Smiod /* Borrowed from <sys/inttypes.h> on recent AIX versions. */
75*3d8817e4Smiod typedef unsigned long ptr_to_uint;
76*3d8817e4Smiod
77*3d8817e4Smiod #define core_hdr(bfd) ((CoreHdr *) bfd->tdata.any)
78*3d8817e4Smiod
79*3d8817e4Smiod /* AIX 4.1 changed the names and locations of a few items in the core file.
80*3d8817e4Smiod AIX 4.3 defined an entirely new structure, core_dumpx, but kept support for
81*3d8817e4Smiod the previous 4.1 structure, core_dump.
82*3d8817e4Smiod
83*3d8817e4Smiod AIX_CORE_DUMPX_CORE is defined (by configure) on AIX 4.3+, and
84*3d8817e4Smiod CORE_VERSION_1 is defined (by AIX core.h) as 2 on AIX 4.3+ and as 1 on AIX
85*3d8817e4Smiod 4.1 and 4.2. AIX pre-4.1 (aka 3.x) either doesn't define CORE_VERSION_1
86*3d8817e4Smiod or else defines it as 0. */
87*3d8817e4Smiod
88*3d8817e4Smiod #if defined(CORE_VERSION_1) && !CORE_VERSION_1
89*3d8817e4Smiod # undef CORE_VERSION_1
90*3d8817e4Smiod #endif
91*3d8817e4Smiod
92*3d8817e4Smiod /* The following union and macros allow this module to compile on all AIX
93*3d8817e4Smiod versions and to handle both core_dumpx and core_dump on 4.3+. CNEW_*()
94*3d8817e4Smiod and COLD_*() macros respectively retrieve core_dumpx and core_dump
95*3d8817e4Smiod values. */
96*3d8817e4Smiod
97*3d8817e4Smiod /* Union of 32-bit and 64-bit versions of ld_info. */
98*3d8817e4Smiod
99*3d8817e4Smiod typedef union {
100*3d8817e4Smiod #ifdef __ld_info32
101*3d8817e4Smiod struct __ld_info32 l32;
102*3d8817e4Smiod struct __ld_info64 l64;
103*3d8817e4Smiod #else
104*3d8817e4Smiod struct ld_info l32;
105*3d8817e4Smiod struct ld_info l64;
106*3d8817e4Smiod #endif
107*3d8817e4Smiod } LdInfo;
108*3d8817e4Smiod
109*3d8817e4Smiod /* Union of old and new core dump structures. */
110*3d8817e4Smiod
111*3d8817e4Smiod typedef union {
112*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
113*3d8817e4Smiod struct core_dumpx new; /* new AIX 4.3+ core dump */
114*3d8817e4Smiod #else
115*3d8817e4Smiod struct core_dump new; /* for simpler coding */
116*3d8817e4Smiod #endif
117*3d8817e4Smiod struct core_dump old; /* old AIX 4.2- core dump, still used on
118*3d8817e4Smiod 4.3+ with appropriate SMIT config */
119*3d8817e4Smiod } CoreHdr;
120*3d8817e4Smiod
121*3d8817e4Smiod /* Union of old and new vm_info structures. */
122*3d8817e4Smiod
123*3d8817e4Smiod #ifdef CORE_VERSION_1
124*3d8817e4Smiod typedef union {
125*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
126*3d8817e4Smiod struct vm_infox new;
127*3d8817e4Smiod #else
128*3d8817e4Smiod struct vm_info new;
129*3d8817e4Smiod #endif
130*3d8817e4Smiod struct vm_info old;
131*3d8817e4Smiod } VmInfo;
132*3d8817e4Smiod #endif
133*3d8817e4Smiod
134*3d8817e4Smiod /* Return whether CoreHdr C is in new or old format. */
135*3d8817e4Smiod
136*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
137*3d8817e4Smiod # define CORE_NEW(c) (!(c).old.c_entries)
138*3d8817e4Smiod #else
139*3d8817e4Smiod # define CORE_NEW(c) 0
140*3d8817e4Smiod #endif
141*3d8817e4Smiod
142*3d8817e4Smiod /* Return the c_stackorg field from struct core_dumpx C. */
143*3d8817e4Smiod
144*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
145*3d8817e4Smiod # define CNEW_STACKORG(c) (c).c_stackorg
146*3d8817e4Smiod #else
147*3d8817e4Smiod # define CNEW_STACKORG(c) 0
148*3d8817e4Smiod #endif
149*3d8817e4Smiod
150*3d8817e4Smiod /* Return the offset to the loader region from struct core_dump C. */
151*3d8817e4Smiod
152*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
153*3d8817e4Smiod # define CNEW_LOADER(c) (c).c_loader
154*3d8817e4Smiod #else
155*3d8817e4Smiod # define CNEW_LOADER(c) 0
156*3d8817e4Smiod #endif
157*3d8817e4Smiod
158*3d8817e4Smiod /* Return the offset to the loader region from struct core_dump C. */
159*3d8817e4Smiod
160*3d8817e4Smiod #define COLD_LOADER(c) (c).c_tab
161*3d8817e4Smiod
162*3d8817e4Smiod /* Return the c_lsize field from struct core_dumpx C. */
163*3d8817e4Smiod
164*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
165*3d8817e4Smiod # define CNEW_LSIZE(c) (c).c_lsize
166*3d8817e4Smiod #else
167*3d8817e4Smiod # define CNEW_LSIZE(c) 0
168*3d8817e4Smiod #endif
169*3d8817e4Smiod
170*3d8817e4Smiod /* Return the c_dataorg field from struct core_dumpx C. */
171*3d8817e4Smiod
172*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
173*3d8817e4Smiod # define CNEW_DATAORG(c) (c).c_dataorg
174*3d8817e4Smiod #else
175*3d8817e4Smiod # define CNEW_DATAORG(c) 0
176*3d8817e4Smiod #endif
177*3d8817e4Smiod
178*3d8817e4Smiod /* Return the c_datasize field from struct core_dumpx C. */
179*3d8817e4Smiod
180*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
181*3d8817e4Smiod # define CNEW_DATASIZE(c) (c).c_datasize
182*3d8817e4Smiod #else
183*3d8817e4Smiod # define CNEW_DATASIZE(c) 0
184*3d8817e4Smiod #endif
185*3d8817e4Smiod
186*3d8817e4Smiod /* Return the c_impl field from struct core_dumpx C. */
187*3d8817e4Smiod
188*3d8817e4Smiod #if defined (HAVE_ST_C_IMPL) || defined (AIX_5_CORE)
189*3d8817e4Smiod # define CNEW_IMPL(c) (c).c_impl
190*3d8817e4Smiod #else
191*3d8817e4Smiod # define CNEW_IMPL(c) 0
192*3d8817e4Smiod #endif
193*3d8817e4Smiod
194*3d8817e4Smiod /* Return the command string from struct core_dumpx C. */
195*3d8817e4Smiod
196*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
197*3d8817e4Smiod # define CNEW_COMM(c) (c).c_u.U_proc.pi_comm
198*3d8817e4Smiod #else
199*3d8817e4Smiod # define CNEW_COMM(c) 0
200*3d8817e4Smiod #endif
201*3d8817e4Smiod
202*3d8817e4Smiod /* Return the command string from struct core_dump C. */
203*3d8817e4Smiod
204*3d8817e4Smiod #ifdef CORE_VERSION_1
205*3d8817e4Smiod # define COLD_COMM(c) (c).c_u.U_comm
206*3d8817e4Smiod #else
207*3d8817e4Smiod # define COLD_COMM(c) (c).c_u.u_comm
208*3d8817e4Smiod #endif
209*3d8817e4Smiod
210*3d8817e4Smiod /* Return the struct __context64 pointer from struct core_dumpx C. */
211*3d8817e4Smiod
212*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
213*3d8817e4Smiod # define CNEW_CONTEXT64(c) (c).c_flt.hctx.r64
214*3d8817e4Smiod #else
215*3d8817e4Smiod # define CNEW_CONTEXT64(c) c
216*3d8817e4Smiod #endif
217*3d8817e4Smiod
218*3d8817e4Smiod /* Return the struct mstsave pointer from struct core_dumpx C. */
219*3d8817e4Smiod
220*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
221*3d8817e4Smiod # define CNEW_MSTSAVE(c) (c).c_flt.hctx.r32
222*3d8817e4Smiod #else
223*3d8817e4Smiod # define CNEW_MSTSAVE(c) c
224*3d8817e4Smiod #endif
225*3d8817e4Smiod
226*3d8817e4Smiod /* Return the struct mstsave pointer from struct core_dump C. */
227*3d8817e4Smiod
228*3d8817e4Smiod #ifdef CORE_VERSION_1
229*3d8817e4Smiod # define COLD_MSTSAVE(c) (c).c_mst
230*3d8817e4Smiod #else
231*3d8817e4Smiod # define COLD_MSTSAVE(c) (c).c_u.u_save
232*3d8817e4Smiod #endif
233*3d8817e4Smiod
234*3d8817e4Smiod /* Return whether struct core_dumpx is from a 64-bit process. */
235*3d8817e4Smiod
236*3d8817e4Smiod #ifdef AIX_CORE_DUMPX_CORE
237*3d8817e4Smiod # define CNEW_PROC64(c) IS_PROC64(&(c).c_u.U_proc)
238*3d8817e4Smiod #else
239*3d8817e4Smiod # define CNEW_PROC64(c) 0
240*3d8817e4Smiod #endif
241*3d8817e4Smiod
242*3d8817e4Smiod /* Magic end-of-stack addresses for old core dumps. This is _very_ fragile,
243*3d8817e4Smiod but I don't see any easy way to get that info right now. */
244*3d8817e4Smiod
245*3d8817e4Smiod #ifdef CORE_VERSION_1
246*3d8817e4Smiod # define COLD_STACKEND 0x2ff23000
247*3d8817e4Smiod #else
248*3d8817e4Smiod # define COLD_STACKEND 0x2ff80000
249*3d8817e4Smiod #endif
250*3d8817e4Smiod
251*3d8817e4Smiod /* Size of the leading portion that old and new core dump structures have in
252*3d8817e4Smiod common. */
253*3d8817e4Smiod #define CORE_COMMONSZ ((int) &((struct core_dump *) 0)->c_entries \
254*3d8817e4Smiod + sizeof (((struct core_dump *) 0)->c_entries))
255*3d8817e4Smiod
256*3d8817e4Smiod /* Define prototypes for certain functions, to avoid a compiler warning
257*3d8817e4Smiod saying that they are missing. */
258*3d8817e4Smiod
259*3d8817e4Smiod const bfd_target * rs6000coff_core_p (bfd *abfd);
260*3d8817e4Smiod bfd_boolean rs6000coff_core_file_matches_executable_p (bfd *core_bfd,
261*3d8817e4Smiod bfd *exec_bfd);
262*3d8817e4Smiod char * rs6000coff_core_file_failing_command (bfd *abfd);
263*3d8817e4Smiod int rs6000coff_core_file_failing_signal (bfd *abfd);
264*3d8817e4Smiod
265*3d8817e4Smiod /* Try to read into CORE the header from the core file associated with ABFD.
266*3d8817e4Smiod Return success. */
267*3d8817e4Smiod
268*3d8817e4Smiod static bfd_boolean
read_hdr(bfd * abfd,CoreHdr * core)269*3d8817e4Smiod read_hdr (bfd *abfd, CoreHdr *core)
270*3d8817e4Smiod {
271*3d8817e4Smiod bfd_size_type size;
272*3d8817e4Smiod
273*3d8817e4Smiod if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
274*3d8817e4Smiod return FALSE;
275*3d8817e4Smiod
276*3d8817e4Smiod /* Read the leading portion that old and new core dump structures have in
277*3d8817e4Smiod common. */
278*3d8817e4Smiod size = CORE_COMMONSZ;
279*3d8817e4Smiod if (bfd_bread (core, size, abfd) != size)
280*3d8817e4Smiod return FALSE;
281*3d8817e4Smiod
282*3d8817e4Smiod /* Read the trailing portion of the structure. */
283*3d8817e4Smiod if (CORE_NEW (*core))
284*3d8817e4Smiod size = sizeof (core->new);
285*3d8817e4Smiod else
286*3d8817e4Smiod size = sizeof (core->old);
287*3d8817e4Smiod size -= CORE_COMMONSZ;
288*3d8817e4Smiod return bfd_bread ((char *) core + CORE_COMMONSZ, size, abfd) == size;
289*3d8817e4Smiod }
290*3d8817e4Smiod
291*3d8817e4Smiod static asection *
make_bfd_asection(bfd * abfd,const char * name,flagword flags,bfd_size_type size,bfd_vma vma,file_ptr filepos)292*3d8817e4Smiod make_bfd_asection (bfd *abfd, const char *name, flagword flags,
293*3d8817e4Smiod bfd_size_type size, bfd_vma vma, file_ptr filepos)
294*3d8817e4Smiod {
295*3d8817e4Smiod asection *asect;
296*3d8817e4Smiod
297*3d8817e4Smiod asect = bfd_make_section_anyway (abfd, name);
298*3d8817e4Smiod if (!asect)
299*3d8817e4Smiod return NULL;
300*3d8817e4Smiod
301*3d8817e4Smiod asect->flags = flags;
302*3d8817e4Smiod asect->size = size;
303*3d8817e4Smiod asect->vma = vma;
304*3d8817e4Smiod asect->filepos = filepos;
305*3d8817e4Smiod asect->alignment_power = 8;
306*3d8817e4Smiod
307*3d8817e4Smiod return asect;
308*3d8817e4Smiod }
309*3d8817e4Smiod
310*3d8817e4Smiod /* Decide if a given bfd represents a `core' file or not. There really is no
311*3d8817e4Smiod magic number or anything like, in rs6000coff. */
312*3d8817e4Smiod
313*3d8817e4Smiod const bfd_target *
rs6000coff_core_p(bfd * abfd)314*3d8817e4Smiod rs6000coff_core_p (bfd *abfd)
315*3d8817e4Smiod {
316*3d8817e4Smiod CoreHdr core;
317*3d8817e4Smiod struct stat statbuf;
318*3d8817e4Smiod bfd_size_type size;
319*3d8817e4Smiod char *tmpptr;
320*3d8817e4Smiod
321*3d8817e4Smiod /* Values from new and old core structures. */
322*3d8817e4Smiod int c_flag;
323*3d8817e4Smiod file_ptr c_stack, c_regoff, c_loader;
324*3d8817e4Smiod bfd_size_type c_size, c_regsize, c_lsize;
325*3d8817e4Smiod bfd_vma c_stackend;
326*3d8817e4Smiod void *c_regptr;
327*3d8817e4Smiod int proc64;
328*3d8817e4Smiod
329*3d8817e4Smiod if (!read_hdr (abfd, &core))
330*3d8817e4Smiod {
331*3d8817e4Smiod if (bfd_get_error () != bfd_error_system_call)
332*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
333*3d8817e4Smiod return NULL;
334*3d8817e4Smiod }
335*3d8817e4Smiod
336*3d8817e4Smiod /* Copy fields from new or old core structure. */
337*3d8817e4Smiod if (CORE_NEW (core))
338*3d8817e4Smiod {
339*3d8817e4Smiod c_flag = core.new.c_flag;
340*3d8817e4Smiod c_stack = (file_ptr) core.new.c_stack;
341*3d8817e4Smiod c_size = core.new.c_size;
342*3d8817e4Smiod c_stackend = CNEW_STACKORG (core.new) + c_size;
343*3d8817e4Smiod c_lsize = CNEW_LSIZE (core.new);
344*3d8817e4Smiod c_loader = CNEW_LOADER (core.new);
345*3d8817e4Smiod proc64 = CNEW_PROC64 (core.new);
346*3d8817e4Smiod }
347*3d8817e4Smiod else
348*3d8817e4Smiod {
349*3d8817e4Smiod c_flag = core.old.c_flag;
350*3d8817e4Smiod c_stack = (file_ptr) (ptr_to_uint) core.old.c_stack;
351*3d8817e4Smiod c_size = core.old.c_size;
352*3d8817e4Smiod c_stackend = COLD_STACKEND;
353*3d8817e4Smiod c_lsize = 0x7ffffff;
354*3d8817e4Smiod c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old);
355*3d8817e4Smiod proc64 = 0;
356*3d8817e4Smiod }
357*3d8817e4Smiod
358*3d8817e4Smiod if (proc64)
359*3d8817e4Smiod {
360*3d8817e4Smiod c_regsize = sizeof (CNEW_CONTEXT64 (core.new));
361*3d8817e4Smiod c_regptr = &CNEW_CONTEXT64 (core.new);
362*3d8817e4Smiod }
363*3d8817e4Smiod else if (CORE_NEW (core))
364*3d8817e4Smiod {
365*3d8817e4Smiod c_regsize = sizeof (CNEW_MSTSAVE (core.new));
366*3d8817e4Smiod c_regptr = &CNEW_MSTSAVE (core.new);
367*3d8817e4Smiod }
368*3d8817e4Smiod else
369*3d8817e4Smiod {
370*3d8817e4Smiod c_regsize = sizeof (COLD_MSTSAVE (core.old));
371*3d8817e4Smiod c_regptr = &COLD_MSTSAVE (core.old);
372*3d8817e4Smiod }
373*3d8817e4Smiod c_regoff = (char *) c_regptr - (char *) &core;
374*3d8817e4Smiod
375*3d8817e4Smiod if (bfd_stat (abfd, &statbuf) < 0)
376*3d8817e4Smiod {
377*3d8817e4Smiod bfd_set_error (bfd_error_system_call);
378*3d8817e4Smiod return NULL;
379*3d8817e4Smiod }
380*3d8817e4Smiod
381*3d8817e4Smiod /* If the core file ulimit is too small, the system will first
382*3d8817e4Smiod omit the data segment, then omit the stack, then decline to
383*3d8817e4Smiod dump core altogether (as far as I know UBLOCK_VALID and LE_VALID
384*3d8817e4Smiod are always set) (this is based on experimentation on AIX 3.2).
385*3d8817e4Smiod Now, the thing is that GDB users will be surprised
386*3d8817e4Smiod if segments just silently don't appear (well, maybe they would
387*3d8817e4Smiod think to check "info files", I don't know).
388*3d8817e4Smiod
389*3d8817e4Smiod For the data segment, we have no choice but to keep going if it's
390*3d8817e4Smiod not there, since the default behavior is not to dump it (regardless
391*3d8817e4Smiod of the ulimit, it's based on SA_FULLDUMP). But for the stack segment,
392*3d8817e4Smiod if it's not there, we refuse to have anything to do with this core
393*3d8817e4Smiod file. The usefulness of a core dump without a stack segment is pretty
394*3d8817e4Smiod limited anyway. */
395*3d8817e4Smiod
396*3d8817e4Smiod if (!(c_flag & UBLOCK_VALID)
397*3d8817e4Smiod || !(c_flag & LE_VALID))
398*3d8817e4Smiod {
399*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
400*3d8817e4Smiod return NULL;
401*3d8817e4Smiod }
402*3d8817e4Smiod
403*3d8817e4Smiod if (!(c_flag & USTACK_VALID))
404*3d8817e4Smiod {
405*3d8817e4Smiod bfd_set_error (bfd_error_file_truncated);
406*3d8817e4Smiod return NULL;
407*3d8817e4Smiod }
408*3d8817e4Smiod
409*3d8817e4Smiod /* Don't check the core file size for a full core, AIX 4.1 includes
410*3d8817e4Smiod additional shared library sections in a full core. */
411*3d8817e4Smiod if (!(c_flag & (FULL_CORE | CORE_TRUNC)))
412*3d8817e4Smiod {
413*3d8817e4Smiod /* If the size is wrong, it means we're misinterpreting something. */
414*3d8817e4Smiod if (c_stack + (file_ptr) c_size != statbuf.st_size)
415*3d8817e4Smiod {
416*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
417*3d8817e4Smiod return NULL;
418*3d8817e4Smiod }
419*3d8817e4Smiod }
420*3d8817e4Smiod
421*3d8817e4Smiod /* Sanity check on the c_tab field. */
422*3d8817e4Smiod if (!CORE_NEW (core) && (c_loader < (file_ptr) sizeof core.old ||
423*3d8817e4Smiod c_loader >= statbuf.st_size ||
424*3d8817e4Smiod c_loader >= c_stack))
425*3d8817e4Smiod {
426*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
427*3d8817e4Smiod return NULL;
428*3d8817e4Smiod }
429*3d8817e4Smiod
430*3d8817e4Smiod /* Issue warning if the core file was truncated during writing. */
431*3d8817e4Smiod if (c_flag & CORE_TRUNC)
432*3d8817e4Smiod (*_bfd_error_handler) (_("%s: warning core file truncated"),
433*3d8817e4Smiod bfd_get_filename (abfd));
434*3d8817e4Smiod
435*3d8817e4Smiod /* Allocate core file header. */
436*3d8817e4Smiod size = CORE_NEW (core) ? sizeof (core.new) : sizeof (core.old);
437*3d8817e4Smiod tmpptr = (char *) bfd_zalloc (abfd, (bfd_size_type) size);
438*3d8817e4Smiod if (!tmpptr)
439*3d8817e4Smiod return NULL;
440*3d8817e4Smiod
441*3d8817e4Smiod /* Copy core file header. */
442*3d8817e4Smiod memcpy (tmpptr, &core, size);
443*3d8817e4Smiod set_tdata (abfd, tmpptr);
444*3d8817e4Smiod
445*3d8817e4Smiod /* Set architecture. */
446*3d8817e4Smiod if (CORE_NEW (core))
447*3d8817e4Smiod {
448*3d8817e4Smiod enum bfd_architecture arch;
449*3d8817e4Smiod unsigned long mach;
450*3d8817e4Smiod
451*3d8817e4Smiod switch (CNEW_IMPL (core.new))
452*3d8817e4Smiod {
453*3d8817e4Smiod case POWER_RS1:
454*3d8817e4Smiod case POWER_RSC:
455*3d8817e4Smiod case POWER_RS2:
456*3d8817e4Smiod arch = bfd_arch_rs6000;
457*3d8817e4Smiod mach = bfd_mach_rs6k;
458*3d8817e4Smiod break;
459*3d8817e4Smiod default:
460*3d8817e4Smiod arch = bfd_arch_powerpc;
461*3d8817e4Smiod mach = bfd_mach_ppc;
462*3d8817e4Smiod break;
463*3d8817e4Smiod }
464*3d8817e4Smiod bfd_default_set_arch_mach (abfd, arch, mach);
465*3d8817e4Smiod }
466*3d8817e4Smiod
467*3d8817e4Smiod /* .stack section. */
468*3d8817e4Smiod if (!make_bfd_asection (abfd, ".stack",
469*3d8817e4Smiod SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
470*3d8817e4Smiod c_size, c_stackend - c_size, c_stack))
471*3d8817e4Smiod goto fail;
472*3d8817e4Smiod
473*3d8817e4Smiod /* .reg section for all registers. */
474*3d8817e4Smiod if (!make_bfd_asection (abfd, ".reg",
475*3d8817e4Smiod SEC_HAS_CONTENTS,
476*3d8817e4Smiod c_regsize, (bfd_vma) 0, c_regoff))
477*3d8817e4Smiod goto fail;
478*3d8817e4Smiod
479*3d8817e4Smiod /* .ldinfo section.
480*3d8817e4Smiod To actually find out how long this section is in this particular
481*3d8817e4Smiod core dump would require going down the whole list of struct ld_info's.
482*3d8817e4Smiod See if we can just fake it. */
483*3d8817e4Smiod if (!make_bfd_asection (abfd, ".ldinfo",
484*3d8817e4Smiod SEC_HAS_CONTENTS,
485*3d8817e4Smiod c_lsize, (bfd_vma) 0, c_loader))
486*3d8817e4Smiod goto fail;
487*3d8817e4Smiod
488*3d8817e4Smiod #ifndef CORE_VERSION_1
489*3d8817e4Smiod /* .data section if present.
490*3d8817e4Smiod AIX 3 dumps the complete data section and sets FULL_CORE if the
491*3d8817e4Smiod ulimit is large enough, otherwise the data section is omitted.
492*3d8817e4Smiod AIX 4 sets FULL_CORE even if the core file is truncated, we have
493*3d8817e4Smiod to examine core.c_datasize below to find out the actual size of
494*3d8817e4Smiod the .data section. */
495*3d8817e4Smiod if (c_flag & FULL_CORE)
496*3d8817e4Smiod {
497*3d8817e4Smiod if (!make_bfd_asection (abfd, ".data",
498*3d8817e4Smiod SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
499*3d8817e4Smiod (bfd_size_type) core.old.c_u.u_dsize,
500*3d8817e4Smiod (bfd_vma)
501*3d8817e4Smiod CDATA_ADDR (core.old.c_u.u_dsize),
502*3d8817e4Smiod c_stack + c_size))
503*3d8817e4Smiod goto fail;
504*3d8817e4Smiod }
505*3d8817e4Smiod #endif
506*3d8817e4Smiod
507*3d8817e4Smiod #ifdef CORE_VERSION_1
508*3d8817e4Smiod /* AIX 4 adds data sections from loaded objects to the core file,
509*3d8817e4Smiod which can be found by examining ldinfo, and anonymously mmapped
510*3d8817e4Smiod regions. */
511*3d8817e4Smiod {
512*3d8817e4Smiod LdInfo ldinfo;
513*3d8817e4Smiod bfd_size_type ldi_datasize;
514*3d8817e4Smiod file_ptr ldi_core;
515*3d8817e4Smiod uint ldi_next;
516*3d8817e4Smiod bfd_vma ldi_dataorg;
517*3d8817e4Smiod
518*3d8817e4Smiod /* Fields from new and old core structures. */
519*3d8817e4Smiod bfd_size_type c_datasize, c_vmregions;
520*3d8817e4Smiod file_ptr c_data, c_vmm;
521*3d8817e4Smiod
522*3d8817e4Smiod if (CORE_NEW (core))
523*3d8817e4Smiod {
524*3d8817e4Smiod c_datasize = CNEW_DATASIZE (core.new);
525*3d8817e4Smiod c_data = (file_ptr) core.new.c_data;
526*3d8817e4Smiod c_vmregions = core.new.c_vmregions;
527*3d8817e4Smiod c_vmm = (file_ptr) core.new.c_vmm;
528*3d8817e4Smiod }
529*3d8817e4Smiod else
530*3d8817e4Smiod {
531*3d8817e4Smiod c_datasize = core.old.c_datasize;
532*3d8817e4Smiod c_data = (file_ptr) (ptr_to_uint) core.old.c_data;
533*3d8817e4Smiod c_vmregions = core.old.c_vmregions;
534*3d8817e4Smiod c_vmm = (file_ptr) (ptr_to_uint) core.old.c_vmm;
535*3d8817e4Smiod }
536*3d8817e4Smiod
537*3d8817e4Smiod /* .data section from executable. */
538*3d8817e4Smiod if (c_datasize)
539*3d8817e4Smiod {
540*3d8817e4Smiod if (!make_bfd_asection (abfd, ".data",
541*3d8817e4Smiod SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
542*3d8817e4Smiod c_datasize,
543*3d8817e4Smiod (bfd_vma) CDATA_ADDR (c_datasize),
544*3d8817e4Smiod c_data))
545*3d8817e4Smiod goto fail;
546*3d8817e4Smiod }
547*3d8817e4Smiod
548*3d8817e4Smiod /* .data sections from loaded objects. */
549*3d8817e4Smiod if (proc64)
550*3d8817e4Smiod size = (int) ((LdInfo *) 0)->l64.ldinfo_filename;
551*3d8817e4Smiod else
552*3d8817e4Smiod size = (int) ((LdInfo *) 0)->l32.ldinfo_filename;
553*3d8817e4Smiod
554*3d8817e4Smiod while (1)
555*3d8817e4Smiod {
556*3d8817e4Smiod if (bfd_seek (abfd, c_loader, SEEK_SET) != 0)
557*3d8817e4Smiod goto fail;
558*3d8817e4Smiod if (bfd_bread (&ldinfo, size, abfd) != size)
559*3d8817e4Smiod goto fail;
560*3d8817e4Smiod
561*3d8817e4Smiod if (proc64)
562*3d8817e4Smiod {
563*3d8817e4Smiod ldi_core = ldinfo.l64.ldinfo_core;
564*3d8817e4Smiod ldi_datasize = ldinfo.l64.ldinfo_datasize;
565*3d8817e4Smiod ldi_dataorg = (bfd_vma) ldinfo.l64.ldinfo_dataorg;
566*3d8817e4Smiod ldi_next = ldinfo.l64.ldinfo_next;
567*3d8817e4Smiod }
568*3d8817e4Smiod else
569*3d8817e4Smiod {
570*3d8817e4Smiod ldi_core = ldinfo.l32.ldinfo_core;
571*3d8817e4Smiod ldi_datasize = ldinfo.l32.ldinfo_datasize;
572*3d8817e4Smiod ldi_dataorg = (bfd_vma) (long) ldinfo.l32.ldinfo_dataorg;
573*3d8817e4Smiod ldi_next = ldinfo.l32.ldinfo_next;
574*3d8817e4Smiod }
575*3d8817e4Smiod
576*3d8817e4Smiod if (ldi_core)
577*3d8817e4Smiod if (!make_bfd_asection (abfd, ".data",
578*3d8817e4Smiod SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
579*3d8817e4Smiod ldi_datasize, ldi_dataorg, ldi_core))
580*3d8817e4Smiod goto fail;
581*3d8817e4Smiod
582*3d8817e4Smiod if (ldi_next == 0)
583*3d8817e4Smiod break;
584*3d8817e4Smiod c_loader += ldi_next;
585*3d8817e4Smiod }
586*3d8817e4Smiod
587*3d8817e4Smiod /* .vmdata sections from anonymously mmapped regions. */
588*3d8817e4Smiod if (c_vmregions)
589*3d8817e4Smiod {
590*3d8817e4Smiod bfd_size_type i;
591*3d8817e4Smiod
592*3d8817e4Smiod if (bfd_seek (abfd, c_vmm, SEEK_SET) != 0)
593*3d8817e4Smiod goto fail;
594*3d8817e4Smiod
595*3d8817e4Smiod for (i = 0; i < c_vmregions; i++)
596*3d8817e4Smiod {
597*3d8817e4Smiod VmInfo vminfo;
598*3d8817e4Smiod bfd_size_type vminfo_size;
599*3d8817e4Smiod file_ptr vminfo_offset;
600*3d8817e4Smiod bfd_vma vminfo_addr;
601*3d8817e4Smiod
602*3d8817e4Smiod size = CORE_NEW (core) ? sizeof (vminfo.new) : sizeof (vminfo.old);
603*3d8817e4Smiod if (bfd_bread (&vminfo, size, abfd) != size)
604*3d8817e4Smiod goto fail;
605*3d8817e4Smiod
606*3d8817e4Smiod if (CORE_NEW (core))
607*3d8817e4Smiod {
608*3d8817e4Smiod vminfo_addr = (bfd_vma) vminfo.new.vminfo_addr;
609*3d8817e4Smiod vminfo_size = vminfo.new.vminfo_size;
610*3d8817e4Smiod vminfo_offset = vminfo.new.vminfo_offset;
611*3d8817e4Smiod }
612*3d8817e4Smiod else
613*3d8817e4Smiod {
614*3d8817e4Smiod vminfo_addr = (bfd_vma) (long) vminfo.old.vminfo_addr;
615*3d8817e4Smiod vminfo_size = vminfo.old.vminfo_size;
616*3d8817e4Smiod vminfo_offset = vminfo.old.vminfo_offset;
617*3d8817e4Smiod }
618*3d8817e4Smiod
619*3d8817e4Smiod if (vminfo_offset)
620*3d8817e4Smiod if (!make_bfd_asection (abfd, ".vmdata",
621*3d8817e4Smiod SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
622*3d8817e4Smiod vminfo_size, vminfo_addr,
623*3d8817e4Smiod vminfo_offset))
624*3d8817e4Smiod goto fail;
625*3d8817e4Smiod }
626*3d8817e4Smiod }
627*3d8817e4Smiod }
628*3d8817e4Smiod #endif
629*3d8817e4Smiod
630*3d8817e4Smiod return abfd->xvec; /* This is garbage for now. */
631*3d8817e4Smiod
632*3d8817e4Smiod fail:
633*3d8817e4Smiod bfd_release (abfd, abfd->tdata.any);
634*3d8817e4Smiod abfd->tdata.any = NULL;
635*3d8817e4Smiod bfd_section_list_clear (abfd);
636*3d8817e4Smiod return NULL;
637*3d8817e4Smiod }
638*3d8817e4Smiod
639*3d8817e4Smiod /* Return `TRUE' if given core is from the given executable. */
640*3d8817e4Smiod
641*3d8817e4Smiod bfd_boolean
rs6000coff_core_file_matches_executable_p(bfd * core_bfd,bfd * exec_bfd)642*3d8817e4Smiod rs6000coff_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
643*3d8817e4Smiod {
644*3d8817e4Smiod CoreHdr core;
645*3d8817e4Smiod bfd_size_type size;
646*3d8817e4Smiod char *path, *s;
647*3d8817e4Smiod size_t alloc;
648*3d8817e4Smiod const char *str1, *str2;
649*3d8817e4Smiod bfd_boolean ret;
650*3d8817e4Smiod file_ptr c_loader;
651*3d8817e4Smiod
652*3d8817e4Smiod if (!read_hdr (core_bfd, &core))
653*3d8817e4Smiod return FALSE;
654*3d8817e4Smiod
655*3d8817e4Smiod if (CORE_NEW (core))
656*3d8817e4Smiod c_loader = CNEW_LOADER (core.new);
657*3d8817e4Smiod else
658*3d8817e4Smiod c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old);
659*3d8817e4Smiod
660*3d8817e4Smiod if (CORE_NEW (core) && CNEW_PROC64 (core.new))
661*3d8817e4Smiod size = (int) ((LdInfo *) 0)->l64.ldinfo_filename;
662*3d8817e4Smiod else
663*3d8817e4Smiod size = (int) ((LdInfo *) 0)->l32.ldinfo_filename;
664*3d8817e4Smiod
665*3d8817e4Smiod if (bfd_seek (core_bfd, c_loader + size, SEEK_SET) != 0)
666*3d8817e4Smiod return FALSE;
667*3d8817e4Smiod
668*3d8817e4Smiod alloc = 100;
669*3d8817e4Smiod path = bfd_malloc ((bfd_size_type) alloc);
670*3d8817e4Smiod if (path == NULL)
671*3d8817e4Smiod return FALSE;
672*3d8817e4Smiod s = path;
673*3d8817e4Smiod
674*3d8817e4Smiod while (1)
675*3d8817e4Smiod {
676*3d8817e4Smiod if (bfd_bread (s, (bfd_size_type) 1, core_bfd) != 1)
677*3d8817e4Smiod {
678*3d8817e4Smiod free (path);
679*3d8817e4Smiod return FALSE;
680*3d8817e4Smiod }
681*3d8817e4Smiod if (*s == '\0')
682*3d8817e4Smiod break;
683*3d8817e4Smiod ++s;
684*3d8817e4Smiod if (s == path + alloc)
685*3d8817e4Smiod {
686*3d8817e4Smiod char *n;
687*3d8817e4Smiod
688*3d8817e4Smiod alloc *= 2;
689*3d8817e4Smiod n = bfd_realloc (path, (bfd_size_type) alloc);
690*3d8817e4Smiod if (n == NULL)
691*3d8817e4Smiod {
692*3d8817e4Smiod free (path);
693*3d8817e4Smiod return FALSE;
694*3d8817e4Smiod }
695*3d8817e4Smiod s = n + (path - s);
696*3d8817e4Smiod path = n;
697*3d8817e4Smiod }
698*3d8817e4Smiod }
699*3d8817e4Smiod
700*3d8817e4Smiod str1 = strrchr (path, '/');
701*3d8817e4Smiod str2 = strrchr (exec_bfd->filename, '/');
702*3d8817e4Smiod
703*3d8817e4Smiod /* step over character '/' */
704*3d8817e4Smiod str1 = str1 != NULL ? str1 + 1 : path;
705*3d8817e4Smiod str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
706*3d8817e4Smiod
707*3d8817e4Smiod if (strcmp (str1, str2) == 0)
708*3d8817e4Smiod ret = TRUE;
709*3d8817e4Smiod else
710*3d8817e4Smiod ret = FALSE;
711*3d8817e4Smiod
712*3d8817e4Smiod free (path);
713*3d8817e4Smiod
714*3d8817e4Smiod return ret;
715*3d8817e4Smiod }
716*3d8817e4Smiod
717*3d8817e4Smiod char *
rs6000coff_core_file_failing_command(bfd * abfd)718*3d8817e4Smiod rs6000coff_core_file_failing_command (bfd *abfd)
719*3d8817e4Smiod {
720*3d8817e4Smiod CoreHdr *core = core_hdr (abfd);
721*3d8817e4Smiod char *com = CORE_NEW (*core) ?
722*3d8817e4Smiod CNEW_COMM (core->new) : COLD_COMM (core->old);
723*3d8817e4Smiod
724*3d8817e4Smiod if (*com)
725*3d8817e4Smiod return com;
726*3d8817e4Smiod else
727*3d8817e4Smiod return 0;
728*3d8817e4Smiod }
729*3d8817e4Smiod
730*3d8817e4Smiod int
rs6000coff_core_file_failing_signal(bfd * abfd)731*3d8817e4Smiod rs6000coff_core_file_failing_signal (bfd *abfd)
732*3d8817e4Smiod {
733*3d8817e4Smiod CoreHdr *core = core_hdr (abfd);
734*3d8817e4Smiod return CORE_NEW (*core) ? core->new.c_signo : core->old.c_signo;
735*3d8817e4Smiod }
736*3d8817e4Smiod
737*3d8817e4Smiod #endif /* AIX_CORE */
738