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
34 #include "internalcoff.h"
35 #include "rs6000coff.h"
38 /* The main body of code is in coffcode.h. */
43 /* These are not yet ready for prime time. */
44 #define coff_core_file_matches_executable_p \
45 rs6000coff_core_file_matches_executable_p
46 #define coff_get_section_contents rs6000coff_get_section_contents
47 #define coff_openr_next_archived_file rs6000coff_openr_next_archived_file
48 #define coff_write_armap rs6000coff_write_armap
49 #define coff_stat_arch_elt rs6000coff_stat_arch_elt
50 #define coff_snarf_ar_hdr rs6000coff_snarf_ar_hdr
51 #define coff_mkarchive rs6000coff_mkarchive
53 static bfd_target
*rs6000coff_archive_p ();
54 static bfd_target
*rs6000coff_core_p ();
55 static bfd_target
*rs6000coff_object_p ();
56 static bfd_target
*rs6000coff_real_object_p ();
59 bfd_target rs6000coff_vec
=
61 "coff_rs6000", /* name */
62 bfd_target_coff_flavour
,
63 true, /* data byte order is big */
64 true, /* header byte order is big */
66 (HAS_RELOC
| EXEC_P
| /* object flags */
67 HAS_LINENO
| HAS_DEBUG
|
68 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
),
70 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
71 '/', /* ar_pad_char */
72 15, /* ar_max_namelen??? FIXMEmgo */
73 3, /* default alignment power */
75 _do_getb64
, _do_putb64
, _do_getb32
, _do_putb32
, _do_getb16
, _do_putb16
, /* data */
76 _do_getb64
, _do_putb64
, _do_getb32
, _do_putb32
, _do_getb16
, _do_putb16
, /* hdrs */
78 {_bfd_dummy_target
, coff_object_p
, /* bfd_check_format */
79 bfd_generic_archive_p
, _bfd_dummy_target
},
80 {bfd_false
, coff_mkobject
, _bfd_generic_mkarchive
, /* bfd_set_format */
82 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
83 _bfd_write_archive_contents
, bfd_false
},
91 #if 0 /* we don't have include file for this yet */
92 /* ------------------------------------------------------------------------ */
93 /* Support for archive file stuff.. */
94 /* Stolen from Damon A. Parmazel's `bfd' portation. */
95 /* ------------------------------------------------------------------------ */
97 #include "/usr/include/ar.h" /* <ar.h> doesn't do it. */
100 #define arch_hdr(bfd) \
102 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
106 rs6000coff_mkarchive (abfd
)
109 bfd_error
= invalid_operation
; /* write not supported */
113 /* This functions reads an arch header and returns an areltdata pointer, or
116 Presumes the file pointer is already in the right place (ie pointing
117 to the ar_hdr in the file). Moves the file pointer; on success it
118 should be pointing to the front of the file contents; on failure it
119 could have been moved arbitrarily.
123 rs6000coff_snarf_ar_hdr (abfd
)
133 struct areltdata
*ared
;
134 unsigned int namelen
= 0;
137 size
= sizeof (h
.hdr
);
138 if (bfd_read(&h
.hdr
, 1, size
, abfd
) != size
) {
139 bfd_error
= no_more_archived_files
;
142 size
= atoi(h
.hdr
.ar_namlen
); /* ar_name[] length */
145 if (bfd_read(&h
.hdr
._ar_name
.ar_name
[2], 1, size
, abfd
) != size
) {
146 bfd_error
= no_more_archived_files
;
150 if (strncmp(h
.hdr
._ar_name
.ar_fmag
+ size
, AIAFMAG
, 2)) {
151 bfd_error
= malformed_archive
;
155 h
.hdr
._ar_name
.ar_name
[size
] = 0; /* terminate filename */
158 * if the filename is NULL, we're (probably) at the end.
161 bfd_error
= no_more_archived_files
;
165 size
+= sizeof (h
.hdr
);
166 allocptr
= bfd_zalloc(abfd
, sizeof (*ared
) + size
);
168 if (allocptr
== NULL
) {
169 bfd_error
= no_memory
;
173 ared
= (struct areltdata
*) allocptr
;
175 ared
->arch_header
= (void *) (allocptr
+ sizeof (struct areltdata
));
176 memcpy ((char *) ared
->arch_header
, &h
.hdr
, size
);
177 ared
->parsed_size
= atoi(h
.hdr
.ar_size
);
178 ared
->filename
= ((AR_HDR
*) ared
->arch_header
)->_ar_name
.ar_name
;
184 * xcoff_openr_next_archived_file - xcoff has nxt/prv seek addrs.
187 rs6000coff_openr_next_archived_file(archive
, last_file
)
188 bfd
*archive
, *last_file
;
193 filestart
= bfd_ardata(archive
)->first_file_filepos
;
195 filestart
= atol(arch_hdr(last_file
)->ar_nxtmem
);
197 return get_elt_at_filepos (archive
, filestart
);
202 rs6000coff_archive_p (abfd
)
206 register struct artdata
*art
;
208 if (bfd_read (&hdr
, 1, sizeof (hdr
), abfd
) != sizeof (hdr
)) {
209 bfd_error
= wrong_format
;
213 if (strncmp(hdr
.fl_magic
, AIAMAG
, SAIAMAG
)) {
214 bfd_error
= wrong_format
;
219 * bfd_ardata() accesses the bfd->tdata field.
221 abfd
->tdata
= (void *) bfd_zalloc(abfd
, sizeof (*art
) + sizeof (hdr
));
222 if ((art
= bfd_ardata (abfd
)) == NULL
) {
223 bfd_error
= no_memory
;
227 art
->first_file_filepos
= atoi(hdr
.fl_fstmoff
);
228 *(struct fl_hdr
*) (1 + art
) = hdr
;
231 * slurp in the member table, which I thing is the armap equivalent.
232 xcoff_slurp_armap(abfd);
235 if (abfd
->obj_arch
== bfd_arch_unknown
) /* FIXME!!! */
236 abfd
->obj_arch
= bfd_arch_rs6000
;
243 rs6000coff_stat_arch_elt(abfd
, buf
)
250 if (abfd
->arelt_data
== NULL
) {
251 bfd_error
= invalid_operation
;
255 hdr
= arch_hdr (abfd
);
257 #define foo(arelt, stelt, size) \
258 buf->stelt = strtol (hdr->arelt, &aloser, size); \
259 if (aloser == hdr->arelt) return -1;
261 foo (ar_date
, st_mtime
, 10);
262 foo (ar_uid
, st_uid
, 10);
263 foo (ar_gid
, st_gid
, 10);
264 foo (ar_mode
, st_mode
, 8);
265 foo (ar_size
, st_size
, 10);
271 rs6000coff_write_armap (arch
, elength
, map
, orl_count
, stridx
)
273 unsigned int elength
;
276 bfd_error
= invalid_operation
;
283 #if 0 /* not sure if this will work on all hosts yet! */
288 /* ------------------------------------------------------------------------ */
289 /* Support for core file stuff.. */
290 /* ------------------------------------------------------------------------ */
292 #include <sys/user.h>
294 #include <sys/core.h>
297 /* Number of special purpose registers supported bygdb. This value should match
298 `tm.h' in gdb directory. Clean this mess up and use the macros in sys/reg.h.
301 #define NUM_OF_SPEC_REGS 7
302 #define STACK_END_ADDR 0x2ff80000
304 #define core_hdr(bfd) (((Rs6kCorData*)(bfd->tdata))->hdr)
305 #define core_datasec(bfd) (((Rs6kCorData*)(bfd->tdata))->data_section)
306 #define core_stacksec(bfd) (((Rs6kCorData*)(bfd->tdata))->stack_section)
307 #define core_regsec(bfd) (((Rs6kCorData*)(bfd->tdata))->reg_section)
308 #define core_reg2sec(bfd) (((Rs6kCorData*)(bfd->tdata))->reg2_section)
310 /* These are stored in the bfd's tdata */
312 struct core
*hdr
; /* core file header */
313 asection
*data_section
,
315 *reg_section
, /* section for GPRs and special registers. */
316 *reg2_section
; /* section for FPRs. */
320 /* Decide if a given bfd represents a `core' file or not. There really is no
321 magic number or anything like, in rs6000coff. */
324 rs6000coff_core_p (abfd
)
328 struct core_dump coredata
;
332 /* Use bfd_xxx routines, rather than O/S primitives to read coredata. FIXMEmgo */
333 fd
= open (abfd
->filename
, O_RDONLY
);
335 fstat (fd
, &statbuf
);
336 read (fd
, &coredata
, sizeof (struct core_dump
));
340 if (coredata
.c_tab
< (sizeof (coredata
.c_u
) + (int)&coredata
.c_u
- (int)&coredata
.c_signo
) ||
341 coredata
.c_tab
>= statbuf
.st_size
||
342 (long)coredata
.c_stack
<= (long)coredata
.c_tab
) {
347 If it looks like core file, then.....
348 read core file header..... (maybe you've done it above..)
351 /* maybe you should alloc space for the whole core chunk over here!! FIXMEmgo */
352 tmpptr
= (char*)bfd_zalloc (abfd
, sizeof (Rs6kCorData
));
353 set_tdata (abfd
, tmpptr
);
355 /* .stack section. */
356 if ((core_stacksec (abfd
) = (asection
*) bfd_zalloc (abfd
, sizeof (asection
)))
358 bfd_error
= no_memory
;
359 /* bfd_release (abfd, ???? ) */
362 core_stacksec (abfd
)->name
= ".stack";
363 core_stacksec (abfd
)->flags
= SEC_ALLOC
+ SEC_LOAD
;
364 core_stacksec (abfd
)->size
= coredata
.c_size
;
365 core_stacksec (abfd
)->vma
= STACK_END_ADDR
- coredata
.c_size
;
366 core_stacksec (abfd
)->filepos
= coredata
.c_stack
; /*???? */
368 /* .reg section for GPRs and special registers. */
369 if ((core_regsec (abfd
) = (asection
*) bfd_zalloc (abfd
, sizeof (asection
)))
371 bfd_error
= no_memory
;
372 /* bfd_release (abfd, ???? ) */
375 core_regsec (abfd
)->name
= ".reg";
376 core_regsec (abfd
)->flags
= SEC_ALLOC
;
377 core_regsec (abfd
)->size
= (32 + NUM_OF_SPEC_REGS
) * 4;
378 core_regsec (abfd
)->vma
= NULL
; /* not used?? */
379 core_regsec (abfd
)->filepos
=
380 (char*)&coredata
.c_u
.u_save
- (char*)&coredata
;
382 /* .reg2 section for FPRs (floating point registers). */
383 if ((core_reg2sec (abfd
) = (asection
*) bfd_zalloc (abfd
, sizeof (asection
)))
385 bfd_error
= no_memory
;
386 /* bfd_release (abfd, ???? ) */
389 core_reg2sec (abfd
)->name
= ".reg2";
390 core_reg2sec (abfd
)->flags
= SEC_ALLOC
;
391 core_reg2sec (abfd
)->size
= 8 * 32; /* 32 FPRs. */
392 core_reg2sec (abfd
)->vma
= NULL
; /* not used?? */
393 core_reg2sec (abfd
)->filepos
=
394 (char*)&coredata
.c_u
.u_save
.fpr
[0] - (char*)&coredata
;
396 /* set up section chain here. */
397 abfd
->section_count
= 3;
398 abfd
->sections
= core_stacksec (abfd
);
399 core_stacksec (abfd
)->next
= core_regsec(abfd
);
400 core_regsec (abfd
)->next
= core_reg2sec (abfd
);
401 core_reg2sec (abfd
)->next
= NULL
;
403 return abfd
->xvec
; /* this is garbage for now. */
408 /* return `true' if given core is from the given executable.. */
410 rs6000coff_core_file_matches_executable_p (core_bfd
, exec_bfd
)
415 struct core_dump coredata
;
416 struct ld_info ldinfo
;
417 char pathname
[1024];
420 /* Use bfd_xxx routines, rather than O/S primitives, do error checking!!
422 fd
= fopen (core_bfd
->filename
, "r");
424 fread (&coredata
, sizeof (struct core_dump
), 1, fd
);
425 fseek (fd
, (long)coredata
.c_tab
, 0);
426 fread (&ldinfo
, (char*)&ldinfo
.ldinfo_filename
[0] - (char*)&ldinfo
.ldinfo_next
,
428 fscanf (fd
, "%s", pathname
);
429 printf ("path: %s\n", pathname
);
431 str1
= strrchr (pathname
, '/');
432 str2
= strrchr (exec_bfd
->filename
, '/');
434 /* step over character '/' */
435 str1
= str1
? str1
+1 : &pathname
[0];
436 str2
= str2
? str2
+1 : exec_bfd
->filename
;
439 return strcmp (str1
, str2
);
444 rs6000coff_get_section_contents (abfd
, section
, location
, offset
, count
)
454 /* Reading a core file's sections will be slightly different. For the
455 rest of them we can use bfd_generic_get_section_contents () I suppose. */
456 /* Make sure this routine works for any bfd and any section. FIXMEmgo. */
458 if (abfd
->format
== bfd_core
&& strcmp (section
->name
, ".reg") == 0) {
460 struct mstsave mstatus
;
461 int regoffset
= (char*)&mstatus
.gpr
[0] - (char*)&mstatus
;
463 /* Assert that the only way this code will be executed is reading the
465 if (offset
|| count
!= (sizeof(mstatus
.gpr
) + (4 * NUM_OF_SPEC_REGS
)))
466 printf ("ERROR! in rs6000coff_get_section_contents()\n");
468 /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure
471 /* read GPR's into the location. */
472 if ( bfd_seek(abfd
, section
->filepos
+ regoffset
, SEEK_SET
) == -1
473 || bfd_read(location
, 1, sizeof (mstatus
.gpr
), abfd
) != sizeof (mstatus
.gpr
))
474 return (false); /* on error */
476 /* increment location to the beginning of special registers in the section,
477 reset register offset value to the beginning of first special register
478 in mstsave structure, and read special registers. */
480 location
= (PTR
) ((char*)location
+ sizeof (mstatus
.gpr
));
481 regoffset
= (char*)&mstatus
.iar
- (char*)&mstatus
;
483 if ( bfd_seek(abfd
, section
->filepos
+ regoffset
, SEEK_SET
) == -1
484 || bfd_read(location
, 1, 4 * NUM_OF_SPEC_REGS
, abfd
) !=
485 4 * NUM_OF_SPEC_REGS
)
486 return (false); /* on error */
488 /* increment location address, and read the special registers.. */
493 /* else, use default bfd section content transfer. */
495 return bfd_generic_get_section_contents
496 (abfd
, section
, location
, offset
, count
);
499 #endif /* if 0 - for CORE */