1 /* BFD back-end for MIPS Extended-Coff files.
2 Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3 Original version by Per Bothner.
4 Full support added by Ian Lance Taylor, ian@cygnus.com.
6 This file is part of BFD, the Binary File Descriptor library.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #include "coff/internal.h"
28 #include "coff/symconst.h"
29 #include "coff/ecoff.h"
30 #include "coff/mips.h"
34 /* Prototypes for static functions. */
36 static boolean mips_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));
37 static PTR mips_ecoff_mkobject_hook PARAMS ((bfd *abfd, PTR filehdr,
39 static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
40 struct internal_reloc *));
41 static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
42 const struct internal_reloc *,
46 /* ECOFF has COFF sections, but the debugging information is stored in
47 a completely different format. ECOFF targets use some of the
48 swapping routines from coffswap.h, and some of the generic COFF
49 routines in coffgen.c, but, unlike the real COFF targets, do not
50 use coffcode.h itself.
52 Get the generic COFF swapping routines, except for the reloc,
53 symbol, and lineno ones. Give them ecoff names. */
55 #define NO_COFF_RELOCS
56 #define NO_COFF_SYMBOLS
57 #define NO_COFF_LINENOS
58 #define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
59 #define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
60 #define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
61 #define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
62 #define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
63 #define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
66 /* Get the ECOFF swapping routines. */
68 #include "ecoffswap.h"
70 /* This is the ECOFF backend structure. The backend_data field of the
71 ecoff_tdata structure is set to this when an ECOFF BFD is
72 initialized. This is used by the generic ECOFF routines. */
74 static const struct ecoff_backend_data mips_ecoff_backend_data =
76 /* Supported architecture. */
78 /* Big endian magic number. */
80 /* Little endian magic number. */
82 /* Alignment of debugging information. E.g., 4. */
84 /* The page boundary used to align sections in a demand-paged
85 executable file. E.g., 0x1000. */
87 /* Bitsize of constructor entries. */
89 /* Sizes of external symbolic information. */
90 sizeof (struct hdr_ext),
91 sizeof (struct dnr_ext),
92 sizeof (struct pdr_ext),
93 sizeof (struct sym_ext),
94 sizeof (struct opt_ext),
95 sizeof (struct fdr_ext),
96 sizeof (struct rfd_ext),
97 sizeof (struct ext_ext),
98 /* Functions to swap in external symbolic data. */
107 /* Functions to swap out external symbolic data. */
116 /* External reloc size. */
118 /* Reloc swapping functions. */
119 mips_ecoff_swap_reloc_in,
120 mips_ecoff_swap_reloc_out
123 /* See whether the magic number matches. */
126 mips_ecoff_bad_format_hook (abfd, filehdr)
130 struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
132 if (MIPS_ECOFF_BADMAG (*internal_f))
138 /* Create an ECOFF object. */
141 mips_ecoff_mkobject (abfd)
144 abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *)
145 bfd_zalloc (abfd, sizeof (ecoff_data_type)));
146 if (abfd->tdata.ecoff_obj_data == NULL)
148 bfd_error = no_memory;
152 ecoff_data (abfd)->backend_data = &mips_ecoff_backend_data;
154 /* Always create a .scommon section for every BFD. This is a hack so
155 that the linker has something to attach scSCommon symbols to. */
156 bfd_make_section (abfd, SCOMMON);
161 /* Create the MIPS ECOFF backend specific information. */
164 mips_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
169 struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
170 struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
171 ecoff_data_type *ecoff;
173 if (mips_ecoff_mkobject (abfd) == false)
176 ecoff = ecoff_data (abfd);
178 ecoff->sym_filepos = internal_f->f_symptr;
180 if (internal_a != (struct internal_aouthdr *) NULL)
184 ecoff->text_start = internal_a->text_start;
185 ecoff->text_end = internal_a->text_start + internal_a->tsize;
186 ecoff->gp = internal_a->gp_value;
187 ecoff->gprmask = internal_a->gprmask;
188 for (i = 0; i < 4; i++)
189 ecoff->cprmask[i] = internal_a->cprmask[i];
190 if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
191 abfd->flags |= D_PAGED;
197 /* Reloc handling. MIPS ECOFF relocs are packed into 8 bytes in
198 external form. They use a bit which indicates whether the symbol
201 /* Swap a reloc in. */
204 mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
207 struct internal_reloc *intern;
209 const RELOC *ext = (RELOC *) ext_ptr;
211 intern->r_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_vaddr);
212 if (abfd->xvec->header_byteorder_big_p != false)
214 intern->r_symndx = (((int) ext->r_bits[0]
215 << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
216 | ((int) ext->r_bits[1]
217 << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
218 | ((int) ext->r_bits[2]
219 << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
220 intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
221 >> RELOC_BITS3_TYPE_SH_BIG);
222 intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
226 intern->r_symndx = (((int) ext->r_bits[0]
227 << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
228 | ((int) ext->r_bits[1]
229 << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
230 | ((int) ext->r_bits[2]
231 << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
232 intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
233 >> RELOC_BITS3_TYPE_SH_LITTLE);
234 intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
238 /* Swap a reloc out. */
241 mips_ecoff_swap_reloc_out (abfd, intern, dst)
243 const struct internal_reloc *intern;
246 RELOC *ext = (RELOC *) dst;
248 bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);
249 if (abfd->xvec->header_byteorder_big_p != false)
251 ext->r_bits[0] = intern->r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
252 ext->r_bits[1] = intern->r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
253 ext->r_bits[2] = intern->r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
254 ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
255 & RELOC_BITS3_TYPE_BIG)
256 | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
260 ext->r_bits[0] = intern->r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
261 ext->r_bits[1] = intern->r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
262 ext->r_bits[2] = intern->r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
263 ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
264 & RELOC_BITS3_TYPE_LITTLE)
265 | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
271 #include <core.out.h>
273 struct sgi_core_struct
276 char cmd[CORE_NAMESIZE];
279 #define core_hdr(bfd) ((bfd)->tdata.sgi_core_data)
280 #define core_signal(bfd) (core_hdr(bfd)->sig)
281 #define core_command(bfd) (core_hdr(bfd)->cmd)
284 make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
288 bfd_size_type _raw_size;
294 asect = bfd_make_section (abfd, name);
298 asect->flags = flags;
299 asect->_raw_size = _raw_size;
301 asect->filepos = filepos;
302 asect->alignment_power = 4;
308 ecoff_core_file_p (abfd)
314 struct coreout coreout;
315 struct idesc *idg, *idf, *ids;
317 val = bfd_read ((PTR)&coreout, 1, sizeof coreout, abfd);
318 if (val != sizeof coreout)
321 if (coreout.c_magic != CORE_MAGIC
322 || coreout.c_version != CORE_VERSION1)
325 core_hdr (abfd) = (struct sgi_core_struct *) bfd_zalloc (abfd, sizeof (struct sgi_core_struct));
326 if (!core_hdr (abfd))
329 strncpy (core_command (abfd), coreout.c_name, CORE_NAMESIZE);
330 core_signal (abfd) = coreout.c_sigcause;
332 bfd_seek (abfd, coreout.c_vmapoffset, SEEK_SET);
334 for (i = 0; i < coreout.c_nvmap; i++)
338 val = bfd_read ((PTR)&vmap, 1, sizeof vmap, abfd);
339 if (val != sizeof vmap)
354 if (!make_bfd_asection (abfd, secname,
355 SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS,
363 /* Make sure that the regs are contiguous within the core file. */
365 idg = &coreout.c_idesc[I_GPREGS];
366 idf = &coreout.c_idesc[I_FPREGS];
367 ids = &coreout.c_idesc[I_SPECREGS];
369 if (idg->i_offset + idg->i_len != idf->i_offset
370 || idf->i_offset + idf->i_len != ids->i_offset)
371 return 0; /* Can't deal with non-contig regs */
373 bfd_seek (abfd, idg->i_offset, SEEK_SET);
375 make_bfd_asection (abfd, ".reg",
376 SEC_ALLOC+SEC_HAS_CONTENTS,
377 idg->i_len + idf->i_len + ids->i_len,
381 /* OK, we believe you. You're a core file (sure, sure). */
387 ecoff_core_file_failing_command (abfd)
390 return core_command (abfd);
394 ecoff_core_file_failing_signal (abfd)
397 return core_signal (abfd);
401 ecoff_core_file_matches_executable_p (core_bfd, exec_bfd)
402 bfd *core_bfd, *exec_bfd;
404 return true; /* XXX - FIXME */
406 #else /* not def HOST_IRIX4 */
407 #define ecoff_core_file_p _bfd_dummy_target
408 #define ecoff_core_file_failing_command _bfd_dummy_core_file_failing_command
409 #define ecoff_core_file_failing_signal _bfd_dummy_core_file_failing_signal
410 #define ecoff_core_file_matches_executable_p \
411 _bfd_dummy_core_file_matches_executable_p
414 /* This is the COFF backend structure. The backend_data field of the
415 bfd_target structure is set to this. The section reading code in
416 coffgen.c uses this structure. */
418 static CONST bfd_coff_backend_data mips_ecoff_std_swap_table = {
419 (void (*) PARAMS ((bfd *,PTR,int,int,PTR))) bfd_void, /* aux_in */
420 (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
421 (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
422 (unsigned (*) PARAMS ((bfd *,PTR,int,int,PTR))) bfd_void, /* aux_out */
423 (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
424 (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
425 (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
426 mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
427 mips_ecoff_swap_scnhdr_out,
428 FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, true,
429 mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
430 mips_ecoff_swap_scnhdr_in, mips_ecoff_bad_format_hook,
431 ecoff_set_arch_mach_hook, mips_ecoff_mkobject_hook,
432 ecoff_styp_to_sec_flags, ecoff_make_section_hook, ecoff_set_alignment_hook,
433 ecoff_slurp_symbol_table
436 bfd_target ecoff_little_vec =
438 "ecoff-littlemips", /* name */
439 bfd_target_ecoff_flavour,
440 false, /* data byte order is little */
441 false, /* header byte order is little */
443 (HAS_RELOC | EXEC_P | /* object flags */
444 HAS_LINENO | HAS_DEBUG |
445 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
447 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* sect
449 0, /* leading underscore */
450 ' ', /* ar_pad_char */
451 15, /* ar_max_namelen */
452 4, /* minimum alignment power */
453 _do_getl64, _do_getl_signed_64, _do_putl64,
454 _do_getl32, _do_getl_signed_32, _do_putl32,
455 _do_getl16, _do_getl_signed_16, _do_putl16, /* data */
456 _do_getl64, _do_getl_signed_64, _do_putl64,
457 _do_getl32, _do_getl_signed_32, _do_putl32,
458 _do_getl16, _do_getl_signed_16, _do_putl16, /* hdrs */
460 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
461 ecoff_archive_p, _bfd_dummy_target},
462 {bfd_false, mips_ecoff_mkobject, /* bfd_set_format */
463 _bfd_generic_mkarchive, bfd_false},
464 {bfd_false, ecoff_write_object_contents, /* bfd_write_contents */
465 _bfd_write_archive_contents, bfd_false},
467 (PTR) &mips_ecoff_std_swap_table
470 bfd_target ecoff_big_vec =
472 "ecoff-bigmips", /* name */
473 bfd_target_ecoff_flavour,
474 true, /* data byte order is big */
475 true, /* header byte order is big */
477 (HAS_RELOC | EXEC_P | /* object flags */
478 HAS_LINENO | HAS_DEBUG |
479 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
481 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* sect flags */
482 0, /* leading underscore */
483 ' ', /* ar_pad_char */
484 15, /* ar_max_namelen */
485 4, /* minimum alignment power */
486 _do_getb64, _do_getb_signed_64, _do_putb64,
487 _do_getb32, _do_getb_signed_32, _do_putb32,
488 _do_getb16, _do_getb_signed_16, _do_putb16,
489 _do_getb64, _do_getb_signed_64, _do_putb64,
490 _do_getb32, _do_getb_signed_32, _do_putb32,
491 _do_getb16, _do_getb_signed_16, _do_putb16,
492 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
493 ecoff_archive_p, ecoff_core_file_p},
494 {bfd_false, mips_ecoff_mkobject, /* bfd_set_format */
495 _bfd_generic_mkarchive, bfd_false},
496 {bfd_false, ecoff_write_object_contents, /* bfd_write_contents */
497 _bfd_write_archive_contents, bfd_false},
499 (PTR) &mips_ecoff_std_swap_table
500 /* Note that there is another bfd_target just above this one. If
501 you are adding initializers here, you should be adding them there