z8kgen: temp file to generate z8k-opc.h from
[external/binutils.git] / bfd / coff-rs6000.c
1 /* IBM RS/6000 "XCOFF" back-end for BFD.
2    Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3    Written by Metin G. Ozisik, Mimi Phûông-Thåo Võ, and John Gilmore.
4    Archive support from Damon A. Permezel.
5    Contributed by IBM Corporation and Cygnus Support.
6
7 This file is part of BFD, the Binary File Descriptor library.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
22
23 /* This port currently only handles reading object files, except when
24    compiled on an RS/6000 host.  -- no archive support, no core files.
25    In all cases, it does not support writing.
26
27    FIXMEmgo comments are left from Metin Ozisik's original port.  */
28
29 /* Internalcoff.h and coffcode.h modify themselves based on this flag.  */
30 #define RS6000COFF_C 1
31
32 #include "bfd.h"
33 #include "sysdep.h"
34 #include "libbfd.h"
35 #include "obstack.h"
36 #include "internalcoff.h"
37 #include "coff-rs6000.h"
38 #include "libcoff.h"
39
40 /* The main body of code is in coffcode.h.  */
41
42 /* Can't read rs6000 relocs */
43 #define RTYPE2HOWTO(a,b)
44 #include "coffcode.h"
45
46 #define coff_archive_p          bfd_generic_archive_p
47 #define coff_mkarchive          _bfd_generic_mkarchive
48
49 #ifdef ARCHIVES_PLEASE
50
51 /* ------------------------------------------------------------------------ */
52 /*      Support for archive file stuff..                                    */
53 /*      Stolen from Damon A. Permezel's `bfd' portation.                    */
54 /* ------------------------------------------------------------------------ */
55
56 #undef  coff_openr_next_archived_file
57 #define coff_openr_next_archived_file   rs6000coff_openr_next_archived_file
58
59 #undef  coff_write_armap
60 #define coff_write_armap                rs6000coff_write_armap
61
62 #undef  coff_stat_arch_elt
63 #define coff_stat_arch_elt              rs6000coff_stat_arch_elt
64
65 #undef  coff_snarf_ar_hdr
66 #define coff_snarf_ar_hdr               rs6000coff_snarf_ar_hdr
67
68 #undef  coff_mkarchive
69 #define coff_mkarchive                  rs6000coff_mkarchive
70
71 #undef  coff_archive_p
72 #define coff_archive_p                  rs6000coff_archive_p
73
74 #include "/usr/include/ar.h"            /* <ar.h> doesn't do it.        */
75
76
77 #define arch_hdr(bfd)           \
78         ((struct ar_hdr *)      \
79          (((struct areltdata *)((bfd)->arelt_data))->arch_header))
80
81
82 static boolean
83 rs6000coff_mkarchive (abfd)
84      bfd *abfd;
85 {
86         bfd_error = invalid_operation;  /* write not supported  */
87 }
88
89
90 /* This functions reads an arch header and returns an areltdata pointer, or
91    NULL on error.
92
93    Presumes the file pointer is already in the right place (ie pointing
94    to the ar_hdr in the file).   Moves the file pointer; on success it
95    should be pointing to the front of the file contents; on failure it
96    could have been moved arbitrarily.
97 */
98
99 struct areltdata *
100 rs6000coff_snarf_ar_hdr (abfd)
101      bfd *abfd;
102 {
103         extern int errno;
104
105         struct {
106                 struct ar_hdr hdr;
107                 char namebuf[256];
108         } h;
109         int size;
110         struct areltdata *ared;
111         unsigned int namelen = 0;
112         char *allocptr;
113
114         size = sizeof (h.hdr);
115         if (bfd_read(&h.hdr, 1, size, abfd) != size) {
116                 bfd_error = no_more_archived_files;
117                 return NULL;
118         }
119         size  = atoi(h.hdr.ar_namlen);  /* ar_name[] length     */
120         size += size & 1;
121
122         if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
123                 bfd_error = no_more_archived_files;
124                 return NULL;
125         }
126
127         if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
128                 bfd_error = malformed_archive;
129                 return NULL;
130         }
131
132         h.hdr._ar_name.ar_name[size] = 0;       /* terminate filename   */
133
134         /*
135          * if the filename is NULL, we're (probably) at the end.
136          */
137         if (size == 0) {
138                 bfd_error = no_more_archived_files;
139                 return NULL;
140         }
141
142         size += sizeof (h.hdr);
143         allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
144
145         if (allocptr == NULL) {
146                 bfd_error = no_memory;
147                 return NULL;
148         }
149
150         ared = (struct areltdata *) allocptr;
151
152         ared->arch_header = (void *) (allocptr + sizeof (struct areltdata));
153         memcpy ((char *) ared->arch_header, &h.hdr, size);
154         ared->parsed_size = atoi(h.hdr.ar_size);
155         ared->filename    = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name;
156
157         return ared;
158 }
159
160 /* Stolen directly from archive.c, except it calls rs6000coff_snarf_ar_hdr.
161    Why wasn't this part of the transfer vector?  */
162
163 bfd *
164 rs6000coff_get_elt_at_filepos (archive, filepos)
165      bfd *archive;
166      file_ptr filepos;
167 {
168   struct areltdata *new_areldata;
169   bfd *n_nfd;
170
171   n_nfd = look_for_bfd_in_cache (archive, filepos);
172   if (n_nfd) return n_nfd;
173
174   if (0 > bfd_seek (archive, filepos, SEEK_SET)) {
175     bfd_error = system_call_error;
176     return NULL;
177   }
178
179   if ((new_areldata = rs6000coff_snarf_ar_hdr (archive)) == NULL) return NULL;
180   
181   n_nfd = _bfd_create_empty_archive_element_shell (archive);
182   if (n_nfd == NULL) {
183     bfd_release (archive, (PTR)new_areldata);
184     return NULL;
185   }
186   n_nfd->origin = bfd_tell (archive);
187   n_nfd->arelt_data = (PTR) new_areldata;
188   n_nfd->filename = new_areldata->filename;
189
190   if (add_bfd_to_cache (archive, filepos, n_nfd))
191     return n_nfd;
192
193   /* huh? */
194   bfd_release (archive, (PTR)n_nfd);
195   bfd_release (archive, (PTR)new_areldata);
196   return NULL;
197 }
198
199 /*
200  * xcoff_openr_next_archived_file -     xcoff has nxt/prv seek addrs.
201  */
202 static bfd *
203 rs6000coff_openr_next_archived_file(archive, last_file)
204   bfd *archive, *last_file; 
205 {
206         file_ptr filestart;
207
208         if (!last_file)
209                 filestart = bfd_ardata(archive)->first_file_filepos;
210         else
211                 filestart = atol(arch_hdr(last_file)->ar_nxtmem);
212
213         return rs6000coff_get_elt_at_filepos (archive, filestart);
214 }
215
216
217 static bfd_target *
218 rs6000coff_archive_p (abfd)
219      bfd *abfd;
220 {
221         struct fl_hdr hdr;
222         register struct artdata *art;
223
224         if (bfd_read (&hdr, sizeof (hdr), 1, abfd) != sizeof (hdr)) {
225                 bfd_error = wrong_format;
226                 return 0;
227         }
228
229         if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
230                 bfd_error = wrong_format;
231                 return 0;
232         }
233
234         /*
235          * bfd_ardata() accesses the bfd->tdata field.
236          */
237         abfd->tdata = (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
238         if ((art = bfd_ardata (abfd)) == NULL) {
239                 bfd_error = no_memory;
240                 return 0;
241         }
242
243         art->first_file_filepos = atoi(hdr.fl_fstmoff);
244         *(struct fl_hdr *) (1 + art) = hdr;
245
246         /* Someday...
247          * slurp in the member table, which I think is the armap equivalent.
248         xcoff_slurp_armap(abfd);
249          */
250   
251         return abfd->xvec;
252 }
253
254
255 static int
256 rs6000coff_stat_arch_elt(abfd, buf)
257   bfd *abfd;
258   struct stat *buf;
259 {
260         struct ar_hdr *hdr;
261         char *aloser;
262   
263         if (abfd->arelt_data == NULL) {
264                 bfd_error = invalid_operation;
265                 return -1;
266         }
267     
268         hdr = arch_hdr (abfd);
269
270 #define foo(arelt, stelt, size)  \
271         buf->stelt = strtol (hdr->arelt, &aloser, size); \
272                 if (aloser == hdr->arelt) return -1;
273   
274         foo (ar_date, st_mtime, 10);
275         foo (ar_uid, st_uid, 10);
276         foo (ar_gid, st_gid, 10);
277         foo (ar_mode, st_mode, 8);
278         foo (ar_size, st_size, 10);
279 #undef foo
280
281         return 0;
282 }
283
284 static boolean
285 rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
286   bfd *arch;
287   unsigned int elength;
288   struct orl *map; 
289 {
290         bfd_error = invalid_operation;
291         return false;
292 }
293 #endif  /* ARCHIVES_PLEASE */
294
295 #ifdef  COREFILES_PLEASE
296
297 #undef  coff_core_file_matches_executable_p
298 #define coff_core_file_matches_executable_p  \
299                                      rs6000coff_core_file_matches_executable_p
300
301 #undef  coff_get_section_contents
302 #define coff_get_section_contents       rs6000coff_get_section_contents
303
304
305 /* AOUTHDR is defined by the above.  We need another defn of it, from the
306    system include files.  Punt the old one and get us a new name for the
307    typedef in the system include files.  */
308 #ifdef AOUTHDR
309 #undef AOUTHDR
310 #endif
311 #define AOUTHDR second_AOUTHDR
312
313 #undef  SCNHDR
314
315
316 /* ------------------------------------------------------------------------ */
317 /*      Support for core file stuff..                                       */
318 /* ------------------------------------------------------------------------ */
319
320 #include <sys/user.h>
321 #include <sys/ldr.h>
322 #include <sys/core.h>
323
324
325 /* Number of special purpose registers supported by gdb.  This value
326    should match `tm.h' in gdb directory.  Clean this mess up and use
327    the macros in sys/reg.h.  FIXMEmgo. */
328
329 #define NUM_OF_SPEC_REGS  7
330 #define STACK_END_ADDR 0x2ff80000
331
332 #define core_hdr(bfd)           (((Rs6kCorData*)(bfd->tdata))->hdr)
333 #define core_datasec(bfd)       (((Rs6kCorData*)(bfd->tdata))->data_section)
334 #define core_stacksec(bfd)      (((Rs6kCorData*)(bfd->tdata))->stack_section)
335 #define core_regsec(bfd)        (((Rs6kCorData*)(bfd->tdata))->reg_section)
336 #define core_reg2sec(bfd)       (((Rs6kCorData*)(bfd->tdata))->reg2_section)
337
338 /* These are stored in the bfd's tdata */
339 typedef struct {
340   struct core *hdr;             /* core file header */
341   asection *data_section,
342            *stack_section,
343            *reg_section,        /* section for GPRs and special registers. */
344            *reg2_section;       /* section for FPRs. */
345 } Rs6kCorData;
346
347
348 /* Decide if a given bfd represents a `core' file or not. There really is no
349    magic number or anything like, in rs6000coff. */
350
351 static bfd_target *
352 rs6000coff_core_p (abfd)
353      bfd *abfd;
354 {
355   int fd;
356   struct core_dump coredata;
357   struct stat statbuf;
358   char *tmpptr;
359
360   /* Use bfd_xxx routines, rather than O/S primitives to read coredata. FIXMEmgo */
361   fd = open (abfd->filename, O_RDONLY);
362
363   fstat (fd, &statbuf);
364   read (fd, &coredata, sizeof (struct core_dump));
365
366   close (fd);
367
368   if (coredata.c_tab < (sizeof (coredata.c_u) + (int)&coredata.c_u - (int)&coredata.c_signo) ||
369       coredata.c_tab >= statbuf.st_size ||
370       (long)coredata.c_stack <= (long)coredata.c_tab ) {
371     return NULL;
372   }
373
374 /*
375   If it looks like core file, then.....
376   read core file header..... (maybe you've done it above..)
377 */
378
379   /* maybe you should alloc space for the whole core chunk over here!! FIXMEmgo */
380   tmpptr = (char*)bfd_zalloc (abfd, sizeof (Rs6kCorData));
381   set_tdata (abfd, tmpptr);
382
383   /* .stack section. */
384   if ((core_stacksec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
385        == NULL)  {
386     bfd_error = no_memory;
387     /* bfd_release (abfd, ???? ) */
388     return NULL;
389   }
390   core_stacksec (abfd)->name = ".stack";
391   core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
392   core_stacksec (abfd)->size = coredata.c_size;
393   core_stacksec (abfd)->vma = STACK_END_ADDR - coredata.c_size;
394   core_stacksec (abfd)->filepos = coredata.c_stack;     /*???? */
395
396   /* .reg section for GPRs and special registers. */
397   if ((core_regsec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
398        == NULL)  {
399     bfd_error = no_memory;
400     /* bfd_release (abfd, ???? ) */
401     return NULL;
402   }
403   core_regsec (abfd)->name = ".reg";
404   core_regsec (abfd)->flags = SEC_ALLOC;
405   core_regsec (abfd)->size = (32 + NUM_OF_SPEC_REGS) * 4;
406   core_regsec (abfd)->vma = NULL;                       /* not used?? */
407   core_regsec (abfd)->filepos = 
408         (char*)&coredata.c_u.u_save - (char*)&coredata;
409
410   /* .reg2 section for FPRs (floating point registers). */
411   if ((core_reg2sec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
412        == NULL)  {
413     bfd_error = no_memory;
414     /* bfd_release (abfd, ???? ) */
415     return NULL;
416   }
417   core_reg2sec (abfd)->name = ".reg2";
418   core_reg2sec (abfd)->flags = SEC_ALLOC;
419   core_reg2sec (abfd)->size = 8 * 32;                   /* 32 FPRs. */
420   core_reg2sec (abfd)->vma = NULL;                      /* not used?? */
421   core_reg2sec (abfd)->filepos = 
422         (char*)&coredata.c_u.u_save.fpr[0] - (char*)&coredata;
423
424   /* set up section chain here. */
425   abfd->section_count = 3;
426   abfd->sections = core_stacksec (abfd);
427   core_stacksec (abfd)->next = core_regsec(abfd);
428   core_regsec (abfd)->next = core_reg2sec (abfd);
429   core_reg2sec (abfd)->next = NULL;
430
431   return abfd->xvec;                            /* this is garbage for now. */
432 }
433
434
435
436 /* return `true' if given core is from the given executable.. */
437 static boolean
438 rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd)
439      bfd *core_bfd;
440      bfd *exec_bfd;
441 {
442   FILE *fd;
443   struct core_dump coredata;
444   struct ld_info ldinfo;
445   char pathname [1024];
446   char *str1, *str2;
447
448   /* Use bfd_xxx routines, rather than O/S primitives, do error checking!!
449                                                                 FIXMEmgo */
450   fd = fopen (core_bfd->filename, "r");
451
452   fread (&coredata, sizeof (struct core_dump), 1, fd);
453   fseek (fd, (long)coredata.c_tab, 0);
454   fread (&ldinfo, (char*)&ldinfo.ldinfo_filename[0] - (char*)&ldinfo.ldinfo_next,
455          1, fd);
456   fscanf (fd, "%s", pathname);
457   printf ("path: %s\n", pathname);
458   
459   str1 = strrchr (pathname, '/');
460   str2 = strrchr (exec_bfd->filename, '/');
461
462   /* step over character '/' */
463   str1 = str1 ? str1+1 : &pathname[0];
464   str2 = str2 ? str2+1 : exec_bfd->filename;
465
466   fclose (fd);
467   return strcmp (str1, str2);
468 }
469
470
471 static boolean
472 rs6000coff_get_section_contents (abfd, section, location, offset, count)
473      bfd *abfd;
474      sec_ptr section;
475      PTR location;
476      file_ptr offset;
477      int count;
478 {
479     if (count == 0)
480         return true;
481
482     /* Reading a core file's sections will be slightly different. For the
483        rest of them we can use bfd_generic_get_section_contents () I suppose. */
484     /* Make sure this routine works for any bfd and any section. FIXMEmgo. */
485
486     if (abfd->format == bfd_core && strcmp (section->name, ".reg") == 0) {
487
488       struct mstsave mstatus;
489       int    regoffset = (char*)&mstatus.gpr[0] - (char*)&mstatus;
490
491       /* Assert that the only way this code will be executed is reading the
492          whole section. */
493       if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS)))
494         printf ("ERROR! in rs6000coff_get_section_contents()\n");
495
496       /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure
497          in the core file. */
498
499       /* read GPR's into the location. */
500       if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1
501         || bfd_read(location, sizeof (mstatus.gpr), 1, abfd) != sizeof (mstatus.gpr))
502         return (false); /* on error */
503
504       /* increment location to the beginning of special registers in the section,
505          reset register offset value to the beginning of first special register
506          in mstsave structure, and read special registers. */
507
508       location = (PTR) ((char*)location + sizeof (mstatus.gpr));
509       regoffset = (char*)&mstatus.iar - (char*)&mstatus;
510
511       if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1
512         || bfd_read(location, 4 * NUM_OF_SPEC_REGS, 1, abfd) != 
513                                                         4 * NUM_OF_SPEC_REGS)
514         return (false); /* on error */
515       
516       /* increment location address, and read the special registers.. */
517       /* FIXMEmgo */
518       return (true);
519     }
520
521     /* else, use default bfd section content transfer. */
522     else
523       return bfd_generic_get_section_contents 
524                         (abfd, section, location, offset, count);
525 }
526
527 #endif /* COREFILES_PLEASE */
528 \f
529 /* The transfer vector that leads the outside world to all of the above. */
530
531 bfd_target rs6000coff_vec =
532 {
533   "aixcoff-rs6000",             /* name */
534   bfd_target_coff_flavour,      
535   true,                         /* data byte order is big */
536   true,                         /* header byte order is big */
537
538   (HAS_RELOC | EXEC_P |         /* object flags */
539    HAS_LINENO | HAS_DEBUG |
540    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
541
542   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
543   '/',                          /* ar_pad_char */
544   15,                           /* ar_max_namelen??? FIXMEmgo */
545   3,                            /* default alignment power */
546
547   _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
548   _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
549
550   {_bfd_dummy_target, coff_object_p,    /* bfd_check_format */
551      coff_archive_p, _bfd_dummy_target},
552   {bfd_false, coff_mkobject, coff_mkarchive, /* bfd_set_format */
553      bfd_false},
554   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
555      _bfd_write_archive_contents, bfd_false},
556
557   JUMP_TABLE(coff),
558   COFF_SWAP_TABLE
559 };