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 "coff/internal.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
.aout_ar_data
=
238 (void *) bfd_zalloc(abfd
, sizeof (*art
) + sizeof (hdr
));
239 if ((art
= bfd_ardata (abfd
)) == NULL
) {
240 bfd_error
= no_memory
;
244 art
->first_file_filepos
= atoi(hdr
.fl_fstmoff
);
245 *(struct fl_hdr
*) (1 + art
) = hdr
;
248 * slurp in the member table, which I think is the armap equivalent.
249 xcoff_slurp_armap(abfd);
257 rs6000coff_stat_arch_elt(abfd
, buf
)
264 if (abfd
->arelt_data
== NULL
) {
265 bfd_error
= invalid_operation
;
269 hdr
= arch_hdr (abfd
);
271 #define foo(arelt, stelt, size) \
272 buf->stelt = strtol (hdr->arelt, &aloser, size); \
273 if (aloser == hdr->arelt) return -1;
275 foo (ar_date
, st_mtime
, 10);
276 foo (ar_uid
, st_uid
, 10);
277 foo (ar_gid
, st_gid
, 10);
278 foo (ar_mode
, st_mode
, 8);
279 foo (ar_size
, st_size
, 10);
286 rs6000coff_write_armap (arch
, elength
, map
, orl_count
, stridx
)
288 unsigned int elength
;
291 bfd_error
= invalid_operation
;
294 #endif /* ARCHIVES_PLEASE */
297 #ifdef COREFILES_PLEASE
298 extern bfd_target
* rs6000coff_core_p ();
299 extern boolean
rs6000coff_get_section_contents ();
300 extern boolean
rs6000coff_core_file_matches_executable_p ();
302 #undef coff_core_file_matches_executable_p
303 #define coff_core_file_matches_executable_p \
304 rs6000coff_core_file_matches_executable_p
306 #undef coff_get_section_contents
307 #define coff_get_section_contents rs6000coff_get_section_contents
310 /* The transfer vector that leads the outside world to all of the above. */
312 bfd_target rs6000coff_vec
=
314 "aixcoff-rs6000", /* name */
315 bfd_target_coff_flavour
,
316 true, /* data byte order is big */
317 true, /* header byte order is big */
319 (HAS_RELOC
| EXEC_P
| /* object flags */
320 HAS_LINENO
| HAS_DEBUG
|
321 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
),
323 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
324 0, /* leading char */
325 '/', /* ar_pad_char */
326 15, /* ar_max_namelen??? FIXMEmgo */
327 3, /* default alignment power */
329 _do_getb64
, _do_putb64
, _do_getb32
, _do_putb32
, _do_getb16
, _do_putb16
, /* data */
330 _do_getb64
, _do_putb64
, _do_getb32
, _do_putb32
, _do_getb16
, _do_putb16
, /* hdrs */
332 {_bfd_dummy_target
, coff_object_p
, /* bfd_check_format */
334 #ifdef COREFILES_PLEASE
340 {bfd_false
, coff_mkobject
, coff_mkarchive
, /* bfd_set_format */
342 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
343 _bfd_write_archive_contents
, bfd_false
},