1 /* BFD back-end for IBM RS/6000 "XCOFF" files.
2 Copyright 1990, 1991, 1992, 1993 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 /* Can't read rs6000 relocs */
48 static reloc_howto_type dummy_reloc =
51 0, /* size (0 = byte, 1 = short, 2 = long) */
53 false, /* pc_relative */
55 complain_overflow_dont, /* complain_on_overflow */
56 0, /* special_function */
58 false, /* partial_inplace */
61 false); /* pcrel_offset */
63 #define RTYPE2HOWTO(cache_ptr, dst) cache_ptr->howto = &dummy_reloc;
67 #define coff_archive_p bfd_generic_archive_p
68 #define coff_mkarchive _bfd_generic_mkarchive
70 #ifdef ARCHIVES_PLEASE
72 /* ------------------------------------------------------------------------ */
73 /* Support for archive file stuff.. */
74 /* Stolen from Damon A. Permezel's `bfd' portation. */
75 /* ------------------------------------------------------------------------ */
77 #undef coff_openr_next_archived_file
78 #define coff_openr_next_archived_file rs6000coff_openr_next_archived_file
80 #undef coff_write_armap
81 #define coff_write_armap rs6000coff_write_armap
83 #undef coff_stat_arch_elt
84 #define coff_stat_arch_elt rs6000coff_stat_arch_elt
86 #undef coff_snarf_ar_hdr
87 #define coff_snarf_ar_hdr rs6000coff_snarf_ar_hdr
90 #define coff_mkarchive rs6000coff_mkarchive
93 #define coff_archive_p rs6000coff_archive_p
95 #include "/usr/include/ar.h" /* <ar.h> doesn't do it. */
98 #define arch_hdr(bfd) \
100 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
104 rs6000coff_mkarchive (abfd)
107 bfd_error = invalid_operation; /* write not supported */
111 /* This functions reads an arch header and returns an areltdata pointer, or
114 Presumes the file pointer is already in the right place (ie pointing
115 to the ar_hdr in the file). Moves the file pointer; on success it
116 should be pointing to the front of the file contents; on failure it
117 could have been moved arbitrarily.
121 rs6000coff_snarf_ar_hdr (abfd)
131 struct areltdata *ared;
132 unsigned int namelen = 0;
135 size = sizeof (h.hdr);
136 if (bfd_read(&h.hdr, 1, size, abfd) != size) {
137 bfd_error = no_more_archived_files;
140 size = atoi(h.hdr.ar_namlen); /* ar_name[] length */
143 if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
144 bfd_error = no_more_archived_files;
148 if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
149 bfd_error = malformed_archive;
153 h.hdr._ar_name.ar_name[size] = 0; /* terminate filename */
156 * if the filename is NULL, we're (probably) at the end.
159 bfd_error = no_more_archived_files;
163 size += sizeof (h.hdr);
164 allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
166 if (allocptr == NULL) {
167 bfd_error = no_memory;
171 ared = (struct areltdata *) allocptr;
173 ared->arch_header = (void *) (allocptr + sizeof (struct areltdata));
174 memcpy ((char *) ared->arch_header, &h.hdr, size);
175 ared->parsed_size = atoi(h.hdr.ar_size);
176 ared->filename = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name;
181 /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
182 Why wasn't this part of the transfer vector? */
185 rs6000coff_get_elt_at_filepos (archive, filepos)
189 struct areltdata *new_areldata;
192 n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
193 if (n_nfd) return n_nfd;
195 if (0 != bfd_seek (archive, filepos, SEEK_SET)) {
196 bfd_error = system_call_error;
200 if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL;
202 n_nfd = _bfd_create_empty_archive_element_shell (archive);
204 bfd_release (archive, (PTR)new_areldata);
207 n_nfd->origin = bfd_tell (archive);
208 n_nfd->arelt_data = (PTR) new_areldata;
209 n_nfd->filename = new_areldata->filename;
211 if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
215 bfd_release (archive, (PTR)n_nfd);
216 bfd_release (archive, (PTR)new_areldata);
221 * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs.
224 rs6000coff_openr_next_archived_file(archive, last_file)
225 bfd *archive, *last_file;
230 filestart = bfd_ardata(archive)->first_file_filepos;
232 filestart = atol(arch_hdr(last_file)->ar_nxtmem);
234 return rs6000coff_get_elt_at_filepos (archive, filestart);
239 rs6000coff_archive_p (abfd)
243 register struct artdata *art;
245 if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
246 bfd_error = wrong_format;
250 if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
251 bfd_error = wrong_format;
256 * bfd_ardata() accesses the bfd->tdata field.
258 abfd->tdata.aout_ar_data =
259 (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
260 if ((art = bfd_ardata (abfd)) == NULL) {
261 bfd_error = no_memory;
265 art->first_file_filepos = atoi(hdr.fl_fstmoff);
266 *(struct fl_hdr *) (1 + art) = hdr;
269 * slurp in the member table, which I think is the armap equivalent.
270 xcoff_slurp_armap(abfd);
278 rs6000coff_stat_arch_elt(abfd, buf)
285 if (abfd->arelt_data == NULL) {
286 bfd_error = invalid_operation;
290 hdr = arch_hdr (abfd);
292 #define foo(arelt, stelt, size) \
293 buf->stelt = strtol (hdr->arelt, &aloser, size); \
294 if (aloser == hdr->arelt) return -1;
296 foo (ar_date, st_mtime, 10);
297 foo (ar_uid, st_uid, 10);
298 foo (ar_gid, st_gid, 10);
299 foo (ar_mode, st_mode, 8);
300 foo (ar_size, st_size, 10);
307 rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
309 unsigned int elength;
312 bfd_error = invalid_operation;
315 #endif /* ARCHIVES_PLEASE */
318 #ifdef COREFILES_PLEASE
319 extern bfd_target * rs6000coff_core_p ();
320 extern boolean rs6000coff_get_section_contents ();
321 extern boolean rs6000coff_core_file_matches_executable_p ();
323 #undef coff_core_file_matches_executable_p
324 #define coff_core_file_matches_executable_p \
325 rs6000coff_core_file_matches_executable_p
327 #undef coff_get_section_contents
328 #define coff_get_section_contents rs6000coff_get_section_contents
331 /* The transfer vector that leads the outside world to all of the above. */
333 bfd_target rs6000coff_vec =
335 "aixcoff-rs6000", /* name */
336 bfd_target_coff_flavour,
337 true, /* data byte order is big */
338 true, /* header byte order is big */
340 (HAS_RELOC | EXEC_P | /* object flags */
341 HAS_LINENO | HAS_DEBUG |
342 HAS_SYMS | HAS_LOCALS | WP_TEXT),
344 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
345 0, /* leading char */
346 '/', /* ar_pad_char */
347 15, /* ar_max_namelen??? FIXMEmgo */
348 3, /* default alignment power */
350 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
351 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
352 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
353 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
354 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
355 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
357 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
359 #ifdef COREFILES_PLEASE
365 {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
367 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
368 _bfd_write_archive_contents, bfd_false},