Initial revision
[binutils.git] / bfd / rs6000-core.c
blobb20555f5d3817b62f21ae509599e2a502cfee81d
1 /* IBM RS/6000 "XCOFF" back-end for BFD.
2 Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998
3 Free Software Foundation, Inc.
4 FIXME: Can someone provide a transliteration of this name into ASCII?
5 Using the following chars caused a compiler warning on HIUX (so I replaced
6 them with octal escapes), and isn't useful without an understanding of what
7 character set it is.
8 Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
9 and John Gilmore.
10 Archive support from Damon A. Permezel.
11 Contributed by IBM Corporation and Cygnus Support.
13 This file is part of BFD, the Binary File Descriptor library.
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
29 /* This port currently only handles reading object files, except when
30 compiled on an RS/6000 host. -- no archive support, no core files.
31 In all cases, it does not support writing.
33 FIXMEmgo comments are left from Metin Ozisik's original port.
35 This is in a separate file from coff-rs6000.c, because it includes
36 system include files that conflict with coff/rs6000.h.
39 /* Internalcoff.h and coffcode.h modify themselves based on this flag. */
40 #define RS6000COFF_C 1
42 /* The AIX 4.1 kernel is obviously compiled with -D_LONG_LONG, so
43 we have to define _LONG_LONG for older versions of gcc to get the
44 proper alignments in the user structure. */
45 #if defined(_AIX41) && !defined(_LONG_LONG)
46 #define _LONG_LONG
47 #endif
49 #include "bfd.h"
50 #include "sysdep.h"
51 #include "libbfd.h"
53 #ifdef AIX_CORE
55 /* AOUTHDR is defined by the above. We need another defn of it, from the
56 system include files. Punt the old one and get us a new name for the
57 typedef in the system include files. */
58 #ifdef AOUTHDR
59 #undef AOUTHDR
60 #endif
61 #define AOUTHDR second_AOUTHDR
63 #undef SCNHDR
66 /* ------------------------------------------------------------------------ */
67 /* Support for core file stuff.. */
68 /* ------------------------------------------------------------------------ */
70 #include <sys/user.h>
71 #include <sys/ldr.h>
72 #include <sys/core.h>
75 /* Number of special purpose registers supported by gdb. This value
76 should match `tm.h' in gdb directory. Clean this mess up and use
77 the macros in sys/reg.h. FIXMEmgo. */
79 #define NUM_OF_SPEC_REGS 7
81 #define core_hdr(bfd) (((Rs6kCorData*)(bfd->tdata.any))->hdr)
83 /* AIX 4.1 Changed the names and locations of a few items in the core file,
84 this seems to be the quickest easiet way to deal with it.
86 Note however that encoding magic addresses (STACK_END_ADDR) is going
87 to be _very_ fragile. But I don't see any easy way to get that info
88 right now. */
89 #ifdef CORE_VERSION_1
90 #define CORE_DATA_SIZE_FIELD c_u.U_dsize
91 #define CORE_COMM_FIELD c_u.U_comm
92 #define SAVE_FIELD c_mst
93 #define STACK_END_ADDR 0x2ff23000
94 #else
95 #define CORE_DATA_SIZE_FIELD c_u.u_dsize
96 #define CORE_COMM_FIELD c_u.u_comm
97 #define SAVE_FIELD c_u.u_save
98 #define STACK_END_ADDR 0x2ff80000
99 #endif
101 /* These are stored in the bfd's tdata */
102 typedef struct {
103 struct core_dump hdr; /* core file header */
104 } Rs6kCorData;
106 static asection *make_bfd_asection PARAMS ((bfd *, CONST char *, flagword,
107 bfd_size_type, bfd_vma, file_ptr));
109 static asection *
110 make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
111 bfd *abfd;
112 CONST char *name;
113 flagword flags;
114 bfd_size_type _raw_size;
115 bfd_vma vma;
116 file_ptr filepos;
118 asection *asect;
120 asect = bfd_make_section_anyway (abfd, name);
121 if (!asect)
122 return NULL;
124 asect->flags = flags;
125 asect->_raw_size = _raw_size;
126 asect->vma = vma;
127 asect->filepos = filepos;
128 asect->alignment_power = 8;
130 return asect;
133 /* Decide if a given bfd represents a `core' file or not. There really is no
134 magic number or anything like, in rs6000coff. */
136 const bfd_target *
137 rs6000coff_core_p (abfd)
138 bfd *abfd;
140 struct core_dump coredata;
141 struct stat statbuf;
142 bfd_size_type nread;
143 char *tmpptr;
145 if (bfd_seek (abfd, 0, SEEK_SET) != 0)
146 return NULL;
148 nread = bfd_read (&coredata, 1, sizeof (struct core_dump), abfd);
149 if (nread != sizeof (struct core_dump))
151 if (bfd_get_error () != bfd_error_system_call)
152 bfd_set_error (bfd_error_wrong_format);
153 return NULL;
156 if (bfd_stat (abfd, &statbuf) < 0)
158 bfd_set_error (bfd_error_system_call);
159 return NULL;
162 /* If the core file ulimit is too small, the system will first
163 omit the data segment, then omit the stack, then decline to
164 dump core altogether (as far as I know UBLOCK_VALID and LE_VALID
165 are always set) (this is based on experimentation on AIX 3.2).
166 Now, the thing is that GDB users will be surprised
167 if segments just silently don't appear (well, maybe they would
168 think to check "info files", I don't know).
170 For the data segment, we have no choice but to keep going if it's
171 not there, since the default behavior is not to dump it (regardless
172 of the ulimit, it's based on SA_FULLDUMP). But for the stack segment,
173 if it's not there, we refuse to have anything to do with this core
174 file. The usefulness of a core dump without a stack segment is pretty
175 limited anyway. */
177 if (!(coredata.c_flag & UBLOCK_VALID)
178 || !(coredata.c_flag & LE_VALID))
180 bfd_set_error (bfd_error_wrong_format);
181 return NULL;
184 if (!(coredata.c_flag & USTACK_VALID))
186 bfd_set_error (bfd_error_file_truncated);
187 return NULL;
190 /* Don't check the core file size for a full core, AIX 4.1 includes
191 additional shared library sections in a full core. */
192 if (!(coredata.c_flag & (FULL_CORE | CORE_TRUNC))
193 && ((bfd_vma)coredata.c_stack + coredata.c_size) != statbuf.st_size)
195 /* If the size is wrong, it means we're misinterpreting something. */
196 bfd_set_error (bfd_error_wrong_format);
197 return NULL;
200 /* Sanity check on the c_tab field. */
201 if ((u_long) coredata.c_tab < sizeof coredata ||
202 (u_long) coredata.c_tab >= statbuf.st_size ||
203 (long) coredata.c_tab >= (long)coredata.c_stack)
205 bfd_set_error (bfd_error_wrong_format);
206 return NULL;
209 /* Issue warning if the core file was truncated during writing. */
210 if (coredata.c_flag & CORE_TRUNC)
211 (*_bfd_error_handler) (_("%s: warning core file truncated"),
212 bfd_get_filename (abfd));
214 /* Allocate core file header. */
215 tmpptr = (char*) bfd_zalloc (abfd, sizeof (Rs6kCorData));
216 if (!tmpptr)
217 return NULL;
219 set_tdata (abfd, tmpptr);
221 /* Copy core file header. */
222 core_hdr (abfd) = coredata;
224 /* .stack section. */
225 if (!make_bfd_asection (abfd, ".stack",
226 SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
227 (bfd_size_type) coredata.c_size,
228 (bfd_vma) (STACK_END_ADDR - coredata.c_size),
229 (file_ptr) coredata.c_stack))
230 return NULL;
232 /* .reg section for GPRs and special registers. */
233 if (!make_bfd_asection (abfd, ".reg",
234 SEC_HAS_CONTENTS,
235 (bfd_size_type) ((32 + NUM_OF_SPEC_REGS) * 4),
236 (bfd_vma) 0,
237 (file_ptr) ((char *) &coredata.SAVE_FIELD
238 - (char *) &coredata)))
239 return NULL;
241 /* .reg2 section for FPRs (floating point registers). */
242 if (!make_bfd_asection (abfd, ".reg2",
243 SEC_HAS_CONTENTS,
244 (bfd_size_type) 8 * 32, /* 32 FPRs. */
245 (bfd_vma) 0,
246 (file_ptr) ((char *) &coredata.SAVE_FIELD.fpr[0]
247 - (char *) &coredata)))
248 return NULL;
250 /* .ldinfo section.
251 To actually find out how long this section is in this particular
252 core dump would require going down the whole list of struct ld_info's.
253 See if we can just fake it. */
254 if (!make_bfd_asection (abfd, ".ldinfo",
255 SEC_HAS_CONTENTS,
256 (bfd_size_type) 0x7fffffff,
257 (bfd_vma) 0,
258 (file_ptr) coredata.c_tab))
259 return NULL;
261 #ifndef CORE_VERSION_1
262 /* .data section if present.
263 AIX 3 dumps the complete data section and sets FULL_CORE if the
264 ulimit is large enough, otherwise the data section is omitted.
265 AIX 4 sets FULL_CORE even if the core file is truncated, we have
266 to examine coredata.c_datasize below to find out the actual size of
267 the .data section. */
268 if (coredata.c_flag & FULL_CORE)
270 if (!make_bfd_asection (abfd, ".data",
271 SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
272 (bfd_size_type) coredata.CORE_DATA_SIZE_FIELD,
273 (bfd_vma)
274 CDATA_ADDR (coredata.CORE_DATA_SIZE_FIELD),
275 (file_ptr) coredata.c_stack + coredata.c_size))
276 return NULL;
278 #endif
280 #ifdef CORE_VERSION_1
281 /* AIX 4 adds data sections from loaded objects to the core file,
282 which can be found by examining ldinfo, and anonymously mmapped
283 regions. */
285 struct ld_info ldinfo;
286 bfd_size_type ldinfo_size;
287 file_ptr ldinfo_offset = (file_ptr) coredata.c_tab;
289 /* .data section from executable. */
290 if (coredata.c_datasize)
292 if (!make_bfd_asection (abfd, ".data",
293 SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
294 (bfd_size_type) coredata.c_datasize,
295 (bfd_vma)
296 CDATA_ADDR (coredata.CORE_DATA_SIZE_FIELD),
297 (file_ptr) coredata.c_data))
298 return NULL;
301 /* .data sections from loaded objects. */
302 ldinfo_size = (char *) &ldinfo.ldinfo_filename[0]
303 - (char *) &ldinfo.ldinfo_next;
304 while (1)
306 if (bfd_seek (abfd, ldinfo_offset, SEEK_SET) != 0)
307 return NULL;
308 if (bfd_read (&ldinfo, ldinfo_size, 1, abfd) != ldinfo_size)
309 return NULL;
310 if (ldinfo.ldinfo_core)
312 if (!make_bfd_asection (abfd, ".data",
313 SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
314 (bfd_size_type) ldinfo.ldinfo_datasize,
315 (bfd_vma) ldinfo.ldinfo_dataorg,
316 (file_ptr) ldinfo.ldinfo_core))
317 return NULL;
319 if (ldinfo.ldinfo_next == 0)
320 break;
321 ldinfo_offset += ldinfo.ldinfo_next;
324 /* .vmdata sections from anonymously mmapped regions. */
325 if (coredata.c_vmregions)
327 int i;
329 if (bfd_seek (abfd, (file_ptr) coredata.c_vmm, SEEK_SET) != 0)
330 return NULL;
332 for (i = 0; i < coredata.c_vmregions; i++)
334 struct vm_info vminfo;
336 if (bfd_read (&vminfo, sizeof (vminfo), 1, abfd) != sizeof (vminfo))
337 return NULL;
338 if (vminfo.vminfo_offset)
340 if (!make_bfd_asection (abfd, ".vmdata",
341 SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS,
342 (bfd_size_type) vminfo.vminfo_size,
343 (bfd_vma) vminfo.vminfo_addr,
344 (file_ptr) vminfo.vminfo_offset))
345 return NULL;
350 #endif
352 return abfd->xvec; /* this is garbage for now. */
357 /* return `true' if given core is from the given executable.. */
358 boolean
359 rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd)
360 bfd *core_bfd;
361 bfd *exec_bfd;
363 struct core_dump coredata;
364 struct ld_info ldinfo;
365 bfd_size_type size;
366 char *path, *s;
367 size_t alloc;
368 const char *str1, *str2;
369 boolean ret;
371 if (bfd_seek (core_bfd, 0, SEEK_SET) != 0
372 || bfd_read (&coredata, sizeof coredata, 1, core_bfd) != sizeof coredata)
373 return false;
375 if (bfd_seek (core_bfd, (long) coredata.c_tab, SEEK_SET) != 0)
376 return false;
378 size = (char *) &ldinfo.ldinfo_filename[0] - (char *) &ldinfo.ldinfo_next;
379 if (bfd_read (&ldinfo, size, 1, core_bfd) != size)
380 return false;
382 alloc = 100;
383 path = bfd_malloc (alloc);
384 if (path == NULL)
385 return false;
386 s = path;
388 while (1)
390 if (bfd_read (s, 1, 1, core_bfd) != 1)
392 free (path);
393 return false;
395 if (*s == '\0')
396 break;
397 ++s;
398 if (s == path + alloc)
400 char *n;
402 alloc *= 2;
403 n = bfd_realloc (path, alloc);
404 if (n == NULL)
406 free (path);
407 return false;
409 s = n + (path - s);
410 path = n;
414 str1 = strrchr (path, '/');
415 str2 = strrchr (exec_bfd->filename, '/');
417 /* step over character '/' */
418 str1 = str1 != NULL ? str1 + 1 : path;
419 str2 = str2 != NULL ? str2 + 1 : exec_bfd->filename;
421 if (strcmp (str1, str2) == 0)
422 ret = true;
423 else
424 ret = false;
426 free (path);
428 return ret;
431 char *
432 rs6000coff_core_file_failing_command (abfd)
433 bfd *abfd;
435 char *com = core_hdr (abfd).CORE_COMM_FIELD;
436 if (*com)
437 return com;
438 else
439 return 0;
443 rs6000coff_core_file_failing_signal (abfd)
444 bfd *abfd;
446 return core_hdr (abfd).c_signo;
450 boolean
451 rs6000coff_get_section_contents (abfd, section, location, offset, count)
452 bfd *abfd;
453 sec_ptr section;
454 PTR location;
455 file_ptr offset;
456 bfd_size_type count;
458 if (count == 0)
459 return true;
461 /* Reading a core file's sections will be slightly different. For the
462 rest of them we can use bfd_generic_get_section_contents () I suppose. */
463 /* Make sure this routine works for any bfd and any section. FIXMEmgo. */
465 if (abfd->format == bfd_core && strcmp (section->name, ".reg") == 0) {
467 struct mstsave mstatus;
468 int regoffset = (char*)&mstatus.gpr[0] - (char*)&mstatus;
470 /* Assert that the only way this code will be executed is reading the
471 whole section. */
472 if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS)))
473 (*_bfd_error_handler)
474 (_("ERROR! in rs6000coff_get_section_contents()\n"));
476 /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure
477 in the core file. */
479 /* read GPR's into the location. */
480 if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1
481 || bfd_read(location, sizeof (mstatus.gpr), 1, abfd) != sizeof (mstatus.gpr))
482 return (false); /* on error */
484 /* increment location to the beginning of special registers in the section,
485 reset register offset value to the beginning of first special register
486 in mstsave structure, and read special registers. */
488 location = (PTR) ((char*)location + sizeof (mstatus.gpr));
489 regoffset = (char*)&mstatus.iar - (char*)&mstatus;
491 if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1
492 || bfd_read(location, 4 * NUM_OF_SPEC_REGS, 1, abfd) !=
493 4 * NUM_OF_SPEC_REGS)
494 return (false); /* on error */
496 /* increment location address, and read the special registers.. */
497 /* FIXMEmgo */
498 return (true);
501 /* else, use default bfd section content transfer. */
502 else
503 return _bfd_generic_get_section_contents
504 (abfd, section, location, offset, count);
507 #endif /* AIX_CORE */