Made sure that every call to bfd_read, bfd_write, and bfd_seek
[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_set_error (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                 if (bfd_get_error () != bfd_error_system_call)
531                   bfd_set_error (bfd_error_no_more_archived_files);
532                 return NULL;
533         }
534         size  = atoi(h.hdr.ar_namlen);  /* ar_name[] length     */
535         size += size & 1;
536
537         if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
538                 if (bfd_get_error () != bfd_error_system_call)
539                   bfd_set_error (bfd_error_no_more_archived_files);
540                 return NULL;
541         }
542
543         if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
544                 bfd_set_error (bfd_error_malformed_archive);
545                 return NULL;
546         }
547
548         h.hdr._ar_name.ar_name[size] = 0;       /* terminate filename   */
549
550         /*
551          * if the filename is NULL, we're (probably) at the end.
552          */
553         if (size == 0) {
554                 bfd_set_error (bfd_error_no_more_archived_files);
555                 return NULL;
556         }
557
558         size += sizeof (h.hdr);
559         allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
560
561         if (allocptr == NULL) {
562                 bfd_set_error (bfd_error_no_memory);
563                 return NULL;
564         }
565
566         ared = (struct areltdata *) allocptr;
567
568         ared->arch_header = (void *) (allocptr + sizeof (struct areltdata));
569         memcpy ((char *) ared->arch_header, &h.hdr, size);
570         ared->parsed_size = atoi(h.hdr.ar_size);
571         ared->filename    = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name;
572
573         return ared;
574 }
575
576 /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
577    Why wasn't this part of the transfer vector?  */
578
579 bfd *
580 rs6000coff_get_elt_at_filepos (archive, filepos)
581      bfd *archive;
582      file_ptr filepos;
583 {
584   struct areltdata *new_areldata;
585   bfd *n_nfd;
586
587   n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
588   if (n_nfd) return n_nfd;
589
590   if (0 != bfd_seek (archive, filepos, SEEK_SET))
591     return NULL;
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                 if (bfd_get_error () != bfd_error_system_call)
640                   bfd_set_error (bfd_error_wrong_format);
641                 return 0;
642         }
643
644         if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
645                 bfd_set_error (bfd_error_wrong_format);
646                 return 0;
647         }
648
649         /*
650          * bfd_ardata() accesses the bfd->tdata field.
651          */
652         abfd->tdata.aout_ar_data =
653           (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
654         if ((art = bfd_ardata (abfd)) == NULL) {
655                 bfd_set_error (bfd_error_no_memory);
656                 return 0;
657         }
658
659         art->first_file_filepos = atoi(hdr.fl_fstmoff);
660         *(struct fl_hdr *) (1 + art) = hdr;
661
662         /* Someday...
663          * slurp in the member table, which I think is the armap equivalent.
664         xcoff_slurp_armap(abfd);
665          */
666   
667         return abfd->xvec;
668 }
669
670
671 static int
672 rs6000coff_stat_arch_elt(abfd, buf)
673   bfd *abfd;
674   struct stat *buf;
675 {
676         struct ar_hdr *hdr;
677         char *aloser;
678   
679         if (abfd->arelt_data == NULL) {
680                 bfd_set_error (bfd_error_invalid_operation);
681                 return -1;
682         }
683     
684         hdr = arch_hdr (abfd);
685
686 #define foo(arelt, stelt, size)  \
687         buf->stelt = strtol (hdr->arelt, &aloser, size); \
688                 if (aloser == hdr->arelt) return -1;
689   
690         foo (ar_date, st_mtime, 10);
691         foo (ar_uid, st_uid, 10);
692         foo (ar_gid, st_gid, 10);
693         foo (ar_mode, st_mode, 8);
694         foo (ar_size, st_size, 10);
695 #undef foo
696
697         return 0;
698 }
699
700 static boolean
701 rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
702   bfd *arch;
703   unsigned int elength;
704   struct orl *map; 
705   unsigned int orl_count;
706   int stridx;
707 {
708         bfd_set_error (bfd_error_invalid_operation);
709         return false;
710 }
711 #endif  /* HOST_AIX */
712
713 \f
714 #define CORE_FILE_P _bfd_dummy_target
715
716 #ifdef HOST_AIX
717 #undef CORE_FILE_P
718 #define CORE_FILE_P rs6000coff_core_p
719 extern bfd_target * rs6000coff_core_p ();
720 extern boolean rs6000coff_get_section_contents ();
721 extern boolean rs6000coff_core_file_matches_executable_p ();
722
723 #undef  coff_core_file_matches_executable_p
724 #define coff_core_file_matches_executable_p  \
725                                      rs6000coff_core_file_matches_executable_p
726
727 #undef  coff_get_section_contents
728 #define coff_get_section_contents       rs6000coff_get_section_contents
729 #endif /* HOST_AIX */
730
731 #ifdef HOST_LYNX
732
733 #undef CORE_FILE_P
734 #define CORE_FILE_P lynx_core_file_p
735 extern bfd_target *lynx_core_file_p PARAMS ((bfd *abfd));
736
737 extern boolean lynx_core_file_matches_executable_p PARAMS ((bfd *core_bfd,
738                                                             bfd *exec_bfd));
739 #undef  coff_core_file_matches_executable_p
740 #define coff_core_file_matches_executable_p lynx_core_file_matches_executable_p
741
742 extern char *lynx_core_file_failing_command PARAMS ((bfd *abfd));
743 #undef coff_core_file_failing_command
744 #define coff_core_file_failing_command lynx_core_file_failing_command
745
746 extern int lynx_core_file_failing_signal PARAMS ((bfd *abfd));
747 #undef coff_core_file_failing_signal
748 #define coff_core_file_failing_signal lynx_core_file_failing_signal
749
750 #endif /* HOST_LYNX */
751
752 /* The transfer vector that leads the outside world to all of the above. */
753
754 bfd_target rs6000coff_vec =
755 {
756   "aixcoff-rs6000",             /* name */
757   bfd_target_coff_flavour,      
758   true,                         /* data byte order is big */
759   true,                         /* header byte order is big */
760
761   (HAS_RELOC | EXEC_P |         /* object flags */
762    HAS_LINENO | HAS_DEBUG |
763    HAS_SYMS | HAS_LOCALS | WP_TEXT),
764
765   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
766   0,                            /* leading char */
767   '/',                          /* ar_pad_char */
768   15,                           /* ar_max_namelen??? FIXMEmgo */
769   3,                            /* default alignment power */
770
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, /* data */
774   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
775      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
776      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
777
778   {_bfd_dummy_target, coff_object_p,    /* bfd_check_format */
779      coff_archive_p, CORE_FILE_P},
780   {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
781      bfd_false},
782   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
783      _bfd_write_archive_contents, bfd_false},
784
785   JUMP_TABLE(coff),
786   COFF_SWAP_TABLE,
787 };