* Rename COFF-related files in `coff-ARCH.c' form.
[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 -- no archive
24    support, no core files, and no writing.  FIXME.  */
25
26 /* Internalcoff.h and coffcode.h modify themselves based on this flag.  */
27 #define RS6000COFF_C 1
28
29 #include "bfd.h"
30 #include "sysdep.h"
31 #include "libbfd.h"
32 #include "obstack.h"
33 #include "internalcoff.h"
34 #include "coff-rs6000.h"
35 #include "libcoff.h"
36
37 /* The main body of code is in coffcode.h.  */
38 #include "coffcode.h"
39
40
41 #if 0
42 /* These are not yet ready for prime time.  */
43 #define coff_core_file_matches_executable_p  \
44                                      rs6000coff_core_file_matches_executable_p
45 #define coff_get_section_contents       rs6000coff_get_section_contents
46 #define coff_openr_next_archived_file   rs6000coff_openr_next_archived_file
47 #define coff_write_armap                rs6000coff_write_armap
48 #define coff_stat_arch_elt              rs6000coff_stat_arch_elt
49 #define coff_snarf_ar_hdr               rs6000coff_snarf_ar_hdr
50 #define coff_mkarchive                  rs6000coff_mkarchive
51
52 static bfd_target *rs6000coff_archive_p ();
53 static bfd_target *rs6000coff_core_p ();
54 static bfd_target *rs6000coff_object_p ();
55 static bfd_target *rs6000coff_real_object_p ();
56 #endif
57
58 bfd_target rs6000coff_vec =
59 {
60   "coff-rs6000",                /* name */
61   bfd_target_coff_flavour,      
62   true,                         /* data byte order is big */
63   true,                         /* header byte order is big */
64
65   (HAS_RELOC | EXEC_P |         /* object flags */
66    HAS_LINENO | HAS_DEBUG |
67    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
68
69   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
70   '/',                          /* ar_pad_char */
71   15,                           /* ar_max_namelen??? FIXMEmgo */
72   3,                            /* default alignment power */
73
74   _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
75   _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
76
77   {_bfd_dummy_target, coff_object_p,    /* bfd_check_format */
78      bfd_generic_archive_p, _bfd_dummy_target},
79   {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
80      bfd_false},
81   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
82      _bfd_write_archive_contents, bfd_false},
83
84   JUMP_TABLE(coff),
85   COFF_SWAP_TABLE
86
87 };
88
89
90 #if 0   /* we don't have include file for this yet */
91 /* ------------------------------------------------------------------------ */
92 /*      Support for archive file stuff..                                    */
93 /*      Stolen from Damon A. Parmazel's `bfd' portation.                    */
94 /* ------------------------------------------------------------------------ */
95
96 #include "/usr/include/ar.h"            /* <ar.h> doesn't do it.        */
97
98
99 #define arch_hdr(bfd)           \
100         ((struct ar_hdr *)      \
101          (((struct areltdata *)((bfd)->arelt_data))->arch_header))
102
103
104 static boolean
105 rs6000coff_mkarchive (abfd)
106      bfd *abfd;
107 {
108         bfd_error = invalid_operation;  /* write not supported  */
109 }
110
111
112 /* This functions reads an arch header and returns an areltdata pointer, or
113    NULL on error.
114
115    Presumes the file pointer is already in the right place (ie pointing
116    to the ar_hdr in the file).   Moves the file pointer; on success it
117    should be pointing to the front of the file contents; on failure it
118    could have been moved arbitrarily.
119 */
120
121 struct areltdata *
122 rs6000coff_snarf_ar_hdr (abfd)
123      bfd *abfd;
124 {
125         extern int errno;
126
127         struct {
128                 struct ar_hdr hdr;
129                 char namebuf[256];
130         } h;
131         int size;
132         struct areltdata *ared;
133         unsigned int namelen = 0;
134         char *allocptr;
135
136         size = sizeof (h.hdr);
137         if (bfd_read(&h.hdr, 1, size, abfd) != size) {
138                 bfd_error = no_more_archived_files;
139                 return NULL;
140         }
141         size  = atoi(h.hdr.ar_namlen);  /* ar_name[] length     */
142         size += size & 1;
143
144         if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
145                 bfd_error = no_more_archived_files;
146                 return NULL;
147         }
148
149         if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
150                 bfd_error = malformed_archive;
151                 return NULL;
152         }
153
154         h.hdr._ar_name.ar_name[size] = 0;       /* terminate filename   */
155
156         /*
157          * if the filename is NULL, we're (probably) at the end.
158          */
159         if (size == 0) {
160                 bfd_error = no_more_archived_files;
161                 return NULL;
162         }
163
164         size += sizeof (h.hdr);
165         allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
166
167         if (allocptr == NULL) {
168                 bfd_error = no_memory;
169                 return NULL;
170         }
171
172         ared = (struct areltdata *) allocptr;
173
174         ared->arch_header = (void *) (allocptr + sizeof (struct areltdata));
175         memcpy ((char *) ared->arch_header, &h.hdr, size);
176         ared->parsed_size = atoi(h.hdr.ar_size);
177         ared->filename    = ((AR_HDR*) ared->arch_header)->_ar_name.ar_name;
178
179         return ared;
180 }
181
182 /*
183  * xcoff_openr_next_archived_file -     xcoff has nxt/prv seek addrs.
184  */
185 static bfd *
186 rs6000coff_openr_next_archived_file(archive, last_file)
187   bfd *archive, *last_file; 
188 {
189         file_ptr filestart;
190
191         if (!last_file)
192                 filestart = bfd_ardata(archive)->first_file_filepos;
193         else
194                 filestart = atol(arch_hdr(last_file)->ar_nxtmem);
195
196         return get_elt_at_filepos (archive, filestart);
197 }
198
199
200 static bfd_target *
201 rs6000coff_archive_p (abfd)
202      bfd *abfd;
203 {
204         struct fl_hdr hdr;
205         register struct artdata *art;
206
207         if (bfd_read (&hdr, 1, sizeof (hdr), abfd) != sizeof (hdr)) {
208                 bfd_error = wrong_format;
209                 return 0;
210         }
211
212         if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
213                 bfd_error = wrong_format;
214                 return 0;
215         }
216
217         /*
218          * bfd_ardata() accesses the bfd->tdata field.
219          */
220         abfd->tdata = (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
221         if ((art = bfd_ardata (abfd)) == NULL) {
222                 bfd_error = no_memory;
223                 return 0;
224         }
225
226         art->first_file_filepos = atoi(hdr.fl_fstmoff);
227         *(struct fl_hdr *) (1 + art) = hdr;
228
229         /*
230          * slurp in the member table, which I thing is the armap equivalent.
231         xcoff_slurp_armap(abfd);
232          */
233   
234         if (abfd->obj_arch == bfd_arch_unknown) /* FIXME!!!     */
235                 abfd->obj_arch = bfd_arch_rs6000;
236
237         return abfd->xvec;
238 }
239
240
241 static int
242 rs6000coff_stat_arch_elt(abfd, buf)
243   bfd *abfd;
244   struct stat *buf;
245 {
246         struct ar_hdr *hdr;
247         char *aloser;
248   
249         if (abfd->arelt_data == NULL) {
250                 bfd_error = invalid_operation;
251                 return -1;
252         }
253     
254         hdr = arch_hdr (abfd);
255
256 #define foo(arelt, stelt, size)  \
257         buf->stelt = strtol (hdr->arelt, &aloser, size); \
258                 if (aloser == hdr->arelt) return -1;
259   
260         foo (ar_date, st_mtime, 10);
261         foo (ar_uid, st_uid, 10);
262         foo (ar_gid, st_gid, 10);
263         foo (ar_mode, st_mode, 8);
264         foo (ar_size, st_size, 10);
265
266         return 0;
267 }
268
269 static boolean
270 rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
271   bfd *arch;
272   unsigned int elength;
273   struct orl *map; 
274 {
275         bfd_error = invalid_operation;
276         return false;
277 }
278
279
280 #endif  /* if 0 */
281
282 #if 0   /* not sure if this will work on all hosts yet! */
283 #ifdef AOUTHDR
284 #undef AOUTHDR
285 #endif
286
287 /* ------------------------------------------------------------------------ */
288 /*      Support for core file stuff..                                       */
289 /* ------------------------------------------------------------------------ */
290
291 #include <sys/user.h>
292 #include <sys/ldr.h>
293 #include <sys/core.h>
294
295
296 /* Number of special purpose registers supported bygdb. This value should match
297    `tm.h' in gdb directory. Clean this mess up and use the macros in sys/reg.h.
298    FIXMEmgo. */
299
300 #define NUM_OF_SPEC_REGS  7
301 #define STACK_END_ADDR 0x2ff80000
302
303 #define core_hdr(bfd)           (((Rs6kCorData*)(bfd->tdata))->hdr)
304 #define core_datasec(bfd)       (((Rs6kCorData*)(bfd->tdata))->data_section)
305 #define core_stacksec(bfd)      (((Rs6kCorData*)(bfd->tdata))->stack_section)
306 #define core_regsec(bfd)        (((Rs6kCorData*)(bfd->tdata))->reg_section)
307 #define core_reg2sec(bfd)       (((Rs6kCorData*)(bfd->tdata))->reg2_section)
308
309 /* These are stored in the bfd's tdata */
310 typedef struct {
311   struct core *hdr;             /* core file header */
312   asection *data_section,
313            *stack_section,
314            *reg_section,        /* section for GPRs and special registers. */
315            *reg2_section;       /* section for FPRs. */
316 } Rs6kCorData;
317
318
319 /* Decide if a given bfd represents a `core' file or not. There really is no
320    magic number or anything like, in rs6000coff. */
321
322 static bfd_target *
323 rs6000coff_core_p (abfd)
324      bfd *abfd;
325 {
326   int fd;
327   struct core_dump coredata;
328   struct stat statbuf;
329   char *tmpptr;
330
331   /* Use bfd_xxx routines, rather than O/S primitives to read coredata. FIXMEmgo */
332   fd = open (abfd->filename, O_RDONLY);
333
334   fstat (fd, &statbuf);
335   read (fd, &coredata, sizeof (struct core_dump));
336
337   close (fd);
338
339   if (coredata.c_tab < (sizeof (coredata.c_u) + (int)&coredata.c_u - (int)&coredata.c_signo) ||
340       coredata.c_tab >= statbuf.st_size ||
341       (long)coredata.c_stack <= (long)coredata.c_tab ) {
342     return NULL;
343   }
344
345 /*
346   If it looks like core file, then.....
347   read core file header..... (maybe you've done it above..)
348 */
349
350   /* maybe you should alloc space for the whole core chunk over here!! FIXMEmgo */
351   tmpptr = (char*)bfd_zalloc (abfd, sizeof (Rs6kCorData));
352   set_tdata (abfd, tmpptr);
353
354   /* .stack section. */
355   if ((core_stacksec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
356        == NULL)  {
357     bfd_error = no_memory;
358     /* bfd_release (abfd, ???? ) */
359     return NULL;
360   }
361   core_stacksec (abfd)->name = ".stack";
362   core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
363   core_stacksec (abfd)->size = coredata.c_size;
364   core_stacksec (abfd)->vma = STACK_END_ADDR - coredata.c_size;
365   core_stacksec (abfd)->filepos = coredata.c_stack;     /*???? */
366
367   /* .reg section for GPRs and special registers. */
368   if ((core_regsec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
369        == NULL)  {
370     bfd_error = no_memory;
371     /* bfd_release (abfd, ???? ) */
372     return NULL;
373   }
374   core_regsec (abfd)->name = ".reg";
375   core_regsec (abfd)->flags = SEC_ALLOC;
376   core_regsec (abfd)->size = (32 + NUM_OF_SPEC_REGS) * 4;
377   core_regsec (abfd)->vma = NULL;                       /* not used?? */
378   core_regsec (abfd)->filepos = 
379         (char*)&coredata.c_u.u_save - (char*)&coredata;
380
381   /* .reg2 section for FPRs (floating point registers). */
382   if ((core_reg2sec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
383        == NULL)  {
384     bfd_error = no_memory;
385     /* bfd_release (abfd, ???? ) */
386     return NULL;
387   }
388   core_reg2sec (abfd)->name = ".reg2";
389   core_reg2sec (abfd)->flags = SEC_ALLOC;
390   core_reg2sec (abfd)->size = 8 * 32;                   /* 32 FPRs. */
391   core_reg2sec (abfd)->vma = NULL;                      /* not used?? */
392   core_reg2sec (abfd)->filepos = 
393         (char*)&coredata.c_u.u_save.fpr[0] - (char*)&coredata;
394
395   /* set up section chain here. */
396   abfd->section_count = 3;
397   abfd->sections = core_stacksec (abfd);
398   core_stacksec (abfd)->next = core_regsec(abfd);
399   core_regsec (abfd)->next = core_reg2sec (abfd);
400   core_reg2sec (abfd)->next = NULL;
401
402   return abfd->xvec;                            /* this is garbage for now. */
403 }
404
405
406
407 /* return `true' if given core is from the given executable.. */
408 static boolean
409 rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd)
410      bfd *core_bfd;
411      bfd *exec_bfd;
412 {
413   FILE *fd;
414   struct core_dump coredata;
415   struct ld_info ldinfo;
416   char pathname [1024];
417   char *str1, *str2;
418
419   /* Use bfd_xxx routines, rather than O/S primitives, do error checking!!
420                                                                 FIXMEmgo */
421   fd = fopen (core_bfd->filename, "r");
422
423   fread (&coredata, sizeof (struct core_dump), 1, fd);
424   fseek (fd, (long)coredata.c_tab, 0);
425   fread (&ldinfo, (char*)&ldinfo.ldinfo_filename[0] - (char*)&ldinfo.ldinfo_next,
426          1, fd);
427   fscanf (fd, "%s", pathname);
428   printf ("path: %s\n", pathname);
429   
430   str1 = strrchr (pathname, '/');
431   str2 = strrchr (exec_bfd->filename, '/');
432
433   /* step over character '/' */
434   str1 = str1 ? str1+1 : &pathname[0];
435   str2 = str2 ? str2+1 : exec_bfd->filename;
436
437   fclose (fd);
438   return strcmp (str1, str2);
439 }
440
441
442 static boolean
443 rs6000coff_get_section_contents (abfd, section, location, offset, count)
444      bfd *abfd;
445      sec_ptr section;
446      PTR location;
447      file_ptr offset;
448      int count;
449 {
450     if (count == 0)
451         return true;
452
453     /* Reading a core file's sections will be slightly different. For the
454        rest of them we can use bfd_generic_get_section_contents () I suppose. */
455     /* Make sure this routine works for any bfd and any section. FIXMEmgo. */
456
457     if (abfd->format == bfd_core && strcmp (section->name, ".reg") == 0) {
458
459       struct mstsave mstatus;
460       int    regoffset = (char*)&mstatus.gpr[0] - (char*)&mstatus;
461
462       /* Assert that the only way this code will be executed is reading the
463          whole section. */
464       if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS)))
465         printf ("ERROR! in rs6000coff_get_section_contents()\n");
466
467       /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure
468          in the core file. */
469
470       /* read GPR's into the location. */
471       if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1
472         || bfd_read(location, 1, sizeof (mstatus.gpr), abfd) != sizeof (mstatus.gpr))
473         return (false); /* on error */
474
475       /* increment location to the beginning of special registers in the section,
476          reset register offset value to the beginning of first special register
477          in mstsave structure, and read special registers. */
478
479       location = (PTR) ((char*)location + sizeof (mstatus.gpr));
480       regoffset = (char*)&mstatus.iar - (char*)&mstatus;
481
482       if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1
483         || bfd_read(location, 1, 4 * NUM_OF_SPEC_REGS, abfd) != 
484                                                         4 * NUM_OF_SPEC_REGS)
485         return (false); /* on error */
486       
487       /* increment location address, and read the special registers.. */
488       /* FIXMEmgo */
489       return (true);
490     }
491
492     /* else, use default bfd section content transfer. */
493     else
494       return bfd_generic_get_section_contents 
495                         (abfd, section, location, offset, count);
496 }
497
498 #endif /* if 0 - for CORE */