1 /* IBM RS/6000 "XCOFF" back-end for BFD.
2 Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3 Written by Metin G. Ozisik, Mimi Phûông-Thåo Võ, and John Gilmore.
4 Archive support from Damon A. Permezel.
5 Contributed by IBM Corporation and Cygnus Support.
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
23 /* This port currently only handles reading object files, except when
24 compiled on an RS/6000 host. -- no archive support, no core files.
25 In all cases, it does not support writing.
27 FIXMEmgo comments are left from Metin Ozisik's original port. */
29 /* Internalcoff.h and coffcode.h modify themselves based on this flag. */
30 #define RS6000COFF_C 1
36 #include "internalcoff.h"
37 #include "coff-rs6000.h"
40 /* The main body of code is in coffcode.h. */
42 /* Can't read rs6000 relocs */
43 #define RTYPE2HOWTO(a,b)
46 #define coff_archive_p bfd_generic_archive_p
47 #define coff_mkarchive _bfd_generic_mkarchive
49 #ifdef ARCHIVES_PLEASE
51 /* ------------------------------------------------------------------------ */
52 /* Support for archive file stuff.. */
53 /* Stolen from Damon A. Permezel's `bfd' portation. */
54 /* ------------------------------------------------------------------------ */
56 #undef coff_openr_next_archived_file
57 #define coff_openr_next_archived_file rs6000coff_openr_next_archived_file
59 #undef coff_write_armap
60 #define coff_write_armap rs6000coff_write_armap
62 #undef coff_stat_arch_elt
63 #define coff_stat_arch_elt rs6000coff_stat_arch_elt
65 #undef coff_snarf_ar_hdr
66 #define coff_snarf_ar_hdr rs6000coff_snarf_ar_hdr
69 #define coff_mkarchive rs6000coff_mkarchive
72 #define coff_archive_p rs6000coff_archive_p
74 #include "/usr/include/ar.h" /* <ar.h> doesn't do it. */
77 #define arch_hdr(bfd) \
79 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
83 rs6000coff_mkarchive (abfd
)
86 bfd_error
= invalid_operation
; /* write not supported */
90 /* This functions reads an arch header and returns an areltdata pointer, or
93 Presumes the file pointer is already in the right place (ie pointing
94 to the ar_hdr in the file). Moves the file pointer; on success it
95 should be pointing to the front of the file contents; on failure it
96 could have been moved arbitrarily.
100 rs6000coff_snarf_ar_hdr (abfd
)
110 struct areltdata
*ared
;
111 unsigned int namelen
= 0;
114 size
= sizeof (h
.hdr
);
115 if (bfd_read(&h
.hdr
, 1, size
, abfd
) != size
) {
116 bfd_error
= no_more_archived_files
;
119 size
= atoi(h
.hdr
.ar_namlen
); /* ar_name[] length */
122 if (bfd_read(&h
.hdr
._ar_name
.ar_name
[2], 1, size
, abfd
) != size
) {
123 bfd_error
= no_more_archived_files
;
127 if (strncmp(h
.hdr
._ar_name
.ar_fmag
+ size
, AIAFMAG
, 2)) {
128 bfd_error
= malformed_archive
;
132 h
.hdr
._ar_name
.ar_name
[size
] = 0; /* terminate filename */
135 * if the filename is NULL, we're (probably) at the end.
138 bfd_error
= no_more_archived_files
;
142 size
+= sizeof (h
.hdr
);
143 allocptr
= bfd_zalloc(abfd
, sizeof (*ared
) + size
);
145 if (allocptr
== NULL
) {
146 bfd_error
= no_memory
;
150 ared
= (struct areltdata
*) allocptr
;
152 ared
->arch_header
= (void *) (allocptr
+ sizeof (struct areltdata
));
153 memcpy ((char *) ared
->arch_header
, &h
.hdr
, size
);
154 ared
->parsed_size
= atoi(h
.hdr
.ar_size
);
155 ared
->filename
= ((AR_HDR
*) ared
->arch_header
)->_ar_name
.ar_name
;
160 /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
161 Why wasn't this part of the transfer vector? */
164 rs6000coff_get_elt_at_filepos (archive
, filepos
)
168 struct areltdata
*new_areldata
;
171 n_nfd
= look_for_bfd_in_cache (archive
, filepos
);
172 if (n_nfd
) return n_nfd
;
174 if (0 > bfd_seek (archive
, filepos
, SEEK_SET
)) {
175 bfd_error
= system_call_error
;
179 if ((new_areldata
= rs6000coff_snarf_ar_hdr (archive
)) == NULL
) return NULL
;
181 n_nfd
= _bfd_create_empty_archive_element_shell (archive
);
183 bfd_release (archive
, (PTR
)new_areldata
);
186 n_nfd
->origin
= bfd_tell (archive
);
187 n_nfd
->arelt_data
= (PTR
) new_areldata
;
188 n_nfd
->filename
= new_areldata
->filename
;
190 if (add_bfd_to_cache (archive
, filepos
, n_nfd
))
194 bfd_release (archive
, (PTR
)n_nfd
);
195 bfd_release (archive
, (PTR
)new_areldata
);
200 * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs.
203 rs6000coff_openr_next_archived_file(archive
, last_file
)
204 bfd
*archive
, *last_file
;
209 filestart
= bfd_ardata(archive
)->first_file_filepos
;
211 filestart
= atol(arch_hdr(last_file
)->ar_nxtmem
);
213 return rs6000coff_get_elt_at_filepos (archive
, filestart
);
218 rs6000coff_archive_p (abfd
)
222 register struct artdata
*art
;
224 if (bfd_read (&hdr
, sizeof (hdr
), 1, abfd
) != sizeof (hdr
)) {
225 bfd_error
= wrong_format
;
229 if (strncmp(hdr
.fl_magic
, AIAMAG
, SAIAMAG
)) {
230 bfd_error
= wrong_format
;
235 * bfd_ardata() accesses the bfd->tdata field.
237 abfd
->tdata
= (void *) bfd_zalloc(abfd
, sizeof (*art
) + sizeof (hdr
));
238 if ((art
= bfd_ardata (abfd
)) == NULL
) {
239 bfd_error
= no_memory
;
243 art
->first_file_filepos
= atoi(hdr
.fl_fstmoff
);
244 *(struct fl_hdr
*) (1 + art
) = hdr
;
247 * slurp in the member table, which I think is the armap equivalent.
248 xcoff_slurp_armap(abfd);
256 rs6000coff_stat_arch_elt(abfd
, buf
)
263 if (abfd
->arelt_data
== NULL
) {
264 bfd_error
= invalid_operation
;
268 hdr
= arch_hdr (abfd
);
270 #define foo(arelt, stelt, size) \
271 buf->stelt = strtol (hdr->arelt, &aloser, size); \
272 if (aloser == hdr->arelt) return -1;
274 foo (ar_date
, st_mtime
, 10);
275 foo (ar_uid
, st_uid
, 10);
276 foo (ar_gid
, st_gid
, 10);
277 foo (ar_mode
, st_mode
, 8);
278 foo (ar_size
, st_size
, 10);
285 rs6000coff_write_armap (arch
, elength
, map
, orl_count
, stridx
)
287 unsigned int elength
;
290 bfd_error
= invalid_operation
;
293 #endif /* ARCHIVES_PLEASE */
295 #ifdef COREFILES_PLEASE
297 #undef coff_core_file_matches_executable_p
298 #define coff_core_file_matches_executable_p \
299 rs6000coff_core_file_matches_executable_p
301 #undef coff_get_section_contents
302 #define coff_get_section_contents rs6000coff_get_section_contents
305 /* AOUTHDR is defined by the above. We need another defn of it, from the
306 system include files. Punt the old one and get us a new name for the
307 typedef in the system include files. */
311 #define AOUTHDR second_AOUTHDR
316 /* ------------------------------------------------------------------------ */
317 /* Support for core file stuff.. */
318 /* ------------------------------------------------------------------------ */
320 #include <sys/user.h>
322 #include <sys/core.h>
325 /* Number of special purpose registers supported by gdb. This value
326 should match `tm.h' in gdb directory. Clean this mess up and use
327 the macros in sys/reg.h. FIXMEmgo. */
329 #define NUM_OF_SPEC_REGS 7
330 #define STACK_END_ADDR 0x2ff80000
332 #define core_hdr(bfd) (((Rs6kCorData*)(bfd->tdata))->hdr)
333 #define core_datasec(bfd) (((Rs6kCorData*)(bfd->tdata))->data_section)
334 #define core_stacksec(bfd) (((Rs6kCorData*)(bfd->tdata))->stack_section)
335 #define core_regsec(bfd) (((Rs6kCorData*)(bfd->tdata))->reg_section)
336 #define core_reg2sec(bfd) (((Rs6kCorData*)(bfd->tdata))->reg2_section)
338 /* These are stored in the bfd's tdata */
340 struct core
*hdr
; /* core file header */
341 asection
*data_section
,
343 *reg_section
, /* section for GPRs and special registers. */
344 *reg2_section
; /* section for FPRs. */
348 /* Decide if a given bfd represents a `core' file or not. There really is no
349 magic number or anything like, in rs6000coff. */
352 rs6000coff_core_p (abfd
)
356 struct core_dump coredata
;
360 /* Use bfd_xxx routines, rather than O/S primitives to read coredata. FIXMEmgo */
361 fd
= open (abfd
->filename
, O_RDONLY
);
363 fstat (fd
, &statbuf
);
364 read (fd
, &coredata
, sizeof (struct core_dump
));
368 if (coredata
.c_tab
< (sizeof (coredata
.c_u
) + (int)&coredata
.c_u
- (int)&coredata
.c_signo
) ||
369 coredata
.c_tab
>= statbuf
.st_size
||
370 (long)coredata
.c_stack
<= (long)coredata
.c_tab
) {
375 If it looks like core file, then.....
376 read core file header..... (maybe you've done it above..)
379 /* maybe you should alloc space for the whole core chunk over here!! FIXMEmgo */
380 tmpptr
= (char*)bfd_zalloc (abfd
, sizeof (Rs6kCorData
));
381 set_tdata (abfd
, tmpptr
);
383 /* .stack section. */
384 if ((core_stacksec (abfd
) = (asection
*) bfd_zalloc (abfd
, sizeof (asection
)))
386 bfd_error
= no_memory
;
387 /* bfd_release (abfd, ???? ) */
390 core_stacksec (abfd
)->name
= ".stack";
391 core_stacksec (abfd
)->flags
= SEC_ALLOC
+ SEC_LOAD
;
392 core_stacksec (abfd
)->size
= coredata
.c_size
;
393 core_stacksec (abfd
)->vma
= STACK_END_ADDR
- coredata
.c_size
;
394 core_stacksec (abfd
)->filepos
= coredata
.c_stack
; /*???? */
396 /* .reg section for GPRs and special registers. */
397 if ((core_regsec (abfd
) = (asection
*) bfd_zalloc (abfd
, sizeof (asection
)))
399 bfd_error
= no_memory
;
400 /* bfd_release (abfd, ???? ) */
403 core_regsec (abfd
)->name
= ".reg";
404 core_regsec (abfd
)->flags
= SEC_ALLOC
;
405 core_regsec (abfd
)->size
= (32 + NUM_OF_SPEC_REGS
) * 4;
406 core_regsec (abfd
)->vma
= NULL
; /* not used?? */
407 core_regsec (abfd
)->filepos
=
408 (char*)&coredata
.c_u
.u_save
- (char*)&coredata
;
410 /* .reg2 section for FPRs (floating point registers). */
411 if ((core_reg2sec (abfd
) = (asection
*) bfd_zalloc (abfd
, sizeof (asection
)))
413 bfd_error
= no_memory
;
414 /* bfd_release (abfd, ???? ) */
417 core_reg2sec (abfd
)->name
= ".reg2";
418 core_reg2sec (abfd
)->flags
= SEC_ALLOC
;
419 core_reg2sec (abfd
)->size
= 8 * 32; /* 32 FPRs. */
420 core_reg2sec (abfd
)->vma
= NULL
; /* not used?? */
421 core_reg2sec (abfd
)->filepos
=
422 (char*)&coredata
.c_u
.u_save
.fpr
[0] - (char*)&coredata
;
424 /* set up section chain here. */
425 abfd
->section_count
= 3;
426 abfd
->sections
= core_stacksec (abfd
);
427 core_stacksec (abfd
)->next
= core_regsec(abfd
);
428 core_regsec (abfd
)->next
= core_reg2sec (abfd
);
429 core_reg2sec (abfd
)->next
= NULL
;
431 return abfd
->xvec
; /* this is garbage for now. */
436 /* return `true' if given core is from the given executable.. */
438 rs6000coff_core_file_matches_executable_p (core_bfd
, exec_bfd
)
443 struct core_dump coredata
;
444 struct ld_info ldinfo
;
445 char pathname
[1024];
448 /* Use bfd_xxx routines, rather than O/S primitives, do error checking!!
450 fd
= fopen (core_bfd
->filename
, "r");
452 fread (&coredata
, sizeof (struct core_dump
), 1, fd
);
453 fseek (fd
, (long)coredata
.c_tab
, 0);
454 fread (&ldinfo
, (char*)&ldinfo
.ldinfo_filename
[0] - (char*)&ldinfo
.ldinfo_next
,
456 fscanf (fd
, "%s", pathname
);
457 printf ("path: %s\n", pathname
);
459 str1
= strrchr (pathname
, '/');
460 str2
= strrchr (exec_bfd
->filename
, '/');
462 /* step over character '/' */
463 str1
= str1
? str1
+1 : &pathname
[0];
464 str2
= str2
? str2
+1 : exec_bfd
->filename
;
467 return strcmp (str1
, str2
);
472 rs6000coff_get_section_contents (abfd
, section
, location
, offset
, count
)
482 /* Reading a core file's sections will be slightly different. For the
483 rest of them we can use bfd_generic_get_section_contents () I suppose. */
484 /* Make sure this routine works for any bfd and any section. FIXMEmgo. */
486 if (abfd
->format
== bfd_core
&& strcmp (section
->name
, ".reg") == 0) {
488 struct mstsave mstatus
;
489 int regoffset
= (char*)&mstatus
.gpr
[0] - (char*)&mstatus
;
491 /* Assert that the only way this code will be executed is reading the
493 if (offset
|| count
!= (sizeof(mstatus
.gpr
) + (4 * NUM_OF_SPEC_REGS
)))
494 printf ("ERROR! in rs6000coff_get_section_contents()\n");
496 /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure
499 /* read GPR's into the location. */
500 if ( bfd_seek(abfd
, section
->filepos
+ regoffset
, SEEK_SET
) == -1
501 || bfd_read(location
, sizeof (mstatus
.gpr
), 1, abfd
) != sizeof (mstatus
.gpr
))
502 return (false); /* on error */
504 /* increment location to the beginning of special registers in the section,
505 reset register offset value to the beginning of first special register
506 in mstsave structure, and read special registers. */
508 location
= (PTR
) ((char*)location
+ sizeof (mstatus
.gpr
));
509 regoffset
= (char*)&mstatus
.iar
- (char*)&mstatus
;
511 if ( bfd_seek(abfd
, section
->filepos
+ regoffset
, SEEK_SET
) == -1
512 || bfd_read(location
, 4 * NUM_OF_SPEC_REGS
, 1, abfd
) !=
513 4 * NUM_OF_SPEC_REGS
)
514 return (false); /* on error */
516 /* increment location address, and read the special registers.. */
521 /* else, use default bfd section content transfer. */
523 return bfd_generic_get_section_contents
524 (abfd
, section
, location
, offset
, count
);
527 #endif /* COREFILES_PLEASE */
529 /* The transfer vector that leads the outside world to all of the above. */
531 bfd_target rs6000coff_vec
=
533 "aixcoff-rs6000", /* name */
534 bfd_target_coff_flavour
,
535 true, /* data byte order is big */
536 true, /* header byte order is big */
538 (HAS_RELOC
| EXEC_P
| /* object flags */
539 HAS_LINENO
| HAS_DEBUG
|
540 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
),
542 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
543 '/', /* ar_pad_char */
544 15, /* ar_max_namelen??? FIXMEmgo */
545 3, /* default alignment power */
547 _do_getb64
, _do_putb64
, _do_getb32
, _do_putb32
, _do_getb16
, _do_putb16
, /* data */
548 _do_getb64
, _do_putb64
, _do_getb32
, _do_putb32
, _do_getb16
, _do_putb16
, /* hdrs */
550 {_bfd_dummy_target
, coff_object_p
, /* bfd_check_format */
551 coff_archive_p
, _bfd_dummy_target
},
552 {bfd_false
, coff_mkobject
, coff_mkarchive
, /* bfd_set_format */
554 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
555 _bfd_write_archive_contents
, bfd_false
},