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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
49 /* The XCOFF reloc table. Actually, XCOFF relocations specify the
50 bitsize and whether they are signed or not, along with a
51 conventional type. This table is for the types, which are used for
52 different algorithms for putting in the reloc. Many of these
53 relocs need special_function entries, which I have not written. */
55 static reloc_howto_type rs6000coff_howto_table[] =
57 /* Standard 32 bit relocation. */
60 2, /* size (0 = byte, 1 = short, 2 = long) */
62 false, /* pc_relative */
64 complain_overflow_bitfield, /* complain_on_overflow */
65 0, /* special_function */
67 true, /* partial_inplace */
68 0xffffffff, /* src_mask */
69 0xffffffff, /* dst_mask */
70 false), /* pcrel_offset */
72 /* 32 bit relocation, but store negative value. */
75 -2, /* size (0 = byte, 1 = short, 2 = long) */
77 false, /* pc_relative */
79 complain_overflow_bitfield, /* complain_on_overflow */
80 0, /* special_function */
82 true, /* partial_inplace */
83 0xffffffff, /* src_mask */
84 0xffffffff, /* dst_mask */
85 false), /* pcrel_offset */
87 /* 32 bit PC relative relocation. */
90 2, /* size (0 = byte, 1 = short, 2 = long) */
92 true, /* pc_relative */
94 complain_overflow_signed, /* complain_on_overflow */
95 0, /* special_function */
97 true, /* partial_inplace */
98 0xffffffff, /* src_mask */
99 0xffffffff, /* dst_mask */
100 false), /* pcrel_offset */
102 /* 16 bit TOC relative relocation. */
105 1, /* size (0 = byte, 1 = short, 2 = long) */
107 false, /* pc_relative */
109 complain_overflow_signed, /* complain_on_overflow */
110 0, /* special_function */
112 true, /* partial_inplace */
113 0xffff, /* src_mask */
114 0xffff, /* dst_mask */
115 false), /* pcrel_offset */
117 /* I don't really know what this is. */
120 2, /* size (0 = byte, 1 = short, 2 = long) */
122 false, /* pc_relative */
124 complain_overflow_bitfield, /* complain_on_overflow */
125 0, /* special_function */
127 true, /* partial_inplace */
128 0xffffffff, /* src_mask */
129 0xffffffff, /* dst_mask */
130 false), /* pcrel_offset */
132 /* External TOC relative symbol. */
135 2, /* size (0 = byte, 1 = short, 2 = long) */
137 false, /* pc_relative */
139 complain_overflow_bitfield, /* complain_on_overflow */
140 0, /* special_function */
142 true, /* partial_inplace */
143 0xffff, /* src_mask */
144 0xffff, /* dst_mask */
145 false), /* pcrel_offset */
147 /* Local TOC relative symbol. */
150 2, /* size (0 = byte, 1 = short, 2 = long) */
152 false, /* pc_relative */
154 complain_overflow_bitfield, /* complain_on_overflow */
155 0, /* special_function */
157 true, /* partial_inplace */
158 0xffff, /* src_mask */
159 0xffff, /* dst_mask */
160 false), /* pcrel_offset */
164 /* Non modifiable absolute branch. */
167 2, /* size (0 = byte, 1 = short, 2 = long) */
169 false, /* pc_relative */
171 complain_overflow_bitfield, /* complain_on_overflow */
172 0, /* special_function */
174 true, /* partial_inplace */
175 0x3fffffc, /* src_mask */
176 0x3fffffc, /* dst_mask */
177 false), /* pcrel_offset */
181 /* Non modifiable relative branch. */
182 HOWTO (0xa, /* type */
184 2, /* size (0 = byte, 1 = short, 2 = long) */
186 true, /* pc_relative */
188 complain_overflow_signed, /* complain_on_overflow */
189 0, /* special_function */
191 true, /* partial_inplace */
192 0x3fffffc, /* src_mask */
193 0x3fffffc, /* dst_mask */
194 false), /* pcrel_offset */
199 HOWTO (0xc, /* type */
201 2, /* size (0 = byte, 1 = short, 2 = long) */
203 false, /* pc_relative */
205 complain_overflow_bitfield, /* complain_on_overflow */
206 0, /* special_function */
208 true, /* partial_inplace */
209 0xffff, /* src_mask */
210 0xffff, /* dst_mask */
211 false), /* pcrel_offset */
214 HOWTO (0xd, /* type */
216 2, /* size (0 = byte, 1 = short, 2 = long) */
218 false, /* pc_relative */
220 complain_overflow_bitfield, /* complain_on_overflow */
221 0, /* special_function */
223 true, /* partial_inplace */
224 0xffff, /* src_mask */
225 0xffff, /* dst_mask */
226 false), /* pcrel_offset */
230 /* Non-relocating reference. */
231 HOWTO (0xf, /* type */
233 2, /* size (0 = byte, 1 = short, 2 = long) */
235 false, /* pc_relative */
237 complain_overflow_bitfield, /* complain_on_overflow */
238 0, /* special_function */
240 false, /* partial_inplace */
243 false), /* pcrel_offset */
248 /* TOC relative indirect load. */
249 HOWTO (0x12, /* type */
251 2, /* size (0 = byte, 1 = short, 2 = long) */
253 false, /* pc_relative */
255 complain_overflow_bitfield, /* complain_on_overflow */
256 0, /* special_function */
258 true, /* partial_inplace */
259 0xffff, /* src_mask */
260 0xffff, /* dst_mask */
261 false), /* pcrel_offset */
263 /* TOC relative load address. */
264 HOWTO (0x13, /* type */
266 2, /* size (0 = byte, 1 = short, 2 = long) */
268 false, /* pc_relative */
270 complain_overflow_bitfield, /* complain_on_overflow */
271 0, /* special_function */
273 true, /* partial_inplace */
274 0xffff, /* src_mask */
275 0xffff, /* dst_mask */
276 false), /* pcrel_offset */
278 /* Modifiable relative branch. */
279 HOWTO (0x14, /* type */
281 2, /* size (0 = byte, 1 = short, 2 = long) */
283 false, /* pc_relative */
285 complain_overflow_bitfield, /* complain_on_overflow */
286 0, /* special_function */
287 "R_RRTBI", /* name */
288 true, /* partial_inplace */
289 0xffffffff, /* src_mask */
290 0xffffffff, /* dst_mask */
291 false), /* pcrel_offset */
293 /* Modifiable absolute branch. */
294 HOWTO (0x15, /* type */
296 2, /* size (0 = byte, 1 = short, 2 = long) */
298 false, /* pc_relative */
300 complain_overflow_bitfield, /* complain_on_overflow */
301 0, /* special_function */
302 "R_RRTBA", /* name */
303 true, /* partial_inplace */
304 0xffffffff, /* src_mask */
305 0xffffffff, /* dst_mask */
306 false), /* pcrel_offset */
308 /* Modifiable call absolute indirect. */
309 HOWTO (0x16, /* type */
311 2, /* size (0 = byte, 1 = short, 2 = long) */
313 false, /* pc_relative */
315 complain_overflow_bitfield, /* complain_on_overflow */
316 0, /* special_function */
318 true, /* partial_inplace */
319 0xffff, /* src_mask */
320 0xffff, /* dst_mask */
321 false), /* pcrel_offset */
323 /* Modifiable call relative. */
324 HOWTO (0x17, /* type */
326 2, /* size (0 = byte, 1 = short, 2 = long) */
328 false, /* pc_relative */
330 complain_overflow_bitfield, /* complain_on_overflow */
331 0, /* special_function */
333 true, /* partial_inplace */
334 0xffff, /* src_mask */
335 0xffff, /* dst_mask */
336 false), /* pcrel_offset */
338 /* Modifiable branch absolute. */
339 HOWTO (0x18, /* type */
341 2, /* size (0 = byte, 1 = short, 2 = long) */
343 false, /* pc_relative */
345 complain_overflow_bitfield, /* complain_on_overflow */
346 0, /* special_function */
348 true, /* partial_inplace */
349 0xffff, /* src_mask */
350 0xffff, /* dst_mask */
351 false), /* pcrel_offset */
353 /* Modifiable branch absolute. */
354 HOWTO (0x19, /* type */
356 2, /* size (0 = byte, 1 = short, 2 = long) */
358 false, /* pc_relative */
360 complain_overflow_bitfield, /* complain_on_overflow */
361 0, /* special_function */
363 true, /* partial_inplace */
364 0xffff, /* src_mask */
365 0xffff, /* dst_mask */
366 false), /* pcrel_offset */
368 /* Modifiable branch relative. */
369 HOWTO (0x1a, /* type */
371 2, /* size (0 = byte, 1 = short, 2 = long) */
373 false, /* pc_relative */
375 complain_overflow_signed, /* complain_on_overflow */
376 0, /* special_function */
378 true, /* partial_inplace */
379 0xffff, /* src_mask */
380 0xffff, /* dst_mask */
381 false), /* pcrel_offset */
383 /* Modifiable branch absolute. */
384 HOWTO (0x1b, /* type */
386 2, /* size (0 = byte, 1 = short, 2 = long) */
388 false, /* pc_relative */
390 complain_overflow_bitfield, /* complain_on_overflow */
391 0, /* special_function */
393 true, /* partial_inplace */
394 0xffff, /* src_mask */
395 0xffff, /* dst_mask */
396 false) /* pcrel_offset */
399 #define RTYPE2HOWTO(cache_ptr, dst) rs6000coff_rtype2howto (cache_ptr, dst)
401 static void rs6000coff_rtype2howto PARAMS ((arelent *,
402 struct internal_reloc *));
405 rs6000coff_rtype2howto (relent, internal)
407 struct internal_reloc *internal;
409 relent->howto = rs6000coff_howto_table + internal->r_type;
411 /* The r_size field of an XCOFF reloc encodes the bitsize of the
412 relocation, as well as indicating whether it is signed or not.
413 Doublecheck that the relocation information gathered from the
414 type matches this information. */
415 if (relent->howto->bitsize != ((unsigned int) internal->r_size & 0x1f) + 1)
418 if ((internal->r_size & 0x80) != 0
419 ? (relent->howto->complain_on_overflow != complain_overflow_signed)
420 : (relent->howto->complain_on_overflow != complain_overflow_bitfield))
425 #define coff_bfd_reloc_type_lookup rs6000coff_reloc_type_lookup
427 static reloc_howto_type *rs6000coff_reloc_type_lookup
428 PARAMS ((bfd *, bfd_reloc_code_real_type));
430 static reloc_howto_type *
431 rs6000coff_reloc_type_lookup (abfd, code)
433 bfd_reloc_code_real_type code;
437 case BFD_RELOC_PPC_B26:
438 return &rs6000coff_howto_table[0xa];
439 case BFD_RELOC_PPC_BA26:
440 return &rs6000coff_howto_table[8];
441 case BFD_RELOC_PPC_TOC16:
442 return &rs6000coff_howto_table[3];
444 return &rs6000coff_howto_table[0];
450 #define SELECT_RELOC(internal, howto) \
452 internal.r_type = howto->type; \
454 ((howto->complain_on_overflow == complain_overflow_signed \
457 | (howto->bitsize - 1)); \
460 #define COFF_LONG_FILENAMES
462 #include "coffcode.h"
464 #define coff_archive_p bfd_generic_archive_p
465 #define coff_mkarchive _bfd_generic_mkarchive
469 /* ------------------------------------------------------------------------ */
470 /* Support for archive file stuff.. */
471 /* Stolen from Damon A. Permezel's `bfd' portation. */
472 /* ------------------------------------------------------------------------ */
474 #define rs6000coff_slurp_armap bfd_slurp_coff_armap
475 #define rs6000coff_slurp_extended_name_table _bfd_slurp_extended_name_table
476 #define rs6000coff_construct_extended_name_table \
477 _bfd_archive_coff_construct_extended_name_table
478 #define rs6000coff_truncate_arname bfd_dont_truncate_arname
479 #define rs6000coff_update_armap_timestamp bfd_true
481 #undef coff_mkarchive
482 #define coff_mkarchive rs6000coff_mkarchive
484 #undef coff_archive_p
485 #define coff_archive_p rs6000coff_archive_p
487 #include "/usr/include/ar.h" /* <ar.h> doesn't do it. */
490 #define arch_hdr(bfd) \
492 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
496 rs6000coff_mkarchive (abfd)
499 bfd_set_error (bfd_error_invalid_operation); /* write not supported */
504 /* This functions reads an arch header and returns an areltdata pointer, or
507 Presumes the file pointer is already in the right place (ie pointing
508 to the ar_hdr in the file). Moves the file pointer; on success it
509 should be pointing to the front of the file contents; on failure it
510 could have been moved arbitrarily.
514 rs6000coff_snarf_ar_hdr (abfd)
522 struct areltdata *ared;
525 size = sizeof (h.hdr);
526 if (bfd_read(&h.hdr, 1, size, abfd) != size) {
527 if (bfd_get_error () != bfd_error_system_call)
528 bfd_set_error (bfd_error_no_more_archived_files);
531 size = atoi(h.hdr.ar_namlen); /* ar_name[] length */
534 if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
535 if (bfd_get_error () != bfd_error_system_call)
536 bfd_set_error (bfd_error_no_more_archived_files);
540 if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
541 bfd_set_error (bfd_error_malformed_archive);
545 h.hdr._ar_name.ar_name[size] = 0; /* terminate filename */
548 * if the filename is NULL, we're (probably) at the end.
551 bfd_set_error (bfd_error_no_more_archived_files);
555 size += sizeof (h.hdr);
556 allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
558 if (allocptr == NULL) {
559 bfd_set_error (bfd_error_no_memory);
563 ared = (struct areltdata *) allocptr;
565 ared->arch_header = (void *) (allocptr + sizeof (struct areltdata));
566 memcpy ((char *) ared->arch_header, &h.hdr, size);
567 ared->parsed_size = atoi(h.hdr.ar_size);
568 ared->filename = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name;
573 /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
574 Why wasn't this part of the transfer vector? */
577 rs6000coff_get_elt_at_filepos (archive, filepos)
581 struct areltdata *new_areldata;
584 n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
585 if (n_nfd) return n_nfd;
587 if (0 != bfd_seek (archive, filepos, SEEK_SET))
590 if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL;
592 n_nfd = _bfd_create_empty_archive_element_shell (archive);
594 bfd_release (archive, (PTR)new_areldata);
597 n_nfd->origin = bfd_tell (archive);
598 n_nfd->arelt_data = (PTR) new_areldata;
599 n_nfd->filename = new_areldata->filename;
601 if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
605 bfd_release (archive, (PTR)n_nfd);
606 bfd_release (archive, (PTR)new_areldata);
611 * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs.
614 rs6000coff_openr_next_archived_file(archive, last_file)
615 bfd *archive, *last_file;
620 filestart = bfd_ardata(archive)->first_file_filepos;
622 filestart = atol(arch_hdr(last_file)->ar_nxtmem);
624 return rs6000coff_get_elt_at_filepos (archive, filestart);
628 static const bfd_target *
629 rs6000coff_archive_p (abfd)
633 register struct artdata *art;
635 if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
636 if (bfd_get_error () != bfd_error_system_call)
637 bfd_set_error (bfd_error_wrong_format);
641 if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
642 bfd_set_error (bfd_error_wrong_format);
647 * bfd_ardata() accesses the bfd->tdata field.
649 abfd->tdata.aout_ar_data =
650 (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
651 if ((art = bfd_ardata (abfd)) == NULL) {
652 bfd_set_error (bfd_error_no_memory);
656 art->first_file_filepos = atoi(hdr.fl_fstmoff);
657 *(struct fl_hdr *) (1 + art) = hdr;
660 * slurp in the member table, which I think is the armap equivalent.
661 xcoff_slurp_armap(abfd);
669 rs6000coff_generic_stat_arch_elt(abfd, buf)
676 if (abfd->arelt_data == NULL) {
677 bfd_set_error (bfd_error_invalid_operation);
681 hdr = arch_hdr (abfd);
683 #define foo(arelt, stelt, size) \
684 buf->stelt = strtol (hdr->arelt, &aloser, size); \
685 if (aloser == hdr->arelt) return -1;
687 foo (ar_date, st_mtime, 10);
688 foo (ar_uid, st_uid, 10);
689 foo (ar_gid, st_gid, 10);
690 foo (ar_mode, st_mode, 8);
691 foo (ar_size, st_size, 10);
698 rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
700 unsigned int elength;
702 unsigned int orl_count;
705 bfd_set_error (bfd_error_invalid_operation);
708 #endif /* HOST_AIX */
711 #define CORE_FILE_P _bfd_dummy_target
713 #define coff_core_file_failing_command _bfd_nocore_core_file_failing_command
714 #define coff_core_file_failing_signal _bfd_nocore_core_file_failing_signal
715 #define coff_core_file_matches_executable_p \
716 _bfd_nocore_core_file_matches_executable_p
720 #define CORE_FILE_P rs6000coff_core_p
721 extern const bfd_target * rs6000coff_core_p ();
722 extern boolean rs6000coff_get_section_contents ();
723 extern boolean rs6000coff_core_file_matches_executable_p ();
725 #undef coff_core_file_matches_executable_p
726 #define coff_core_file_matches_executable_p \
727 rs6000coff_core_file_matches_executable_p
729 #undef coff_get_section_contents
730 #define coff_get_section_contents rs6000coff_get_section_contents
731 #endif /* AIX_CORE */
736 #define CORE_FILE_P lynx_core_file_p
737 extern const bfd_target *lynx_core_file_p PARAMS ((bfd *abfd));
739 extern boolean lynx_core_file_matches_executable_p PARAMS ((bfd *core_bfd,
741 #undef coff_core_file_matches_executable_p
742 #define coff_core_file_matches_executable_p lynx_core_file_matches_executable_p
744 extern char *lynx_core_file_failing_command PARAMS ((bfd *abfd));
745 #undef coff_core_file_failing_command
746 #define coff_core_file_failing_command lynx_core_file_failing_command
748 extern int lynx_core_file_failing_signal PARAMS ((bfd *abfd));
749 #undef coff_core_file_failing_signal
750 #define coff_core_file_failing_signal lynx_core_file_failing_signal
752 #endif /* LYNX_CORE */
754 /* The transfer vector that leads the outside world to all of the above. */
756 const bfd_target rs6000coff_vec =
758 "aixcoff-rs6000", /* name */
759 bfd_target_coff_flavour,
760 true, /* data byte order is big */
761 true, /* header byte order is big */
763 (HAS_RELOC | EXEC_P | /* object flags */
764 HAS_LINENO | HAS_DEBUG |
765 HAS_SYMS | HAS_LOCALS | WP_TEXT),
767 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
768 0, /* leading char */
769 '/', /* ar_pad_char */
770 15, /* ar_max_namelen??? FIXMEmgo */
772 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
773 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
774 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
775 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
776 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
777 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
779 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
780 coff_archive_p, CORE_FILE_P},
781 {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
783 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
784 _bfd_write_archive_contents, bfd_false},
786 BFD_JUMP_TABLE_GENERIC (coff),
787 BFD_JUMP_TABLE_COPY (coff),
788 BFD_JUMP_TABLE_CORE (coff),
790 BFD_JUMP_TABLE_ARCHIVE (rs6000coff),
792 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
794 BFD_JUMP_TABLE_SYMBOLS (coff),
795 BFD_JUMP_TABLE_RELOCS (coff),
796 BFD_JUMP_TABLE_WRITE (coff),
797 BFD_JUMP_TABLE_LINK (coff),
798 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),