* coff-rs6000.c: Add Lynx core file support, use HOST_AIX, where
[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 #undef  coff_openr_next_archived_file
473 #define coff_openr_next_archived_file   rs6000coff_openr_next_archived_file
474
475 #undef  coff_write_armap
476 #define coff_write_armap                rs6000coff_write_armap
477
478 #undef  coff_stat_arch_elt
479 #define coff_stat_arch_elt              rs6000coff_stat_arch_elt
480
481 #undef  coff_snarf_ar_hdr
482 #define coff_snarf_ar_hdr               rs6000coff_snarf_ar_hdr
483
484 #undef  coff_mkarchive
485 #define coff_mkarchive                  rs6000coff_mkarchive
486
487 #undef  coff_archive_p
488 #define coff_archive_p                  rs6000coff_archive_p
489
490 #include "/usr/include/ar.h"            /* <ar.h> doesn't do it.        */
491
492
493 #define arch_hdr(bfd)           \
494         ((struct ar_hdr *)      \
495          (((struct areltdata *)((bfd)->arelt_data))->arch_header))
496
497
498 static boolean
499 rs6000coff_mkarchive (abfd)
500      bfd *abfd;
501 {
502         bfd_error = invalid_operation;  /* write not supported  */
503         return false;
504 }
505
506
507 /* This functions reads an arch header and returns an areltdata pointer, or
508    NULL on error.
509
510    Presumes the file pointer is already in the right place (ie pointing
511    to the ar_hdr in the file).   Moves the file pointer; on success it
512    should be pointing to the front of the file contents; on failure it
513    could have been moved arbitrarily.
514 */
515
516 struct areltdata *
517 rs6000coff_snarf_ar_hdr (abfd)
518      bfd *abfd;
519 {
520         struct {
521                 struct ar_hdr hdr;
522                 char namebuf[256];
523         } h;
524         int size;
525         struct areltdata *ared;
526         char *allocptr;
527
528         size = sizeof (h.hdr);
529         if (bfd_read(&h.hdr, 1, size, abfd) != size) {
530                 bfd_error = no_more_archived_files;
531                 return NULL;
532         }
533         size  = atoi(h.hdr.ar_namlen);  /* ar_name[] length     */
534         size += size & 1;
535
536         if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
537                 bfd_error = no_more_archived_files;
538                 return NULL;
539         }
540
541         if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
542                 bfd_error = malformed_archive;
543                 return NULL;
544         }
545
546         h.hdr._ar_name.ar_name[size] = 0;       /* terminate filename   */
547
548         /*
549          * if the filename is NULL, we're (probably) at the end.
550          */
551         if (size == 0) {
552                 bfd_error = no_more_archived_files;
553                 return NULL;
554         }
555
556         size += sizeof (h.hdr);
557         allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
558
559         if (allocptr == NULL) {
560                 bfd_error = no_memory;
561                 return NULL;
562         }
563
564         ared = (struct areltdata *) allocptr;
565
566         ared->arch_header = (void *) (allocptr + sizeof (struct areltdata));
567         memcpy ((char *) ared->arch_header, &h.hdr, size);
568         ared->parsed_size = atoi(h.hdr.ar_size);
569         ared->filename    = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name;
570
571         return ared;
572 }
573
574 /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
575    Why wasn't this part of the transfer vector?  */
576
577 bfd *
578 rs6000coff_get_elt_at_filepos (archive, filepos)
579      bfd *archive;
580      file_ptr filepos;
581 {
582   struct areltdata *new_areldata;
583   bfd *n_nfd;
584
585   n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
586   if (n_nfd) return n_nfd;
587
588   if (0 != bfd_seek (archive, filepos, SEEK_SET)) {
589     bfd_error = system_call_error;
590     return NULL;
591   }
592
593   if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL;
594   
595   n_nfd = _bfd_create_empty_archive_element_shell (archive);
596   if (n_nfd == NULL) {
597     bfd_release (archive, (PTR)new_areldata);
598     return NULL;
599   }
600   n_nfd->origin = bfd_tell (archive);
601   n_nfd->arelt_data = (PTR) new_areldata;
602   n_nfd->filename = new_areldata->filename;
603
604   if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
605     return n_nfd;
606
607   /* huh? */
608   bfd_release (archive, (PTR)n_nfd);
609   bfd_release (archive, (PTR)new_areldata);
610   return NULL;
611 }
612
613 /*
614  * xcoff_openr_next_archived_file -     xcoff has nxt/prv seek addrs.
615  */
616 static bfd *
617 rs6000coff_openr_next_archived_file(archive, last_file)
618   bfd *archive, *last_file; 
619 {
620         file_ptr filestart;
621
622         if (!last_file)
623                 filestart = bfd_ardata(archive)->first_file_filepos;
624         else
625                 filestart = atol(arch_hdr(last_file)->ar_nxtmem);
626
627         return rs6000coff_get_elt_at_filepos (archive, filestart);
628 }
629
630
631 static bfd_target *
632 rs6000coff_archive_p (abfd)
633      bfd *abfd;
634 {
635         struct fl_hdr hdr;
636         register struct artdata *art;
637
638         if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
639                 bfd_error = wrong_format;
640                 return 0;
641         }
642
643         if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
644                 bfd_error = wrong_format;
645                 return 0;
646         }
647
648         /*
649          * bfd_ardata() accesses the bfd->tdata field.
650          */
651         abfd->tdata.aout_ar_data =
652           (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
653         if ((art = bfd_ardata (abfd)) == NULL) {
654                 bfd_error = no_memory;
655                 return 0;
656         }
657
658         art->first_file_filepos = atoi(hdr.fl_fstmoff);
659         *(struct fl_hdr *) (1 + art) = hdr;
660
661         /* Someday...
662          * slurp in the member table, which I think is the armap equivalent.
663         xcoff_slurp_armap(abfd);
664          */
665   
666         return abfd->xvec;
667 }
668
669
670 static int
671 rs6000coff_stat_arch_elt(abfd, buf)
672   bfd *abfd;
673   struct stat *buf;
674 {
675         struct ar_hdr *hdr;
676         char *aloser;
677   
678         if (abfd->arelt_data == NULL) {
679                 bfd_error = invalid_operation;
680                 return -1;
681         }
682     
683         hdr = arch_hdr (abfd);
684
685 #define foo(arelt, stelt, size)  \
686         buf->stelt = strtol (hdr->arelt, &aloser, size); \
687                 if (aloser == hdr->arelt) return -1;
688   
689         foo (ar_date, st_mtime, 10);
690         foo (ar_uid, st_uid, 10);
691         foo (ar_gid, st_gid, 10);
692         foo (ar_mode, st_mode, 8);
693         foo (ar_size, st_size, 10);
694 #undef foo
695
696         return 0;
697 }
698
699 static boolean
700 rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
701   bfd *arch;
702   unsigned int elength;
703   struct orl *map; 
704   unsigned int orl_count;
705   int stridx;
706 {
707         bfd_error = invalid_operation;
708         return false;
709 }
710 #endif  /* HOST_AIX */
711
712 \f
713 #define CORE_FILE_P _bfd_dummy_target
714
715 #ifdef HOST_AIX
716 #undef CORE_FILE_P
717 #define CORE_FILE_P rs6000coff_core_p
718 extern bfd_target * rs6000coff_core_p ();
719 extern boolean rs6000coff_get_section_contents ();
720 extern boolean rs6000coff_core_file_matches_executable_p ();
721
722 #undef  coff_core_file_matches_executable_p
723 #define coff_core_file_matches_executable_p  \
724                                      rs6000coff_core_file_matches_executable_p
725
726 #undef  coff_get_section_contents
727 #define coff_get_section_contents       rs6000coff_get_section_contents
728 #endif /* HOST_AIX */
729
730 #ifdef HOST_LYNX
731
732 #undef CORE_FILE_P
733 #define CORE_FILE_P lynx_core_file_p
734 extern bfd_target *lynx_core_file_p PARAMS ((bfd *abfd));
735
736 extern boolean lynx_core_file_matches_executable_p PARAMS ((bfd *core_bfd,
737                                                             bfd *exec_bfd));
738 #undef  coff_core_file_matches_executable_p
739 #define coff_core_file_matches_executable_p lynx_core_file_matches_executable_p
740
741 extern char *lynx_core_file_failing_command PARAMS ((bfd *abfd));
742 #undef coff_core_file_failing_command
743 #define coff_core_file_failing_command lynx_core_file_failing_command
744
745 extern int lynx_core_file_failing_signal PARAMS ((bfd *abfd));
746 #undef coff_core_file_failing_signal
747 #define coff_core_file_failing_signal lynx_core_file_failing_signal
748
749 #endif /* HOST_LYNX */
750
751 /* The transfer vector that leads the outside world to all of the above. */
752
753 bfd_target rs6000coff_vec =
754 {
755   "aixcoff-rs6000",             /* name */
756   bfd_target_coff_flavour,      
757   true,                         /* data byte order is big */
758   true,                         /* header byte order is big */
759
760   (HAS_RELOC | EXEC_P |         /* object flags */
761    HAS_LINENO | HAS_DEBUG |
762    HAS_SYMS | HAS_LOCALS | WP_TEXT),
763
764   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
765   0,                            /* leading char */
766   '/',                          /* ar_pad_char */
767   15,                           /* ar_max_namelen??? FIXMEmgo */
768   3,                            /* default alignment power */
769
770   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
771      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
772      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
773   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
774      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
775      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
776
777   {_bfd_dummy_target, coff_object_p,    /* bfd_check_format */
778      coff_archive_p, CORE_FILE_P},
779   {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
780      bfd_false},
781   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
782      _bfd_write_archive_contents, bfd_false},
783
784   JUMP_TABLE(coff),
785   COFF_SWAP_TABLE,
786 };