1 /* BFD back-end for IBM RS/6000 "XCOFF" files.
2 Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3 FIXME: Can someone provide a transliteration of this name into ASCII?
4 Using the following chars caused a compiler warning on HIUX (so I replaced
5 them with octal escapes), and isn't useful without an understanding of what
7 Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
9 Archive support from Damon A. Permezel.
10 Contributed by IBM Corporation and Cygnus Support.
12 This file is part of BFD, the Binary File Descriptor library.
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
28 /* This port currently only handles reading object files, except when
29 compiled on an RS/6000 host. -- no archive support, no core files.
30 In all cases, it does not support writing.
32 FIXMEmgo comments are left from Metin Ozisik's original port. */
34 /* Internalcoff.h and coffcode.h modify themselves based on this flag. */
35 #define RS6000COFF_C 1
41 #include "coff/internal.h"
42 #include "coff/rs6000.h"
45 /* The main body of code is in coffcode.h. */
47 /* The XCOFF reloc table. Actually, XCOFF relocations specify the
48 bitsize and whether they are signed or not, along with a
49 conventional type. This table is for the types, which are used for
50 different algorithms for putting in the reloc. Many of these
51 relocs need special_function entries, which I have not written. */
53 static reloc_howto_type rs6000coff_howto_table
[] =
55 /* Standard 32 bit relocation. */
58 2, /* size (0 = byte, 1 = short, 2 = long) */
60 false, /* pc_relative */
62 complain_overflow_bitfield
, /* complain_on_overflow */
63 0, /* special_function */
65 true, /* partial_inplace */
66 0xffffffff, /* src_mask */
67 0xffffffff, /* dst_mask */
68 false), /* pcrel_offset */
70 /* 32 bit relocation, but store negative value. */
73 -2, /* size (0 = byte, 1 = short, 2 = long) */
75 false, /* pc_relative */
77 complain_overflow_bitfield
, /* complain_on_overflow */
78 0, /* special_function */
80 true, /* partial_inplace */
81 0xffffffff, /* src_mask */
82 0xffffffff, /* dst_mask */
83 false), /* pcrel_offset */
85 /* 32 bit PC relative relocation. */
88 2, /* size (0 = byte, 1 = short, 2 = long) */
90 true, /* pc_relative */
92 complain_overflow_signed
, /* complain_on_overflow */
93 0, /* special_function */
95 true, /* partial_inplace */
96 0xffffffff, /* src_mask */
97 0xffffffff, /* dst_mask */
98 false), /* pcrel_offset */
100 /* 16 bit TOC relative relocation. */
103 1, /* size (0 = byte, 1 = short, 2 = long) */
105 false, /* pc_relative */
107 complain_overflow_signed
, /* complain_on_overflow */
108 0, /* special_function */
110 true, /* partial_inplace */
111 0xffff, /* src_mask */
112 0xffff, /* dst_mask */
113 false), /* pcrel_offset */
115 /* I don't really know what this is. */
118 2, /* size (0 = byte, 1 = short, 2 = long) */
120 false, /* pc_relative */
122 complain_overflow_bitfield
, /* complain_on_overflow */
123 0, /* special_function */
125 true, /* partial_inplace */
126 0xffffffff, /* src_mask */
127 0xffffffff, /* dst_mask */
128 false), /* pcrel_offset */
130 /* External TOC relative symbol. */
133 2, /* size (0 = byte, 1 = short, 2 = long) */
135 false, /* pc_relative */
137 complain_overflow_bitfield
, /* complain_on_overflow */
138 0, /* special_function */
140 true, /* partial_inplace */
141 0xffff, /* src_mask */
142 0xffff, /* dst_mask */
143 false), /* pcrel_offset */
145 /* Local TOC relative symbol. */
148 2, /* size (0 = byte, 1 = short, 2 = long) */
150 false, /* pc_relative */
152 complain_overflow_bitfield
, /* complain_on_overflow */
153 0, /* special_function */
155 true, /* partial_inplace */
156 0xffff, /* src_mask */
157 0xffff, /* dst_mask */
158 false), /* pcrel_offset */
162 /* Non modifiable absolute branch. */
165 2, /* size (0 = byte, 1 = short, 2 = long) */
167 false, /* pc_relative */
169 complain_overflow_bitfield
, /* complain_on_overflow */
170 0, /* special_function */
172 true, /* partial_inplace */
173 0x3fffffc, /* src_mask */
174 0x3fffffc, /* dst_mask */
175 false), /* pcrel_offset */
179 /* Non modifiable relative branch. */
180 HOWTO (0xa, /* type */
182 2, /* size (0 = byte, 1 = short, 2 = long) */
184 true, /* pc_relative */
186 complain_overflow_signed
, /* complain_on_overflow */
187 0, /* special_function */
189 true, /* partial_inplace */
190 0x3fffffc, /* src_mask */
191 0x3fffffc, /* dst_mask */
192 false), /* pcrel_offset */
197 HOWTO (0xc, /* type */
199 2, /* size (0 = byte, 1 = short, 2 = long) */
201 false, /* pc_relative */
203 complain_overflow_bitfield
, /* complain_on_overflow */
204 0, /* special_function */
206 true, /* partial_inplace */
207 0xffff, /* src_mask */
208 0xffff, /* dst_mask */
209 false), /* pcrel_offset */
212 HOWTO (0xd, /* type */
214 2, /* size (0 = byte, 1 = short, 2 = long) */
216 false, /* pc_relative */
218 complain_overflow_bitfield
, /* complain_on_overflow */
219 0, /* special_function */
221 true, /* partial_inplace */
222 0xffff, /* src_mask */
223 0xffff, /* dst_mask */
224 false), /* pcrel_offset */
228 /* Non-relocating reference. */
229 HOWTO (0xf, /* type */
231 2, /* size (0 = byte, 1 = short, 2 = long) */
233 false, /* pc_relative */
235 complain_overflow_bitfield
, /* complain_on_overflow */
236 0, /* special_function */
238 false, /* partial_inplace */
241 false), /* pcrel_offset */
246 /* TOC relative indirect load. */
247 HOWTO (0x12, /* type */
249 2, /* size (0 = byte, 1 = short, 2 = long) */
251 false, /* pc_relative */
253 complain_overflow_bitfield
, /* complain_on_overflow */
254 0, /* special_function */
256 true, /* partial_inplace */
257 0xffff, /* src_mask */
258 0xffff, /* dst_mask */
259 false), /* pcrel_offset */
261 /* TOC relative load address. */
262 HOWTO (0x13, /* type */
264 2, /* size (0 = byte, 1 = short, 2 = long) */
266 false, /* pc_relative */
268 complain_overflow_bitfield
, /* complain_on_overflow */
269 0, /* special_function */
271 true, /* partial_inplace */
272 0xffff, /* src_mask */
273 0xffff, /* dst_mask */
274 false), /* pcrel_offset */
276 /* Modifiable relative branch. */
277 HOWTO (0x14, /* type */
279 2, /* size (0 = byte, 1 = short, 2 = long) */
281 false, /* pc_relative */
283 complain_overflow_bitfield
, /* complain_on_overflow */
284 0, /* special_function */
285 "R_RRTBI", /* name */
286 true, /* partial_inplace */
287 0xffffffff, /* src_mask */
288 0xffffffff, /* dst_mask */
289 false), /* pcrel_offset */
291 /* Modifiable absolute branch. */
292 HOWTO (0x15, /* type */
294 2, /* size (0 = byte, 1 = short, 2 = long) */
296 false, /* pc_relative */
298 complain_overflow_bitfield
, /* complain_on_overflow */
299 0, /* special_function */
300 "R_RRTBA", /* name */
301 true, /* partial_inplace */
302 0xffffffff, /* src_mask */
303 0xffffffff, /* dst_mask */
304 false), /* pcrel_offset */
306 /* Modifiable call absolute indirect. */
307 HOWTO (0x16, /* type */
309 2, /* size (0 = byte, 1 = short, 2 = long) */
311 false, /* pc_relative */
313 complain_overflow_bitfield
, /* complain_on_overflow */
314 0, /* special_function */
316 true, /* partial_inplace */
317 0xffff, /* src_mask */
318 0xffff, /* dst_mask */
319 false), /* pcrel_offset */
321 /* Modifiable call relative. */
322 HOWTO (0x17, /* type */
324 2, /* size (0 = byte, 1 = short, 2 = long) */
326 false, /* pc_relative */
328 complain_overflow_bitfield
, /* complain_on_overflow */
329 0, /* special_function */
331 true, /* partial_inplace */
332 0xffff, /* src_mask */
333 0xffff, /* dst_mask */
334 false), /* pcrel_offset */
336 /* Modifiable branch absolute. */
337 HOWTO (0x18, /* type */
339 2, /* size (0 = byte, 1 = short, 2 = long) */
341 false, /* pc_relative */
343 complain_overflow_bitfield
, /* complain_on_overflow */
344 0, /* special_function */
346 true, /* partial_inplace */
347 0xffff, /* src_mask */
348 0xffff, /* dst_mask */
349 false), /* pcrel_offset */
351 /* Modifiable branch absolute. */
352 HOWTO (0x19, /* type */
354 2, /* size (0 = byte, 1 = short, 2 = long) */
356 false, /* pc_relative */
358 complain_overflow_bitfield
, /* complain_on_overflow */
359 0, /* special_function */
361 true, /* partial_inplace */
362 0xffff, /* src_mask */
363 0xffff, /* dst_mask */
364 false), /* pcrel_offset */
366 /* Modifiable branch relative. */
367 HOWTO (0x1a, /* type */
369 2, /* size (0 = byte, 1 = short, 2 = long) */
371 false, /* pc_relative */
373 complain_overflow_signed
, /* complain_on_overflow */
374 0, /* special_function */
376 true, /* partial_inplace */
377 0xffff, /* src_mask */
378 0xffff, /* dst_mask */
379 false), /* pcrel_offset */
381 /* Modifiable branch absolute. */
382 HOWTO (0x1b, /* type */
384 2, /* size (0 = byte, 1 = short, 2 = long) */
386 false, /* pc_relative */
388 complain_overflow_bitfield
, /* complain_on_overflow */
389 0, /* special_function */
391 true, /* partial_inplace */
392 0xffff, /* src_mask */
393 0xffff, /* dst_mask */
394 false) /* pcrel_offset */
397 #define RTYPE2HOWTO(cache_ptr, dst) rs6000coff_rtype2howto (cache_ptr, dst)
399 static void rs6000coff_rtype2howto
PARAMS ((arelent
*,
400 struct internal_reloc
*));
403 rs6000coff_rtype2howto (relent
, internal
)
405 struct internal_reloc
*internal
;
407 relent
->howto
= rs6000coff_howto_table
+ internal
->r_type
;
409 /* The r_size field of an XCOFF reloc encodes the bitsize of the
410 relocation, as well as indicating whether it is signed or not.
411 Doublecheck that the relocation information gathered from the
412 type matches this information. */
413 if (relent
->howto
->bitsize
!= (internal
->r_size
& 0x1f) + 1)
416 if ((internal
->r_size
& 0x80) != 0
417 ? (relent
->howto
->complain_on_overflow
!= complain_overflow_signed
)
418 : (relent
->howto
->complain_on_overflow
!= complain_overflow_bitfield
))
423 #define coff_bfd_reloc_type_lookup rs6000coff_reloc_type_lookup
425 static const struct reloc_howto_struct
*rs6000coff_reloc_type_lookup
426 PARAMS ((bfd
*, bfd_reloc_code_real_type
));
428 static const struct reloc_howto_struct
*
429 rs6000coff_reloc_type_lookup (abfd
, code
)
431 bfd_reloc_code_real_type code
;
435 case BFD_RELOC_PPC_B26
:
436 return &rs6000coff_howto_table
[0xa];
437 case BFD_RELOC_PPC_BA26
:
438 return &rs6000coff_howto_table
[8];
439 case BFD_RELOC_PPC_TOC16
:
440 return &rs6000coff_howto_table
[3];
442 return &rs6000coff_howto_table
[0];
448 #define SELECT_RELOC(internal, howto) \
450 internal.r_type = howto->type; \
452 ((howto->complain_on_overflow == complain_overflow_signed \
455 | (howto->bitsize - 1)); \
458 #define COFF_LONG_FILENAMES
460 #include "coffcode.h"
462 #define coff_archive_p bfd_generic_archive_p
463 #define coff_mkarchive _bfd_generic_mkarchive
467 /* ------------------------------------------------------------------------ */
468 /* Support for archive file stuff.. */
469 /* Stolen from Damon A. Permezel's `bfd' portation. */
470 /* ------------------------------------------------------------------------ */
472 #undef coff_openr_next_archived_file
473 #define coff_openr_next_archived_file rs6000coff_openr_next_archived_file
475 #undef coff_write_armap
476 #define coff_write_armap rs6000coff_write_armap
478 #undef coff_stat_arch_elt
479 #define coff_stat_arch_elt rs6000coff_stat_arch_elt
481 #undef coff_snarf_ar_hdr
482 #define coff_snarf_ar_hdr rs6000coff_snarf_ar_hdr
484 #undef coff_mkarchive
485 #define coff_mkarchive rs6000coff_mkarchive
487 #undef coff_archive_p
488 #define coff_archive_p rs6000coff_archive_p
490 #include "/usr/include/ar.h" /* <ar.h> doesn't do it. */
493 #define arch_hdr(bfd) \
495 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
499 rs6000coff_mkarchive (abfd
)
502 bfd_set_error (bfd_error_invalid_operation
); /* write not supported */
507 /* This functions reads an arch header and returns an areltdata pointer, or
510 Presumes the file pointer is already in the right place (ie pointing
511 to the ar_hdr in the file). Moves the file pointer; on success it
512 should be pointing to the front of the file contents; on failure it
513 could have been moved arbitrarily.
517 rs6000coff_snarf_ar_hdr (abfd
)
525 struct areltdata
*ared
;
528 size
= sizeof (h
.hdr
);
529 if (bfd_read(&h
.hdr
, 1, size
, abfd
) != size
) {
530 if (bfd_get_error () != bfd_error_system_call
)
531 bfd_set_error (bfd_error_no_more_archived_files
);
534 size
= atoi(h
.hdr
.ar_namlen
); /* ar_name[] length */
537 if (bfd_read(&h
.hdr
._ar_name
.ar_name
[2], 1, size
, abfd
) != size
) {
538 if (bfd_get_error () != bfd_error_system_call
)
539 bfd_set_error (bfd_error_no_more_archived_files
);
543 if (strncmp(h
.hdr
._ar_name
.ar_fmag
+ size
, AIAFMAG
, 2)) {
544 bfd_set_error (bfd_error_malformed_archive
);
548 h
.hdr
._ar_name
.ar_name
[size
] = 0; /* terminate filename */
551 * if the filename is NULL, we're (probably) at the end.
554 bfd_set_error (bfd_error_no_more_archived_files
);
558 size
+= sizeof (h
.hdr
);
559 allocptr
= bfd_zalloc(abfd
, sizeof (*ared
) + size
);
561 if (allocptr
== NULL
) {
562 bfd_set_error (bfd_error_no_memory
);
566 ared
= (struct areltdata
*) allocptr
;
568 ared
->arch_header
= (void *) (allocptr
+ sizeof (struct areltdata
));
569 memcpy ((char *) ared
->arch_header
, &h
.hdr
, size
);
570 ared
->parsed_size
= atoi(h
.hdr
.ar_size
);
571 ared
->filename
= ((AR_HDR
*) ared
->arch_header
)->_ar_name
.ar_name
;
576 /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
577 Why wasn't this part of the transfer vector? */
580 rs6000coff_get_elt_at_filepos (archive
, filepos
)
584 struct areltdata
*new_areldata
;
587 n_nfd
= _bfd_look_for_bfd_in_cache (archive
, filepos
);
588 if (n_nfd
) return n_nfd
;
590 if (0 != bfd_seek (archive
, filepos
, SEEK_SET
))
593 if ((new_areldata
= rs6000coff_snarf_ar_hdr (archive
)) == NULL
) return NULL
;
595 n_nfd
= _bfd_create_empty_archive_element_shell (archive
);
597 bfd_release (archive
, (PTR
)new_areldata
);
600 n_nfd
->origin
= bfd_tell (archive
);
601 n_nfd
->arelt_data
= (PTR
) new_areldata
;
602 n_nfd
->filename
= new_areldata
->filename
;
604 if (_bfd_add_bfd_to_archive_cache (archive
, filepos
, n_nfd
))
608 bfd_release (archive
, (PTR
)n_nfd
);
609 bfd_release (archive
, (PTR
)new_areldata
);
614 * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs.
617 rs6000coff_openr_next_archived_file(archive
, last_file
)
618 bfd
*archive
, *last_file
;
623 filestart
= bfd_ardata(archive
)->first_file_filepos
;
625 filestart
= atol(arch_hdr(last_file
)->ar_nxtmem
);
627 return rs6000coff_get_elt_at_filepos (archive
, filestart
);
632 rs6000coff_archive_p (abfd
)
636 register struct artdata
*art
;
638 if (bfd_read (&hdr
, sizeof (hdr
), 1, abfd
) != sizeof (hdr
)) {
639 if (bfd_get_error () != bfd_error_system_call
)
640 bfd_set_error (bfd_error_wrong_format
);
644 if (strncmp(hdr
.fl_magic
, AIAMAG
, SAIAMAG
)) {
645 bfd_set_error (bfd_error_wrong_format
);
650 * bfd_ardata() accesses the bfd->tdata field.
652 abfd
->tdata
.aout_ar_data
=
653 (void *) bfd_zalloc(abfd
, sizeof (*art
) + sizeof (hdr
));
654 if ((art
= bfd_ardata (abfd
)) == NULL
) {
655 bfd_set_error (bfd_error_no_memory
);
659 art
->first_file_filepos
= atoi(hdr
.fl_fstmoff
);
660 *(struct fl_hdr
*) (1 + art
) = hdr
;
663 * slurp in the member table, which I think is the armap equivalent.
664 xcoff_slurp_armap(abfd);
672 rs6000coff_stat_arch_elt(abfd
, buf
)
679 if (abfd
->arelt_data
== NULL
) {
680 bfd_set_error (bfd_error_invalid_operation
);
684 hdr
= arch_hdr (abfd
);
686 #define foo(arelt, stelt, size) \
687 buf->stelt = strtol (hdr->arelt, &aloser, size); \
688 if (aloser == hdr->arelt) return -1;
690 foo (ar_date
, st_mtime
, 10);
691 foo (ar_uid
, st_uid
, 10);
692 foo (ar_gid
, st_gid
, 10);
693 foo (ar_mode
, st_mode
, 8);
694 foo (ar_size
, st_size
, 10);
701 rs6000coff_write_armap (arch
, elength
, map
, orl_count
, stridx
)
703 unsigned int elength
;
705 unsigned int orl_count
;
708 bfd_set_error (bfd_error_invalid_operation
);
711 #endif /* HOST_AIX */
714 #define CORE_FILE_P _bfd_dummy_target
718 #define CORE_FILE_P rs6000coff_core_p
719 extern bfd_target
* rs6000coff_core_p ();
720 extern boolean
rs6000coff_get_section_contents ();
721 extern boolean
rs6000coff_core_file_matches_executable_p ();
723 #undef coff_core_file_matches_executable_p
724 #define coff_core_file_matches_executable_p \
725 rs6000coff_core_file_matches_executable_p
727 #undef coff_get_section_contents
728 #define coff_get_section_contents rs6000coff_get_section_contents
729 #endif /* HOST_AIX */
734 #define CORE_FILE_P lynx_core_file_p
735 extern bfd_target
*lynx_core_file_p
PARAMS ((bfd
*abfd
));
737 extern boolean lynx_core_file_matches_executable_p
PARAMS ((bfd
*core_bfd
,
739 #undef coff_core_file_matches_executable_p
740 #define coff_core_file_matches_executable_p lynx_core_file_matches_executable_p
742 extern char *lynx_core_file_failing_command
PARAMS ((bfd
*abfd
));
743 #undef coff_core_file_failing_command
744 #define coff_core_file_failing_command lynx_core_file_failing_command
746 extern int lynx_core_file_failing_signal
PARAMS ((bfd
*abfd
));
747 #undef coff_core_file_failing_signal
748 #define coff_core_file_failing_signal lynx_core_file_failing_signal
750 #endif /* HOST_LYNX */
752 /* The transfer vector that leads the outside world to all of the above. */
754 bfd_target rs6000coff_vec
=
756 "aixcoff-rs6000", /* name */
757 bfd_target_coff_flavour
,
758 true, /* data byte order is big */
759 true, /* header byte order is big */
761 (HAS_RELOC
| EXEC_P
| /* object flags */
762 HAS_LINENO
| HAS_DEBUG
|
763 HAS_SYMS
| HAS_LOCALS
| WP_TEXT
),
765 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
766 0, /* leading char */
767 '/', /* ar_pad_char */
768 15, /* ar_max_namelen??? FIXMEmgo */
769 3, /* default alignment power */
771 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
772 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
773 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* data */
774 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
775 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
776 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* hdrs */
778 {_bfd_dummy_target
, coff_object_p
, /* bfd_check_format */
779 coff_archive_p
, CORE_FILE_P
},
780 {bfd_false
, coff_mkobject
, coff_mkarchive
, /* bfd_set_format */
782 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
783 _bfd_write_archive_contents
, bfd_false
},