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
8 Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
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)
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. */
61 #define AOUTHDR second_AOUTHDR
66 /* ------------------------------------------------------------------------ */
67 /* Support for core file stuff.. */
68 /* ------------------------------------------------------------------------ */
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
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
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
101 /* These are stored in the bfd's tdata */
103 struct core_dump hdr
; /* core file header */
106 static asection
*make_bfd_asection
PARAMS ((bfd
*, CONST
char *, flagword
,
107 bfd_size_type
, bfd_vma
, file_ptr
));
110 make_bfd_asection (abfd
, name
, flags
, _raw_size
, vma
, filepos
)
114 bfd_size_type _raw_size
;
120 asect
= bfd_make_section_anyway (abfd
, name
);
124 asect
->flags
= flags
;
125 asect
->_raw_size
= _raw_size
;
127 asect
->filepos
= filepos
;
128 asect
->alignment_power
= 8;
133 /* Decide if a given bfd represents a `core' file or not. There really is no
134 magic number or anything like, in rs6000coff. */
137 rs6000coff_core_p (abfd
)
140 struct core_dump coredata
;
145 if (bfd_seek (abfd
, 0, SEEK_SET
) != 0)
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
);
156 if (bfd_stat (abfd
, &statbuf
) < 0)
158 bfd_set_error (bfd_error_system_call
);
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
177 if (!(coredata
.c_flag
& UBLOCK_VALID
)
178 || !(coredata
.c_flag
& LE_VALID
))
180 bfd_set_error (bfd_error_wrong_format
);
184 if (!(coredata
.c_flag
& USTACK_VALID
))
186 bfd_set_error (bfd_error_file_truncated
);
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
);
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
);
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
));
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
))
232 /* .reg section for GPRs and special registers. */
233 if (!make_bfd_asection (abfd
, ".reg",
235 (bfd_size_type
) ((32 + NUM_OF_SPEC_REGS
) * 4),
237 (file_ptr
) ((char *) &coredata
.SAVE_FIELD
238 - (char *) &coredata
)))
241 /* .reg2 section for FPRs (floating point registers). */
242 if (!make_bfd_asection (abfd
, ".reg2",
244 (bfd_size_type
) 8 * 32, /* 32 FPRs. */
246 (file_ptr
) ((char *) &coredata
.SAVE_FIELD
.fpr
[0]
247 - (char *) &coredata
)))
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",
256 (bfd_size_type
) 0x7fffffff,
258 (file_ptr
) coredata
.c_tab
))
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
,
274 CDATA_ADDR (coredata
.CORE_DATA_SIZE_FIELD
),
275 (file_ptr
) coredata
.c_stack
+ coredata
.c_size
))
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
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
,
296 CDATA_ADDR (coredata
.CORE_DATA_SIZE_FIELD
),
297 (file_ptr
) coredata
.c_data
))
301 /* .data sections from loaded objects. */
302 ldinfo_size
= (char *) &ldinfo
.ldinfo_filename
[0]
303 - (char *) &ldinfo
.ldinfo_next
;
306 if (bfd_seek (abfd
, ldinfo_offset
, SEEK_SET
) != 0)
308 if (bfd_read (&ldinfo
, ldinfo_size
, 1, abfd
) != ldinfo_size
)
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
))
319 if (ldinfo
.ldinfo_next
== 0)
321 ldinfo_offset
+= ldinfo
.ldinfo_next
;
324 /* .vmdata sections from anonymously mmapped regions. */
325 if (coredata
.c_vmregions
)
329 if (bfd_seek (abfd
, (file_ptr
) coredata
.c_vmm
, SEEK_SET
) != 0)
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
))
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
))
352 return abfd
->xvec
; /* this is garbage for now. */
357 /* return `true' if given core is from the given executable.. */
359 rs6000coff_core_file_matches_executable_p (core_bfd
, exec_bfd
)
363 struct core_dump coredata
;
364 struct ld_info ldinfo
;
368 const char *str1
, *str2
;
371 if (bfd_seek (core_bfd
, 0, SEEK_SET
) != 0
372 || bfd_read (&coredata
, sizeof coredata
, 1, core_bfd
) != sizeof coredata
)
375 if (bfd_seek (core_bfd
, (long) coredata
.c_tab
, SEEK_SET
) != 0)
378 size
= (char *) &ldinfo
.ldinfo_filename
[0] - (char *) &ldinfo
.ldinfo_next
;
379 if (bfd_read (&ldinfo
, size
, 1, core_bfd
) != size
)
383 path
= bfd_malloc (alloc
);
390 if (bfd_read (s
, 1, 1, core_bfd
) != 1)
398 if (s
== path
+ alloc
)
403 n
= bfd_realloc (path
, alloc
);
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)
432 rs6000coff_core_file_failing_command (abfd
)
435 char *com
= core_hdr (abfd
).CORE_COMM_FIELD
;
443 rs6000coff_core_file_failing_signal (abfd
)
446 return core_hdr (abfd
).c_signo
;
451 rs6000coff_get_section_contents (abfd
, section
, location
, offset
, count
)
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
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
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.. */
501 /* else, use default bfd section content transfer. */
503 return _bfd_generic_get_section_contents
504 (abfd
, section
, location
, offset
, count
);
507 #endif /* AIX_CORE */