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.
7 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
23 /* This port currently only handles reading object files -- no archive
24 support, no core files, and no writing. FIXME. */
26 /* Internalcoff.h and coffcode.h modify themselves based on this flag. */
27 #define RS6000COFF_C 1
33 #include "internalcoff.h"
34 #include "coff-rs6000.h"
37 /* The main body of code is in coffcode.h. */
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
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 ();
58 bfd_target rs6000coff_vec =
60 "coff-rs6000", /* name */
61 bfd_target_coff_flavour,
62 true, /* data byte order is big */
63 true, /* header byte order is big */
65 (HAS_RELOC | EXEC_P | /* object flags */
66 HAS_LINENO | HAS_DEBUG |
67 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
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 */
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 */
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 */
81 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
82 _bfd_write_archive_contents, bfd_false},
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 /* ------------------------------------------------------------------------ */
96 #include "/usr/include/ar.h" /* <ar.h> doesn't do it. */
99 #define arch_hdr(bfd) \
101 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
105 rs6000coff_mkarchive (abfd)
108 bfd_error = invalid_operation; /* write not supported */
112 /* This functions reads an arch header and returns an areltdata pointer, or
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.
122 rs6000coff_snarf_ar_hdr (abfd)
132 struct areltdata *ared;
133 unsigned int namelen = 0;
136 size = sizeof (h.hdr);
137 if (bfd_read(&h.hdr, 1, size, abfd) != size) {
138 bfd_error = no_more_archived_files;
141 size = atoi(h.hdr.ar_namlen); /* ar_name[] length */
144 if (bfd_read(&h.hdr._ar_name.ar_name[2], 1, size, abfd) != size) {
145 bfd_error = no_more_archived_files;
149 if (strncmp(h.hdr._ar_name.ar_fmag + size, AIAFMAG, 2)) {
150 bfd_error = malformed_archive;
154 h.hdr._ar_name.ar_name[size] = 0; /* terminate filename */
157 * if the filename is NULL, we're (probably) at the end.
160 bfd_error = no_more_archived_files;
164 size += sizeof (h.hdr);
165 allocptr = bfd_zalloc(abfd, sizeof (*ared) + size);
167 if (allocptr == NULL) {
168 bfd_error = no_memory;
172 ared = (struct areltdata *) allocptr;
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;
183 * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs.
186 rs6000coff_openr_next_archived_file(archive, last_file)
187 bfd *archive, *last_file;
192 filestart = bfd_ardata(archive)->first_file_filepos;
194 filestart = atol(arch_hdr(last_file)->ar_nxtmem);
196 return get_elt_at_filepos (archive, filestart);
201 rs6000coff_archive_p (abfd)
205 register struct artdata *art;
207 if (bfd_read (&hdr, 1, sizeof (hdr), abfd) != sizeof (hdr)) {
208 bfd_error = wrong_format;
212 if (strncmp(hdr.fl_magic, AIAMAG, SAIAMAG)) {
213 bfd_error = wrong_format;
218 * bfd_ardata() accesses the bfd->tdata field.
220 abfd->tdata = (void *) bfd_zalloc(abfd, sizeof (*art) + sizeof (hdr));
221 if ((art = bfd_ardata (abfd)) == NULL) {
222 bfd_error = no_memory;
226 art->first_file_filepos = atoi(hdr.fl_fstmoff);
227 *(struct fl_hdr *) (1 + art) = hdr;
230 * slurp in the member table, which I thing is the armap equivalent.
231 xcoff_slurp_armap(abfd);
234 if (abfd->obj_arch == bfd_arch_unknown) /* FIXME!!! */
235 abfd->obj_arch = bfd_arch_rs6000;
242 rs6000coff_stat_arch_elt(abfd, buf)
249 if (abfd->arelt_data == NULL) {
250 bfd_error = invalid_operation;
254 hdr = arch_hdr (abfd);
256 #define foo(arelt, stelt, size) \
257 buf->stelt = strtol (hdr->arelt, &aloser, size); \
258 if (aloser == hdr->arelt) return -1;
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);
270 rs6000coff_write_armap (arch, elength, map, orl_count, stridx)
272 unsigned int elength;
275 bfd_error = invalid_operation;
282 #if 0 /* not sure if this will work on all hosts yet! */
287 /* ------------------------------------------------------------------------ */
288 /* Support for core file stuff.. */
289 /* ------------------------------------------------------------------------ */
291 #include <sys/user.h>
293 #include <sys/core.h>
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.
300 #define NUM_OF_SPEC_REGS 7
301 #define STACK_END_ADDR 0x2ff80000
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)
309 /* These are stored in the bfd's tdata */
311 struct core *hdr; /* core file header */
312 asection *data_section,
314 *reg_section, /* section for GPRs and special registers. */
315 *reg2_section; /* section for FPRs. */
319 /* Decide if a given bfd represents a `core' file or not. There really is no
320 magic number or anything like, in rs6000coff. */
323 rs6000coff_core_p (abfd)
327 struct core_dump coredata;
331 /* Use bfd_xxx routines, rather than O/S primitives to read coredata. FIXMEmgo */
332 fd = open (abfd->filename, O_RDONLY);
334 fstat (fd, &statbuf);
335 read (fd, &coredata, sizeof (struct core_dump));
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 ) {
346 If it looks like core file, then.....
347 read core file header..... (maybe you've done it above..)
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);
354 /* .stack section. */
355 if ((core_stacksec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
357 bfd_error = no_memory;
358 /* bfd_release (abfd, ???? ) */
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; /*???? */
367 /* .reg section for GPRs and special registers. */
368 if ((core_regsec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
370 bfd_error = no_memory;
371 /* bfd_release (abfd, ???? ) */
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;
381 /* .reg2 section for FPRs (floating point registers). */
382 if ((core_reg2sec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
384 bfd_error = no_memory;
385 /* bfd_release (abfd, ???? ) */
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;
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;
402 return abfd->xvec; /* this is garbage for now. */
407 /* return `true' if given core is from the given executable.. */
409 rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd)
414 struct core_dump coredata;
415 struct ld_info ldinfo;
416 char pathname [1024];
419 /* Use bfd_xxx routines, rather than O/S primitives, do error checking!!
421 fd = fopen (core_bfd->filename, "r");
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,
427 fscanf (fd, "%s", pathname);
428 printf ("path: %s\n", pathname);
430 str1 = strrchr (pathname, '/');
431 str2 = strrchr (exec_bfd->filename, '/');
433 /* step over character '/' */
434 str1 = str1 ? str1+1 : &pathname[0];
435 str2 = str2 ? str2+1 : exec_bfd->filename;
438 return strcmp (str1, str2);
443 rs6000coff_get_section_contents (abfd, section, location, offset, count)
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. */
457 if (abfd->format == bfd_core && strcmp (section->name, ".reg") == 0) {
459 struct mstsave mstatus;
460 int regoffset = (char*)&mstatus.gpr[0] - (char*)&mstatus;
462 /* Assert that the only way this code will be executed is reading the
464 if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS)))
465 printf ("ERROR! in rs6000coff_get_section_contents()\n");
467 /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure
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 */
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. */
479 location = (PTR) ((char*)location + sizeof (mstatus.gpr));
480 regoffset = (char*)&mstatus.iar - (char*)&mstatus;
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 */
487 /* increment location address, and read the special registers.. */
492 /* else, use default bfd section content transfer. */
494 return bfd_generic_get_section_contents
495 (abfd, section, location, offset, count);
498 #endif /* if 0 - for CORE */