#if 0 out some more declarations which conflict with system headers
[deliverable/binutils-gdb.git] / bfd / coff-rs6000.c
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.
6
7 This file is part of BFD, the Binary File Descriptor library.
8
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.
13
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.
18
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. */
22
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.
26
27 FIXMEmgo comments are left from Metin Ozisik's original port. */
28
29 /* Internalcoff.h and coffcode.h modify themselves based on this flag. */
30 #define RS6000COFF_C 1
31
32 #include "bfd.h"
33 #include "sysdep.h"
34 #include "libbfd.h"
35 #include "obstack.h"
36 #include "coff/internal.h"
37 #include "coff/rs6000.h"
38 #include "libcoff.h"
39
40 /* The main body of code is in coffcode.h. */
41
42 /* Can't read rs6000 relocs */
43 #define RTYPE2HOWTO(a,b)
44 #include "coffcode.h"
45
46 #define coff_archive_p bfd_generic_archive_p
47 #define coff_mkarchive _bfd_generic_mkarchive
48
49 #ifdef ARCHIVES_PLEASE
50
51 /* ------------------------------------------------------------------------ */
52 /* Support for archive file stuff.. */
53 /* Stolen from Damon A. Permezel's `bfd' portation. */
54 /* ------------------------------------------------------------------------ */
55
56 #undef coff_openr_next_archived_file
57 #define coff_openr_next_archived_file rs6000coff_openr_next_archived_file
58
59 #undef coff_write_armap
60 #define coff_write_armap rs6000coff_write_armap
61
62 #undef coff_stat_arch_elt
63 #define coff_stat_arch_elt rs6000coff_stat_arch_elt
64
65 #undef coff_snarf_ar_hdr
66 #define coff_snarf_ar_hdr rs6000coff_snarf_ar_hdr
67
68 #undef coff_mkarchive
69 #define coff_mkarchive rs6000coff_mkarchive
70
71 #undef coff_archive_p
72 #define coff_archive_p rs6000coff_archive_p
73
74 #include "/usr/include/ar.h" /* <ar.h> doesn't do it. */
75
76
77 #define arch_hdr(bfd) \
78 ((struct ar_hdr *) \
79 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
80
81
82 static boolean
83 rs6000coff_mkarchive (abfd)
84 bfd *abfd;
85 {
86 bfd_error = invalid_operation; /* write not supported */
87 }
88
89
90 /* This functions reads an arch header and returns an areltdata pointer, or
91 NULL on error.
92
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.
97 */
98
99 struct areltdata *
100 rs6000coff_snarf_ar_hdr (abfd)
101 bfd *abfd;
102 {
103 extern int errno;
104
105 struct {
106 struct ar_hdr hdr;
107 char namebuf[256];
108 } h;
109 int size;
110 struct areltdata *ared;
111 unsigned int namelen = 0;
112 char *allocptr;
113
114 size = sizeof (h.hdr);
115 if (bfd_read(&h.hdr, 1, size, abfd) != size) {
116 bfd_error = no_more_archived_files;
117 return NULL;
118 }
119 size = atoi(h.hdr.ar_namlen); /* ar_name[] length */
120 size += size & 1;
121
122 if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
123 bfd_error = no_more_archived_files;
124 return NULL;
125 }
126
127 if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
128 bfd_error = malformed_archive;
129 return NULL;
130 }
131
132 h.hdr._ar_name.ar_name[size] = 0; /* terminate filename */
133
134 /*
135 * if the filename is NULL, we're (probably) at the end.
136 */
137 if (size == 0) {
138 bfd_error = no_more_archived_files;
139 return NULL;
140 }
141
142 size += sizeof (h.hdr);
143 allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
144
145 if (allocptr == NULL) {
146 bfd_error = no_memory;
147 return NULL;
148 }
149
150 ared = (struct areltdata *) allocptr;
151
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;
156
157 return ared;
158 }
159
160 /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
161 Why wasn't this part of the transfer vector? */
162
163 bfd *
164 rs6000coff_get_elt_at_filepos (archive, filepos)
165 bfd *archive;
166 file_ptr filepos;
167 {
168 struct areltdata *new_areldata;
169 bfd *n_nfd;
170
171 n_nfd = look_for_bfd_in_cache (archive, filepos);
172 if (n_nfd) return n_nfd;
173
174 if (0 != bfd_seek (archive, filepos, SEEK_SET)) {
175 bfd_error = system_call_error;
176 return NULL;
177 }
178
179 if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL;
180
181 n_nfd = _bfd_create_empty_archive_element_shell (archive);
182 if (n_nfd == NULL) {
183 bfd_release (archive, (PTR)new_areldata);
184 return NULL;
185 }
186 n_nfd->origin = bfd_tell (archive);
187 n_nfd->arelt_data = (PTR) new_areldata;
188 n_nfd->filename = new_areldata->filename;
189
190 if (add_bfd_to_cache (archive, filepos, n_nfd))
191 return n_nfd;
192
193 /* huh? */
194 bfd_release (archive, (PTR)n_nfd);
195 bfd_release (archive, (PTR)new_areldata);
196 return NULL;
197 }
198
199 /*
200 * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs.
201 */
202 static bfd *
203 rs6000coff_openr_next_archived_file(archive, last_file)
204 bfd *archive, *last_file;
205 {
206 file_ptr filestart;
207
208 if (!last_file)
209 filestart = bfd_ardata(archive)->first_file_filepos;
210 else
211 filestart = atol(arch_hdr(last_file)->ar_nxtmem);
212
213 return rs6000coff_get_elt_at_filepos (archive, filestart);
214 }
215
216
217 static bfd_target *
218 rs6000coff_archive_p (abfd)
219 bfd *abfd;
220 {
221 struct fl_hdr hdr;
222 register struct artdata *art;
223
224 if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
225 bfd_error = wrong_format;
226 return 0;
227 }
228
229 if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
230 bfd_error = wrong_format;
231 return 0;
232 }
233
234 /*
235 * bfd_ardata() accesses the bfd->tdata field.
236 */
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;
241 return 0;
242 }
243
244 art->first_file_filepos = atoi(hdr.fl_fstmoff);
245 *(struct fl_hdr *) (1 + art) = hdr;
246
247 /* Someday...
248 * slurp in the member table, which I think is the armap equivalent.
249 xcoff_slurp_armap(abfd);
250 */
251
252 return abfd->xvec;
253 }
254
255
256 static int
257 rs6000coff_stat_arch_elt(abfd, buf)
258 bfd *abfd;
259 struct stat *buf;
260 {
261 struct ar_hdr *hdr;
262 char *aloser;
263
264 if (abfd->arelt_data == NULL) {
265 bfd_error = invalid_operation;
266 return -1;
267 }
268
269 hdr = arch_hdr (abfd);
270
271 #define foo(arelt, stelt, size) \
272 buf->stelt = strtol (hdr->arelt, &aloser, size); \
273 if (aloser == hdr->arelt) return -1;
274
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);
280 #undef foo
281
282 return 0;
283 }
284
285 static boolean
286 rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
287 bfd *arch;
288 unsigned int elength;
289 struct orl *map;
290 {
291 bfd_error = invalid_operation;
292 return false;
293 }
294 #endif /* ARCHIVES_PLEASE */
295
296 \f
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 ();
301
302 #undef coff_core_file_matches_executable_p
303 #define coff_core_file_matches_executable_p \
304 rs6000coff_core_file_matches_executable_p
305
306 #undef coff_get_section_contents
307 #define coff_get_section_contents rs6000coff_get_section_contents
308 #endif
309
310 /* The transfer vector that leads the outside world to all of the above. */
311
312 bfd_target rs6000coff_vec =
313 {
314 "aixcoff-rs6000", /* name */
315 bfd_target_coff_flavour,
316 true, /* data byte order is big */
317 true, /* header byte order is big */
318
319 (HAS_RELOC | EXEC_P | /* object flags */
320 HAS_LINENO | HAS_DEBUG |
321 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
322
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 */
328
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 */
331
332 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
333 coff_archive_p,
334 #ifdef COREFILES_PLEASE
335 rs6000coff_core_p
336 #else
337 _bfd_dummy_target
338 #endif
339 },
340 {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
341 bfd_false},
342 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
343 _bfd_write_archive_contents, bfd_false},
344
345 JUMP_TABLE(coff),
346 COFF_SWAP_TABLE
347 };
This page took 0.036175 seconds and 4 git commands to generate.