* config.sub (hiux): Fix typo. From m-kasahr@sramhc.sra.co.JP.
[deliverable/binutils-gdb.git] / bfd / coff-rs6000.c
CommitLineData
f4bd7a8f
DM
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
6 character set it is.
7 Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
8 and John Gilmore.
ba9137fe
JG
9 Archive support from Damon A. Permezel.
10 Contributed by IBM Corporation and Cygnus Support.
11
12This file is part of BFD, the Binary File Descriptor library.
13
14This program is free software; you can redistribute it and/or modify
15it under the terms of the GNU General Public License as published by
16the Free Software Foundation; either version 2 of the License, or
17(at your option) any later version.
18
19This program is distributed in the hope that it will be useful,
20but WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22GNU General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with this program; if not, write to the Free Software
26Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
27
c9301d7b
SC
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.
31
32 FIXMEmgo comments are left from Metin Ozisik's original port. */
ba9137fe
JG
33
34/* Internalcoff.h and coffcode.h modify themselves based on this flag. */
35#define RS6000COFF_C 1
36
ba9137fe 37#include "bfd.h"
156e3852 38#include "sysdep.h"
ba9137fe
JG
39#include "libbfd.h"
40#include "obstack.h"
294eaca4
SC
41#include "coff/internal.h"
42#include "coff/rs6000.h"
ba9137fe
JG
43#include "libcoff.h"
44
45/* The main body of code is in coffcode.h. */
ba9137fe 46
c9301d7b 47/* Can't read rs6000 relocs */
f4bd7a8f
DM
48static reloc_howto_type dummy_reloc =
49 HOWTO (0, /* type */
50 0, /* rightshift */
51 0, /* size (0 = byte, 1 = short, 2 = long) */
52 8, /* bitsize */
53 false, /* pc_relative */
54 0, /* bitpos */
55 complain_overflow_dont, /* complain_on_overflow */
56 0, /* special_function */
57 "UNKNOWN", /* name */
58 false, /* partial_inplace */
59 0, /* src_mask */
60 0, /* dst_mask */
61 false); /* pcrel_offset */
62
63#define RTYPE2HOWTO(cache_ptr, dst) cache_ptr->howto = &dummy_reloc;
64
c9301d7b 65#include "coffcode.h"
ba9137fe 66
c9301d7b
SC
67#define coff_archive_p bfd_generic_archive_p
68#define coff_mkarchive _bfd_generic_mkarchive
ba9137fe 69
c9301d7b 70#ifdef ARCHIVES_PLEASE
ba9137fe 71
c9301d7b
SC
72/* ------------------------------------------------------------------------ */
73/* Support for archive file stuff.. */
74/* Stolen from Damon A. Permezel's `bfd' portation. */
75/* ------------------------------------------------------------------------ */
ba9137fe 76
c9301d7b
SC
77#undef coff_openr_next_archived_file
78#define coff_openr_next_archived_file rs6000coff_openr_next_archived_file
ba9137fe 79
c9301d7b
SC
80#undef coff_write_armap
81#define coff_write_armap rs6000coff_write_armap
ba9137fe 82
c9301d7b
SC
83#undef coff_stat_arch_elt
84#define coff_stat_arch_elt rs6000coff_stat_arch_elt
ba9137fe 85
c9301d7b
SC
86#undef coff_snarf_ar_hdr
87#define coff_snarf_ar_hdr rs6000coff_snarf_ar_hdr
ba9137fe 88
c9301d7b
SC
89#undef coff_mkarchive
90#define coff_mkarchive rs6000coff_mkarchive
ba9137fe 91
c9301d7b
SC
92#undef coff_archive_p
93#define coff_archive_p rs6000coff_archive_p
ba9137fe
JG
94
95#include "/usr/include/ar.h" /* <ar.h> doesn't do it. */
96
97
98#define arch_hdr(bfd) \
99 ((struct ar_hdr *) \
100 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
101
102
103static boolean
104rs6000coff_mkarchive (abfd)
105 bfd *abfd;
106{
107 bfd_error = invalid_operation; /* write not supported */
108}
109
110
111/* This functions reads an arch header and returns an areltdata pointer, or
112 NULL on error.
113
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.
118*/
119
120struct areltdata *
121rs6000coff_snarf_ar_hdr (abfd)
122 bfd *abfd;
123{
124 extern int errno;
125
126 struct {
127 struct ar_hdr hdr;
128 char namebuf[256];
129 } h;
130 int size;
131 struct areltdata *ared;
132 unsigned int namelen = 0;
133 char *allocptr;
134
135 size = sizeof (h.hdr);
136 if (bfd_read(&h.hdr, 1, size, abfd) != size) {
137 bfd_error = no_more_archived_files;
138 return NULL;
139 }
140 size = atoi(h.hdr.ar_namlen); /* ar_name[] length */
141 size += size & 1;
142
143 if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
144 bfd_error = no_more_archived_files;
145 return NULL;
146 }
147
148 if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
149 bfd_error = malformed_archive;
150 return NULL;
151 }
152
153 h.hdr._ar_name.ar_name[size] = 0; /* terminate filename */
154
155 /*
156 * if the filename is NULL, we're (probably) at the end.
157 */
158 if (size == 0) {
159 bfd_error = no_more_archived_files;
160 return NULL;
161 }
162
163 size += sizeof (h.hdr);
164 allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
165
166 if (allocptr == NULL) {
167 bfd_error = no_memory;
168 return NULL;
169 }
170
171 ared = (struct areltdata *) allocptr;
172
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;
177
178 return ared;
179}
180
c9301d7b
SC
181/* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
182 Why wasn't this part of the transfer vector? */
183
184bfd *
185rs6000coff_get_elt_at_filepos (archive, filepos)
186 bfd *archive;
187 file_ptr filepos;
188{
189 struct areltdata *new_areldata;
190 bfd *n_nfd;
191
f4bd7a8f 192 n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
c9301d7b
SC
193 if (n_nfd) return n_nfd;
194
f8e01940 195 if (0 != bfd_seek (archive, filepos, SEEK_SET)) {
c9301d7b
SC
196 bfd_error = system_call_error;
197 return NULL;
198 }
199
200 if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL;
201
202 n_nfd = _bfd_create_empty_archive_element_shell (archive);
203 if (n_nfd == NULL) {
204 bfd_release (archive, (PTR)new_areldata);
205 return NULL;
206 }
207 n_nfd->origin = bfd_tell (archive);
208 n_nfd->arelt_data = (PTR) new_areldata;
209 n_nfd->filename = new_areldata->filename;
210
f4bd7a8f 211 if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
c9301d7b
SC
212 return n_nfd;
213
214 /* huh? */
215 bfd_release (archive, (PTR)n_nfd);
216 bfd_release (archive, (PTR)new_areldata);
217 return NULL;
218}
219
ba9137fe
JG
220/*
221 * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs.
222 */
223static bfd *
224rs6000coff_openr_next_archived_file(archive, last_file)
225 bfd *archive, *last_file;
226{
227 file_ptr filestart;
228
229 if (!last_file)
230 filestart = bfd_ardata(archive)->first_file_filepos;
231 else
232 filestart = atol(arch_hdr(last_file)->ar_nxtmem);
233
c9301d7b 234 return rs6000coff_get_elt_at_filepos (archive, filestart);
ba9137fe
JG
235}
236
237
238static bfd_target *
239rs6000coff_archive_p (abfd)
240 bfd *abfd;
241{
242 struct fl_hdr hdr;
243 register struct artdata *art;
244
c9301d7b 245 if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
ba9137fe
JG
246 bfd_error = wrong_format;
247 return 0;
248 }
249
250 if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
251 bfd_error = wrong_format;
252 return 0;
253 }
254
255 /*
256 * bfd_ardata() accesses the bfd->tdata field.
257 */
294eaca4
SC
258 abfd->tdata.aout_ar_data =
259 (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
ba9137fe
JG
260 if ((art = bfd_ardata (abfd)) == NULL) {
261 bfd_error = no_memory;
262 return 0;
263 }
264
265 art->first_file_filepos = atoi(hdr.fl_fstmoff);
266 *(struct fl_hdr *) (1 + art) = hdr;
267
c9301d7b
SC
268 /* Someday...
269 * slurp in the member table, which I think is the armap equivalent.
ba9137fe
JG
270 xcoff_slurp_armap(abfd);
271 */
272
ba9137fe
JG
273 return abfd->xvec;
274}
275
276
277static int
278rs6000coff_stat_arch_elt(abfd, buf)
279 bfd *abfd;
280 struct stat *buf;
281{
282 struct ar_hdr *hdr;
283 char *aloser;
284
285 if (abfd->arelt_data == NULL) {
286 bfd_error = invalid_operation;
287 return -1;
288 }
289
290 hdr = arch_hdr (abfd);
291
292#define foo(arelt, stelt, size) \
293 buf->stelt = strtol (hdr->arelt, &aloser, size); \
294 if (aloser == hdr->arelt) return -1;
295
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);
c9301d7b 301#undef foo
ba9137fe
JG
302
303 return 0;
304}
305
306static boolean
307rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
308 bfd *arch;
309 unsigned int elength;
310 struct orl *map;
311{
312 bfd_error = invalid_operation;
313 return false;
314}
c9301d7b
SC
315#endif /* ARCHIVES_PLEASE */
316
294eaca4
SC
317\f
318#ifdef COREFILES_PLEASE
319extern bfd_target * rs6000coff_core_p ();
320extern boolean rs6000coff_get_section_contents ();
321extern boolean rs6000coff_core_file_matches_executable_p ();
c9301d7b
SC
322
323#undef coff_core_file_matches_executable_p
324#define coff_core_file_matches_executable_p \
325 rs6000coff_core_file_matches_executable_p
ba9137fe 326
c9301d7b
SC
327#undef coff_get_section_contents
328#define coff_get_section_contents rs6000coff_get_section_contents
ba9137fe 329#endif
ba9137fe 330
c9301d7b
SC
331/* The transfer vector that leads the outside world to all of the above. */
332
333bfd_target rs6000coff_vec =
334{
335 "aixcoff-rs6000", /* name */
336 bfd_target_coff_flavour,
337 true, /* data byte order is big */
338 true, /* header byte order is big */
339
340 (HAS_RELOC | EXEC_P | /* object flags */
341 HAS_LINENO | HAS_DEBUG |
f4bd7a8f 342 HAS_SYMS | HAS_LOCALS | WP_TEXT),
c9301d7b
SC
343
344 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
294eaca4 345 0, /* leading char */
c9301d7b
SC
346 '/', /* ar_pad_char */
347 15, /* ar_max_namelen??? FIXMEmgo */
348 3, /* default alignment power */
349
f4bd7a8f
DM
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 */
c9301d7b
SC
356
357 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
294eaca4
SC
358 coff_archive_p,
359#ifdef COREFILES_PLEASE
360 rs6000coff_core_p
361#else
362 _bfd_dummy_target
363#endif
364 },
c9301d7b
SC
365 {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
366 bfd_false},
367 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
368 _bfd_write_archive_contents, bfd_false},
369
370 JUMP_TABLE(coff),
f4bd7a8f 371 COFF_SWAP_TABLE,
c9301d7b 372};
This page took 0.106911 seconds and 4 git commands to generate.