]>
Commit | Line | Data |
---|---|---|
f4bd7a8f | 1 | /* BFD back-end for IBM RS/6000 "XCOFF" files. |
8b8ddedb | 2 | Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. |
f4bd7a8f DM |
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 | ||
12 | This file is part of BFD, the Binary File Descriptor library. | |
13 | ||
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. | |
18 | ||
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. | |
23 | ||
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. */ | |
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 | |
8b8ddedb SG |
47 | /* The XCOFF reloc table. Actually, XCOFF relocations specify the |
48 | bitsize and whether they are signed or not, along with a | |
49 | conventional type. This table is for the types, which are used for | |
50 | different algorithms for putting in the reloc. Many of these | |
51 | relocs need special_function entries, which I have not written. */ | |
52 | ||
53 | static reloc_howto_type rs6000coff_howto_table[] = | |
54 | { | |
55 | /* Standard 32 bit relocation. */ | |
56 | HOWTO (0, /* type */ | |
57 | 0, /* rightshift */ | |
58 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
59 | 32, /* bitsize */ | |
60 | false, /* pc_relative */ | |
61 | 0, /* bitpos */ | |
62 | complain_overflow_bitfield, /* complain_on_overflow */ | |
63 | 0, /* special_function */ | |
64 | "R_POS", /* name */ | |
65 | true, /* partial_inplace */ | |
66 | 0xffffffff, /* src_mask */ | |
67 | 0xffffffff, /* dst_mask */ | |
68 | false), /* pcrel_offset */ | |
69 | ||
70 | /* 32 bit relocation, but store negative value. */ | |
71 | HOWTO (1, /* type */ | |
72 | 0, /* rightshift */ | |
73 | -2, /* size (0 = byte, 1 = short, 2 = long) */ | |
74 | 32, /* bitsize */ | |
75 | false, /* pc_relative */ | |
76 | 0, /* bitpos */ | |
77 | complain_overflow_bitfield, /* complain_on_overflow */ | |
78 | 0, /* special_function */ | |
79 | "R_NEG", /* name */ | |
80 | true, /* partial_inplace */ | |
81 | 0xffffffff, /* src_mask */ | |
82 | 0xffffffff, /* dst_mask */ | |
83 | false), /* pcrel_offset */ | |
84 | ||
85 | /* 32 bit PC relative relocation. */ | |
86 | HOWTO (2, /* type */ | |
87 | 0, /* rightshift */ | |
88 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
89 | 32, /* bitsize */ | |
90 | true, /* pc_relative */ | |
91 | 0, /* bitpos */ | |
92 | complain_overflow_signed, /* complain_on_overflow */ | |
93 | 0, /* special_function */ | |
94 | "R_REL", /* name */ | |
95 | true, /* partial_inplace */ | |
96 | 0xffffffff, /* src_mask */ | |
97 | 0xffffffff, /* dst_mask */ | |
98 | false), /* pcrel_offset */ | |
99 | ||
100 | /* 16 bit TOC relative relocation. */ | |
101 | HOWTO (3, /* type */ | |
102 | 0, /* rightshift */ | |
103 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
104 | 16, /* bitsize */ | |
105 | false, /* pc_relative */ | |
106 | 0, /* bitpos */ | |
107 | complain_overflow_signed, /* complain_on_overflow */ | |
108 | 0, /* special_function */ | |
109 | "R_TOC", /* name */ | |
110 | true, /* partial_inplace */ | |
111 | 0xffff, /* src_mask */ | |
112 | 0xffff, /* dst_mask */ | |
113 | false), /* pcrel_offset */ | |
114 | ||
115 | /* I don't really know what this is. */ | |
116 | HOWTO (4, /* type */ | |
117 | 1, /* rightshift */ | |
118 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
119 | 32, /* bitsize */ | |
120 | false, /* pc_relative */ | |
121 | 0, /* bitpos */ | |
122 | complain_overflow_bitfield, /* complain_on_overflow */ | |
123 | 0, /* special_function */ | |
124 | "R_RTB", /* name */ | |
125 | true, /* partial_inplace */ | |
126 | 0xffffffff, /* src_mask */ | |
127 | 0xffffffff, /* dst_mask */ | |
128 | false), /* pcrel_offset */ | |
129 | ||
130 | /* External TOC relative symbol. */ | |
131 | HOWTO (5, /* type */ | |
132 | 0, /* rightshift */ | |
133 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
134 | 16, /* bitsize */ | |
135 | false, /* pc_relative */ | |
136 | 0, /* bitpos */ | |
137 | complain_overflow_bitfield, /* complain_on_overflow */ | |
138 | 0, /* special_function */ | |
139 | "R_GL", /* name */ | |
140 | true, /* partial_inplace */ | |
141 | 0xffff, /* src_mask */ | |
142 | 0xffff, /* dst_mask */ | |
143 | false), /* pcrel_offset */ | |
144 | ||
145 | /* Local TOC relative symbol. */ | |
146 | HOWTO (6, /* type */ | |
147 | 0, /* rightshift */ | |
148 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
149 | 16, /* bitsize */ | |
150 | false, /* pc_relative */ | |
151 | 0, /* bitpos */ | |
152 | complain_overflow_bitfield, /* complain_on_overflow */ | |
153 | 0, /* special_function */ | |
154 | "R_TCL", /* name */ | |
155 | true, /* partial_inplace */ | |
156 | 0xffff, /* src_mask */ | |
157 | 0xffff, /* dst_mask */ | |
158 | false), /* pcrel_offset */ | |
159 | ||
160 | { 7 }, | |
161 | ||
162 | /* Non modifiable absolute branch. */ | |
163 | HOWTO (8, /* type */ | |
164 | 0, /* rightshift */ | |
165 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
166 | 26, /* bitsize */ | |
167 | false, /* pc_relative */ | |
168 | 0, /* bitpos */ | |
169 | complain_overflow_bitfield, /* complain_on_overflow */ | |
170 | 0, /* special_function */ | |
171 | "R_BA", /* name */ | |
172 | true, /* partial_inplace */ | |
173 | 0x3fffffc, /* src_mask */ | |
174 | 0x3fffffc, /* dst_mask */ | |
175 | false), /* pcrel_offset */ | |
176 | ||
177 | { 9 }, | |
178 | ||
179 | /* Non modifiable relative branch. */ | |
180 | HOWTO (0xa, /* type */ | |
181 | 0, /* rightshift */ | |
182 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
183 | 26, /* bitsize */ | |
184 | true, /* pc_relative */ | |
185 | 0, /* bitpos */ | |
186 | complain_overflow_signed, /* complain_on_overflow */ | |
187 | 0, /* special_function */ | |
188 | "R_BR", /* name */ | |
189 | true, /* partial_inplace */ | |
190 | 0x3fffffc, /* src_mask */ | |
191 | 0x3fffffc, /* dst_mask */ | |
192 | false), /* pcrel_offset */ | |
193 | ||
194 | { 0xb }, | |
195 | ||
196 | /* Indirect load. */ | |
197 | HOWTO (0xc, /* type */ | |
198 | 0, /* rightshift */ | |
199 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
200 | 16, /* bitsize */ | |
201 | false, /* pc_relative */ | |
202 | 0, /* bitpos */ | |
203 | complain_overflow_bitfield, /* complain_on_overflow */ | |
204 | 0, /* special_function */ | |
205 | "R_RL", /* name */ | |
206 | true, /* partial_inplace */ | |
207 | 0xffff, /* src_mask */ | |
208 | 0xffff, /* dst_mask */ | |
209 | false), /* pcrel_offset */ | |
210 | ||
211 | /* Load address. */ | |
212 | HOWTO (0xd, /* type */ | |
213 | 0, /* rightshift */ | |
214 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
215 | 16, /* bitsize */ | |
216 | false, /* pc_relative */ | |
217 | 0, /* bitpos */ | |
218 | complain_overflow_bitfield, /* complain_on_overflow */ | |
219 | 0, /* special_function */ | |
220 | "R_RLA", /* name */ | |
221 | true, /* partial_inplace */ | |
222 | 0xffff, /* src_mask */ | |
223 | 0xffff, /* dst_mask */ | |
224 | false), /* pcrel_offset */ | |
225 | ||
226 | { 0xe }, | |
227 | ||
228 | /* Non-relocating reference. */ | |
229 | HOWTO (0xf, /* type */ | |
230 | 0, /* rightshift */ | |
231 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
232 | 32, /* bitsize */ | |
233 | false, /* pc_relative */ | |
234 | 0, /* bitpos */ | |
235 | complain_overflow_bitfield, /* complain_on_overflow */ | |
236 | 0, /* special_function */ | |
237 | "R_REF", /* name */ | |
238 | false, /* partial_inplace */ | |
239 | 0, /* src_mask */ | |
240 | 0, /* dst_mask */ | |
241 | false), /* pcrel_offset */ | |
242 | ||
243 | { 0x10 }, | |
244 | { 0x11 }, | |
245 | ||
246 | /* TOC relative indirect load. */ | |
247 | HOWTO (0x12, /* type */ | |
248 | 0, /* rightshift */ | |
249 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
250 | 16, /* bitsize */ | |
251 | false, /* pc_relative */ | |
252 | 0, /* bitpos */ | |
253 | complain_overflow_bitfield, /* complain_on_overflow */ | |
254 | 0, /* special_function */ | |
255 | "R_TRL", /* name */ | |
256 | true, /* partial_inplace */ | |
257 | 0xffff, /* src_mask */ | |
258 | 0xffff, /* dst_mask */ | |
259 | false), /* pcrel_offset */ | |
260 | ||
261 | /* TOC relative load address. */ | |
262 | HOWTO (0x13, /* type */ | |
263 | 0, /* rightshift */ | |
264 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
265 | 16, /* bitsize */ | |
266 | false, /* pc_relative */ | |
267 | 0, /* bitpos */ | |
268 | complain_overflow_bitfield, /* complain_on_overflow */ | |
269 | 0, /* special_function */ | |
270 | "R_TRLA", /* name */ | |
271 | true, /* partial_inplace */ | |
272 | 0xffff, /* src_mask */ | |
273 | 0xffff, /* dst_mask */ | |
274 | false), /* pcrel_offset */ | |
275 | ||
276 | /* Modifiable relative branch. */ | |
277 | HOWTO (0x14, /* type */ | |
278 | 1, /* rightshift */ | |
279 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
280 | 32, /* bitsize */ | |
281 | false, /* pc_relative */ | |
282 | 0, /* bitpos */ | |
283 | complain_overflow_bitfield, /* complain_on_overflow */ | |
284 | 0, /* special_function */ | |
285 | "R_RRTBI", /* name */ | |
286 | true, /* partial_inplace */ | |
287 | 0xffffffff, /* src_mask */ | |
288 | 0xffffffff, /* dst_mask */ | |
289 | false), /* pcrel_offset */ | |
290 | ||
291 | /* Modifiable absolute branch. */ | |
292 | HOWTO (0x15, /* type */ | |
293 | 1, /* rightshift */ | |
294 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
295 | 32, /* bitsize */ | |
296 | false, /* pc_relative */ | |
297 | 0, /* bitpos */ | |
298 | complain_overflow_bitfield, /* complain_on_overflow */ | |
299 | 0, /* special_function */ | |
300 | "R_RRTBA", /* name */ | |
301 | true, /* partial_inplace */ | |
302 | 0xffffffff, /* src_mask */ | |
303 | 0xffffffff, /* dst_mask */ | |
304 | false), /* pcrel_offset */ | |
305 | ||
306 | /* Modifiable call absolute indirect. */ | |
307 | HOWTO (0x16, /* type */ | |
308 | 0, /* rightshift */ | |
309 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
310 | 16, /* bitsize */ | |
311 | false, /* pc_relative */ | |
312 | 0, /* bitpos */ | |
313 | complain_overflow_bitfield, /* complain_on_overflow */ | |
314 | 0, /* special_function */ | |
315 | "R_CAI", /* name */ | |
316 | true, /* partial_inplace */ | |
317 | 0xffff, /* src_mask */ | |
318 | 0xffff, /* dst_mask */ | |
319 | false), /* pcrel_offset */ | |
320 | ||
321 | /* Modifiable call relative. */ | |
322 | HOWTO (0x17, /* type */ | |
323 | 0, /* rightshift */ | |
324 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
325 | 16, /* bitsize */ | |
326 | false, /* pc_relative */ | |
327 | 0, /* bitpos */ | |
328 | complain_overflow_bitfield, /* complain_on_overflow */ | |
329 | 0, /* special_function */ | |
330 | "R_REL", /* name */ | |
331 | true, /* partial_inplace */ | |
332 | 0xffff, /* src_mask */ | |
333 | 0xffff, /* dst_mask */ | |
334 | false), /* pcrel_offset */ | |
335 | ||
336 | /* Modifiable branch absolute. */ | |
337 | HOWTO (0x18, /* type */ | |
338 | 0, /* rightshift */ | |
339 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
340 | 16, /* bitsize */ | |
341 | false, /* pc_relative */ | |
342 | 0, /* bitpos */ | |
343 | complain_overflow_bitfield, /* complain_on_overflow */ | |
344 | 0, /* special_function */ | |
345 | "R_RBA", /* name */ | |
346 | true, /* partial_inplace */ | |
347 | 0xffff, /* src_mask */ | |
348 | 0xffff, /* dst_mask */ | |
349 | false), /* pcrel_offset */ | |
350 | ||
351 | /* Modifiable branch absolute. */ | |
352 | HOWTO (0x19, /* type */ | |
353 | 0, /* rightshift */ | |
354 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
355 | 16, /* bitsize */ | |
356 | false, /* pc_relative */ | |
357 | 0, /* bitpos */ | |
358 | complain_overflow_bitfield, /* complain_on_overflow */ | |
359 | 0, /* special_function */ | |
360 | "R_RBAC", /* name */ | |
361 | true, /* partial_inplace */ | |
362 | 0xffff, /* src_mask */ | |
363 | 0xffff, /* dst_mask */ | |
364 | false), /* pcrel_offset */ | |
365 | ||
366 | /* Modifiable branch relative. */ | |
367 | HOWTO (0x1a, /* type */ | |
368 | 0, /* rightshift */ | |
369 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
370 | 26, /* bitsize */ | |
371 | false, /* pc_relative */ | |
372 | 0, /* bitpos */ | |
373 | complain_overflow_signed, /* complain_on_overflow */ | |
374 | 0, /* special_function */ | |
375 | "R_REL", /* name */ | |
376 | true, /* partial_inplace */ | |
377 | 0xffff, /* src_mask */ | |
378 | 0xffff, /* dst_mask */ | |
379 | false), /* pcrel_offset */ | |
380 | ||
381 | /* Modifiable branch absolute. */ | |
382 | HOWTO (0x1b, /* type */ | |
383 | 0, /* rightshift */ | |
384 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
385 | 16, /* bitsize */ | |
386 | false, /* pc_relative */ | |
387 | 0, /* bitpos */ | |
388 | complain_overflow_bitfield, /* complain_on_overflow */ | |
389 | 0, /* special_function */ | |
390 | "R_REL", /* name */ | |
391 | true, /* partial_inplace */ | |
392 | 0xffff, /* src_mask */ | |
393 | 0xffff, /* dst_mask */ | |
394 | false) /* pcrel_offset */ | |
395 | }; | |
396 | ||
397 | #define RTYPE2HOWTO(cache_ptr, dst) rs6000coff_rtype2howto (cache_ptr, dst) | |
398 | ||
399 | static void rs6000coff_rtype2howto PARAMS ((arelent *, | |
400 | struct internal_reloc *)); | |
401 | ||
402 | static void | |
403 | rs6000coff_rtype2howto (relent, internal) | |
404 | arelent *relent; | |
405 | struct internal_reloc *internal; | |
406 | { | |
407 | relent->howto = rs6000coff_howto_table + internal->r_type; | |
408 | ||
409 | /* The r_size field of an XCOFF reloc encodes the bitsize of the | |
410 | relocation, as well as indicating whether it is signed or not. | |
411 | Doublecheck that the relocation information gathered from the | |
412 | type matches this information. */ | |
413 | if (relent->howto->bitsize != (internal->r_size & 0x1f) + 1) | |
414 | abort (); | |
415 | #if 0 | |
416 | if ((internal->r_size & 0x80) != 0 | |
417 | ? (relent->howto->complain_on_overflow != complain_overflow_signed) | |
418 | : (relent->howto->complain_on_overflow != complain_overflow_bitfield)) | |
419 | abort (); | |
420 | #endif | |
421 | } | |
422 | ||
423 | #define coff_bfd_reloc_type_lookup rs6000coff_reloc_type_lookup | |
424 | ||
425 | static const struct reloc_howto_struct *rs6000coff_reloc_type_lookup | |
426 | PARAMS ((bfd *, bfd_reloc_code_real_type)); | |
427 | ||
428 | static const struct reloc_howto_struct * | |
429 | rs6000coff_reloc_type_lookup (abfd, code) | |
430 | bfd *abfd; | |
431 | bfd_reloc_code_real_type code; | |
432 | { | |
433 | switch (code) | |
434 | { | |
435 | case BFD_RELOC_PPC_B26: | |
436 | return &rs6000coff_howto_table[0xa]; | |
437 | case BFD_RELOC_PPC_BA26: | |
438 | return &rs6000coff_howto_table[8]; | |
439 | case BFD_RELOC_PPC_TOC16: | |
440 | return &rs6000coff_howto_table[3]; | |
441 | case BFD_RELOC_32: | |
442 | return &rs6000coff_howto_table[0]; | |
443 | default: | |
444 | return NULL; | |
445 | } | |
446 | } | |
447 | ||
448 | #define SELECT_RELOC(internal, howto) \ | |
449 | { \ | |
450 | internal.r_type = howto->type; \ | |
451 | internal.r_size = \ | |
452 | ((howto->complain_on_overflow == complain_overflow_signed \ | |
453 | ? 0x80 \ | |
454 | : 0) \ | |
455 | | (howto->bitsize - 1)); \ | |
456 | } | |
457 | ||
458 | #define COFF_LONG_FILENAMES | |
f4bd7a8f | 459 | |
c9301d7b | 460 | #include "coffcode.h" |
ba9137fe | 461 | |
c9301d7b SC |
462 | #define coff_archive_p bfd_generic_archive_p |
463 | #define coff_mkarchive _bfd_generic_mkarchive | |
ba9137fe | 464 | |
8b8ddedb | 465 | #ifdef HOST_AIX |
ba9137fe | 466 | |
c9301d7b SC |
467 | /* ------------------------------------------------------------------------ */ |
468 | /* Support for archive file stuff.. */ | |
469 | /* Stolen from Damon A. Permezel's `bfd' portation. */ | |
470 | /* ------------------------------------------------------------------------ */ | |
ba9137fe | 471 | |
6812b607 ILT |
472 | #define rs6000coff_slurp_armap bfd_slurp_coff_armap |
473 | #define rs6000coff_slurp_extended_name_table _bfd_slurp_extended_name_table | |
474 | #define rs6000coff_truncate_arname bfd_dont_truncate_arname | |
ba9137fe | 475 | |
c9301d7b SC |
476 | #undef coff_mkarchive |
477 | #define coff_mkarchive rs6000coff_mkarchive | |
ba9137fe | 478 | |
c9301d7b SC |
479 | #undef coff_archive_p |
480 | #define coff_archive_p rs6000coff_archive_p | |
ba9137fe JG |
481 | |
482 | #include "/usr/include/ar.h" /* <ar.h> doesn't do it. */ | |
483 | ||
484 | ||
485 | #define arch_hdr(bfd) \ | |
486 | ((struct ar_hdr *) \ | |
487 | (((struct areltdata *)((bfd)->arelt_data))->arch_header)) | |
488 | ||
489 | ||
490 | static boolean | |
491 | rs6000coff_mkarchive (abfd) | |
492 | bfd *abfd; | |
493 | { | |
25057836 | 494 | bfd_set_error (bfd_error_invalid_operation); /* write not supported */ |
8b8ddedb | 495 | return false; |
ba9137fe JG |
496 | } |
497 | ||
498 | ||
499 | /* This functions reads an arch header and returns an areltdata pointer, or | |
500 | NULL on error. | |
501 | ||
502 | Presumes the file pointer is already in the right place (ie pointing | |
503 | to the ar_hdr in the file). Moves the file pointer; on success it | |
504 | should be pointing to the front of the file contents; on failure it | |
505 | could have been moved arbitrarily. | |
506 | */ | |
507 | ||
508 | struct areltdata * | |
509 | rs6000coff_snarf_ar_hdr (abfd) | |
510 | bfd *abfd; | |
511 | { | |
ba9137fe JG |
512 | struct { |
513 | struct ar_hdr hdr; | |
514 | char namebuf[256]; | |
515 | } h; | |
516 | int size; | |
517 | struct areltdata *ared; | |
ba9137fe JG |
518 | char *allocptr; |
519 | ||
520 | size = sizeof (h.hdr); | |
521 | if (bfd_read(&h.hdr, 1, size, abfd) != size) { | |
4002f18a ILT |
522 | if (bfd_get_error () != bfd_error_system_call) |
523 | bfd_set_error (bfd_error_no_more_archived_files); | |
ba9137fe JG |
524 | return NULL; |
525 | } | |
526 | size = atoi(h.hdr.ar_namlen); /* ar_name[] length */ | |
527 | size += size & 1; | |
528 | ||
529 | if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) { | |
4002f18a ILT |
530 | if (bfd_get_error () != bfd_error_system_call) |
531 | bfd_set_error (bfd_error_no_more_archived_files); | |
ba9137fe JG |
532 | return NULL; |
533 | } | |
534 | ||
535 | if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) { | |
25057836 | 536 | bfd_set_error (bfd_error_malformed_archive); |
ba9137fe JG |
537 | return NULL; |
538 | } | |
539 | ||
540 | h.hdr._ar_name.ar_name[size] = 0; /* terminate filename */ | |
541 | ||
542 | /* | |
543 | * if the filename is NULL, we're (probably) at the end. | |
544 | */ | |
545 | if (size == 0) { | |
25057836 | 546 | bfd_set_error (bfd_error_no_more_archived_files); |
ba9137fe JG |
547 | return NULL; |
548 | } | |
549 | ||
550 | size += sizeof (h.hdr); | |
551 | allocptr = bfd_zalloc(abfd, sizeof (*ared) + size); | |
552 | ||
553 | if (allocptr == NULL) { | |
25057836 | 554 | bfd_set_error (bfd_error_no_memory); |
ba9137fe JG |
555 | return NULL; |
556 | } | |
557 | ||
558 | ared = (struct areltdata *) allocptr; | |
559 | ||
560 | ared->arch_header = (void *) (allocptr + sizeof (struct areltdata)); | |
561 | memcpy ((char *) ared->arch_header, &h.hdr, size); | |
562 | ared->parsed_size = atoi(h.hdr.ar_size); | |
563 | ared->filename = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name; | |
564 | ||
565 | return ared; | |
566 | } | |
567 | ||
c9301d7b SC |
568 | /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr. |
569 | Why wasn't this part of the transfer vector? */ | |
570 | ||
571 | bfd * | |
572 | rs6000coff_get_elt_at_filepos (archive, filepos) | |
573 | bfd *archive; | |
574 | file_ptr filepos; | |
575 | { | |
576 | struct areltdata *new_areldata; | |
577 | bfd *n_nfd; | |
578 | ||
f4bd7a8f | 579 | n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos); |
c9301d7b SC |
580 | if (n_nfd) return n_nfd; |
581 | ||
25057836 | 582 | if (0 != bfd_seek (archive, filepos, SEEK_SET)) |
c9301d7b | 583 | return NULL; |
c9301d7b SC |
584 | |
585 | if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL; | |
586 | ||
587 | n_nfd = _bfd_create_empty_archive_element_shell (archive); | |
588 | if (n_nfd == NULL) { | |
589 | bfd_release (archive, (PTR)new_areldata); | |
590 | return NULL; | |
591 | } | |
592 | n_nfd->origin = bfd_tell (archive); | |
593 | n_nfd->arelt_data = (PTR) new_areldata; | |
594 | n_nfd->filename = new_areldata->filename; | |
595 | ||
f4bd7a8f | 596 | if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd)) |
c9301d7b SC |
597 | return n_nfd; |
598 | ||
599 | /* huh? */ | |
600 | bfd_release (archive, (PTR)n_nfd); | |
601 | bfd_release (archive, (PTR)new_areldata); | |
602 | return NULL; | |
603 | } | |
604 | ||
ba9137fe JG |
605 | /* |
606 | * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs. | |
607 | */ | |
608 | static bfd * | |
609 | rs6000coff_openr_next_archived_file(archive, last_file) | |
610 | bfd *archive, *last_file; | |
611 | { | |
612 | file_ptr filestart; | |
613 | ||
614 | if (!last_file) | |
615 | filestart = bfd_ardata(archive)->first_file_filepos; | |
616 | else | |
617 | filestart = atol(arch_hdr(last_file)->ar_nxtmem); | |
618 | ||
c9301d7b | 619 | return rs6000coff_get_elt_at_filepos (archive, filestart); |
ba9137fe JG |
620 | } |
621 | ||
622 | ||
623 | static bfd_target * | |
624 | rs6000coff_archive_p (abfd) | |
625 | bfd *abfd; | |
626 | { | |
627 | struct fl_hdr hdr; | |
628 | register struct artdata *art; | |
629 | ||
c9301d7b | 630 | if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) { |
4002f18a ILT |
631 | if (bfd_get_error () != bfd_error_system_call) |
632 | bfd_set_error (bfd_error_wrong_format); | |
ba9137fe JG |
633 | return 0; |
634 | } | |
635 | ||
636 | if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) { | |
25057836 | 637 | bfd_set_error (bfd_error_wrong_format); |
ba9137fe JG |
638 | return 0; |
639 | } | |
640 | ||
641 | /* | |
642 | * bfd_ardata() accesses the bfd->tdata field. | |
643 | */ | |
294eaca4 SC |
644 | abfd->tdata.aout_ar_data = |
645 | (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr)); | |
ba9137fe | 646 | if ((art = bfd_ardata (abfd)) == NULL) { |
25057836 | 647 | bfd_set_error (bfd_error_no_memory); |
ba9137fe JG |
648 | return 0; |
649 | } | |
650 | ||
651 | art->first_file_filepos = atoi(hdr.fl_fstmoff); | |
652 | *(struct fl_hdr *) (1 + art) = hdr; | |
653 | ||
c9301d7b SC |
654 | /* Someday... |
655 | * slurp in the member table, which I think is the armap equivalent. | |
ba9137fe JG |
656 | xcoff_slurp_armap(abfd); |
657 | */ | |
658 | ||
ba9137fe JG |
659 | return abfd->xvec; |
660 | } | |
661 | ||
662 | ||
663 | static int | |
6812b607 | 664 | rs6000coff_generic_stat_arch_elt(abfd, buf) |
ba9137fe JG |
665 | bfd *abfd; |
666 | struct stat *buf; | |
667 | { | |
668 | struct ar_hdr *hdr; | |
669 | char *aloser; | |
670 | ||
671 | if (abfd->arelt_data == NULL) { | |
25057836 | 672 | bfd_set_error (bfd_error_invalid_operation); |
ba9137fe JG |
673 | return -1; |
674 | } | |
675 | ||
676 | hdr = arch_hdr (abfd); | |
677 | ||
678 | #define foo(arelt, stelt, size) \ | |
679 | buf->stelt = strtol (hdr->arelt, &aloser, size); \ | |
680 | if (aloser == hdr->arelt) return -1; | |
681 | ||
682 | foo (ar_date, st_mtime, 10); | |
683 | foo (ar_uid, st_uid, 10); | |
684 | foo (ar_gid, st_gid, 10); | |
685 | foo (ar_mode, st_mode, 8); | |
686 | foo (ar_size, st_size, 10); | |
c9301d7b | 687 | #undef foo |
ba9137fe JG |
688 | |
689 | return 0; | |
690 | } | |
691 | ||
692 | static boolean | |
693 | rs6000coff_write_armap (arch, elength, map, orl_count, stridx) | |
694 | bfd *arch; | |
695 | unsigned int elength; | |
696 | struct orl *map; | |
8b8ddedb SG |
697 | unsigned int orl_count; |
698 | int stridx; | |
ba9137fe | 699 | { |
25057836 | 700 | bfd_set_error (bfd_error_invalid_operation); |
ba9137fe JG |
701 | return false; |
702 | } | |
8b8ddedb | 703 | #endif /* HOST_AIX */ |
c9301d7b | 704 | |
294eaca4 | 705 | \f |
8b8ddedb SG |
706 | #define CORE_FILE_P _bfd_dummy_target |
707 | ||
6812b607 ILT |
708 | #define coff_core_file_failing_command _bfd_nocore_core_file_failing_command |
709 | #define coff_core_file_failing_signal _bfd_nocore_core_file_failing_signal | |
710 | #define coff_core_file_matches_executable_p \ | |
711 | _bfd_nocore_core_file_matches_executable_p | |
712 | ||
8b8ddedb SG |
713 | #ifdef HOST_AIX |
714 | #undef CORE_FILE_P | |
715 | #define CORE_FILE_P rs6000coff_core_p | |
294eaca4 SC |
716 | extern bfd_target * rs6000coff_core_p (); |
717 | extern boolean rs6000coff_get_section_contents (); | |
718 | extern boolean rs6000coff_core_file_matches_executable_p (); | |
c9301d7b SC |
719 | |
720 | #undef coff_core_file_matches_executable_p | |
721 | #define coff_core_file_matches_executable_p \ | |
722 | rs6000coff_core_file_matches_executable_p | |
ba9137fe | 723 | |
c9301d7b SC |
724 | #undef coff_get_section_contents |
725 | #define coff_get_section_contents rs6000coff_get_section_contents | |
8b8ddedb SG |
726 | #endif /* HOST_AIX */ |
727 | ||
728 | #ifdef HOST_LYNX | |
729 | ||
730 | #undef CORE_FILE_P | |
731 | #define CORE_FILE_P lynx_core_file_p | |
732 | extern bfd_target *lynx_core_file_p PARAMS ((bfd *abfd)); | |
733 | ||
734 | extern boolean lynx_core_file_matches_executable_p PARAMS ((bfd *core_bfd, | |
735 | bfd *exec_bfd)); | |
736 | #undef coff_core_file_matches_executable_p | |
737 | #define coff_core_file_matches_executable_p lynx_core_file_matches_executable_p | |
738 | ||
739 | extern char *lynx_core_file_failing_command PARAMS ((bfd *abfd)); | |
740 | #undef coff_core_file_failing_command | |
741 | #define coff_core_file_failing_command lynx_core_file_failing_command | |
742 | ||
743 | extern int lynx_core_file_failing_signal PARAMS ((bfd *abfd)); | |
744 | #undef coff_core_file_failing_signal | |
745 | #define coff_core_file_failing_signal lynx_core_file_failing_signal | |
746 | ||
747 | #endif /* HOST_LYNX */ | |
ba9137fe | 748 | |
c9301d7b SC |
749 | /* The transfer vector that leads the outside world to all of the above. */ |
750 | ||
751 | bfd_target rs6000coff_vec = | |
752 | { | |
753 | "aixcoff-rs6000", /* name */ | |
754 | bfd_target_coff_flavour, | |
755 | true, /* data byte order is big */ | |
756 | true, /* header byte order is big */ | |
757 | ||
758 | (HAS_RELOC | EXEC_P | /* object flags */ | |
759 | HAS_LINENO | HAS_DEBUG | | |
f4bd7a8f | 760 | HAS_SYMS | HAS_LOCALS | WP_TEXT), |
c9301d7b SC |
761 | |
762 | (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ | |
294eaca4 | 763 | 0, /* leading char */ |
c9301d7b SC |
764 | '/', /* ar_pad_char */ |
765 | 15, /* ar_max_namelen??? FIXMEmgo */ | |
766 | 3, /* default alignment power */ | |
767 | ||
f4bd7a8f DM |
768 | bfd_getb64, bfd_getb_signed_64, bfd_putb64, |
769 | bfd_getb32, bfd_getb_signed_32, bfd_putb32, | |
770 | bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ | |
771 | bfd_getb64, bfd_getb_signed_64, bfd_putb64, | |
772 | bfd_getb32, bfd_getb_signed_32, bfd_putb32, | |
773 | bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ | |
c9301d7b SC |
774 | |
775 | {_bfd_dummy_target, coff_object_p, /* bfd_check_format */ | |
8b8ddedb | 776 | coff_archive_p, CORE_FILE_P}, |
c9301d7b SC |
777 | {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */ |
778 | bfd_false}, | |
779 | {bfd_false, coff_write_object_contents, /* bfd_write_contents */ | |
780 | _bfd_write_archive_contents, bfd_false}, | |
781 | ||
6812b607 ILT |
782 | BFD_JUMP_TABLE_GENERIC (coff), |
783 | BFD_JUMP_TABLE_COPY (coff), | |
784 | BFD_JUMP_TABLE_CORE (coff), | |
785 | #ifdef HOST_AIX | |
786 | BFD_JUMP_TABLE_ARCHIVE (rs6000coff), | |
787 | #else | |
788 | BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), | |
789 | #endif | |
790 | BFD_JUMP_TABLE_SYMBOLS (coff), | |
791 | BFD_JUMP_TABLE_RELOCS (coff), | |
792 | BFD_JUMP_TABLE_WRITE (coff), | |
793 | BFD_JUMP_TABLE_LINK (coff), | |
794 | ||
f4bd7a8f | 795 | COFF_SWAP_TABLE, |
c9301d7b | 796 | }; |