Change DEFAULT_VECTOR to host_aout_vec here as well.
[deliverable/binutils-gdb.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 };
This page took 0.052898 seconds and 4 git commands to generate.