* targets.c (bfd_target): Rearranged fields in target vector.
[external/binutils.git] / bfd / coff-rs6000.c
1 /* BFD back-end for IBM RS/6000 "XCOFF" files.
2    Copyright 1990, 1991, 1992, 1993, 1994 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.
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
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.  */
33
34 /* Internalcoff.h and coffcode.h modify themselves based on this flag.  */
35 #define RS6000COFF_C 1
36
37 #include "bfd.h"
38 #include "sysdep.h"
39 #include "libbfd.h"
40 #include "obstack.h"
41 #include "coff/internal.h"
42 #include "coff/rs6000.h"
43 #include "libcoff.h"
44
45 /* The main body of code is in coffcode.h.  */
46
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
459
460 #include "coffcode.h"
461
462 #define coff_archive_p          bfd_generic_archive_p
463 #define coff_mkarchive          _bfd_generic_mkarchive
464
465 #ifdef HOST_AIX
466
467 /* ------------------------------------------------------------------------ */
468 /*      Support for archive file stuff..                                    */
469 /*      Stolen from Damon A. Permezel's `bfd' portation.                    */
470 /* ------------------------------------------------------------------------ */
471
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
475
476 #undef  coff_mkarchive
477 #define coff_mkarchive                  rs6000coff_mkarchive
478
479 #undef  coff_archive_p
480 #define coff_archive_p                  rs6000coff_archive_p
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 {
494         bfd_set_error (bfd_error_invalid_operation);    /* write not supported  */
495         return false;
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 {
512         struct {
513                 struct ar_hdr hdr;
514                 char namebuf[256];
515         } h;
516         int size;
517         struct areltdata *ared;
518         char *allocptr;
519
520         size = sizeof (h.hdr);
521         if (bfd_read(&h.hdr, 1, size, abfd) != size) {
522                 if (bfd_get_error () != bfd_error_system_call)
523                   bfd_set_error (bfd_error_no_more_archived_files);
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) {
530                 if (bfd_get_error () != bfd_error_system_call)
531                   bfd_set_error (bfd_error_no_more_archived_files);
532                 return NULL;
533         }
534
535         if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
536                 bfd_set_error (bfd_error_malformed_archive);
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) {
546                 bfd_set_error (bfd_error_no_more_archived_files);
547                 return NULL;
548         }
549
550         size += sizeof (h.hdr);
551         allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
552
553         if (allocptr == NULL) {
554                 bfd_set_error (bfd_error_no_memory);
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
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
579   n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
580   if (n_nfd) return n_nfd;
581
582   if (0 != bfd_seek (archive, filepos, SEEK_SET))
583     return NULL;
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
596   if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
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
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
619         return rs6000coff_get_elt_at_filepos (archive, filestart);
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
630         if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
631                 if (bfd_get_error () != bfd_error_system_call)
632                   bfd_set_error (bfd_error_wrong_format);
633                 return 0;
634         }
635
636         if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
637                 bfd_set_error (bfd_error_wrong_format);
638                 return 0;
639         }
640
641         /*
642          * bfd_ardata() accesses the bfd->tdata field.
643          */
644         abfd->tdata.aout_ar_data =
645           (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
646         if ((art = bfd_ardata (abfd)) == NULL) {
647                 bfd_set_error (bfd_error_no_memory);
648                 return 0;
649         }
650
651         art->first_file_filepos = atoi(hdr.fl_fstmoff);
652         *(struct fl_hdr *) (1 + art) = hdr;
653
654         /* Someday...
655          * slurp in the member table, which I think is the armap equivalent.
656         xcoff_slurp_armap(abfd);
657          */
658   
659         return abfd->xvec;
660 }
661
662
663 static int
664 rs6000coff_generic_stat_arch_elt(abfd, buf)
665   bfd *abfd;
666   struct stat *buf;
667 {
668         struct ar_hdr *hdr;
669         char *aloser;
670   
671         if (abfd->arelt_data == NULL) {
672                 bfd_set_error (bfd_error_invalid_operation);
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);
687 #undef foo
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; 
697   unsigned int orl_count;
698   int stridx;
699 {
700         bfd_set_error (bfd_error_invalid_operation);
701         return false;
702 }
703 #endif  /* HOST_AIX */
704
705 \f
706 #define CORE_FILE_P _bfd_dummy_target
707
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
713 #ifdef HOST_AIX
714 #undef CORE_FILE_P
715 #define CORE_FILE_P rs6000coff_core_p
716 extern bfd_target * rs6000coff_core_p ();
717 extern boolean rs6000coff_get_section_contents ();
718 extern boolean rs6000coff_core_file_matches_executable_p ();
719
720 #undef  coff_core_file_matches_executable_p
721 #define coff_core_file_matches_executable_p  \
722                                      rs6000coff_core_file_matches_executable_p
723
724 #undef  coff_get_section_contents
725 #define coff_get_section_contents       rs6000coff_get_section_contents
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 */
748
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 |
760    HAS_SYMS | HAS_LOCALS | WP_TEXT),
761
762   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
763   0,                            /* leading char */
764   '/',                          /* ar_pad_char */
765   15,                           /* ar_max_namelen??? FIXMEmgo */
766   3,                            /* default alignment power */
767
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 */
774
775   {_bfd_dummy_target, coff_object_p,    /* bfd_check_format */
776      coff_archive_p, CORE_FILE_P},
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
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
795   COFF_SWAP_TABLE,
796 };