* mips-dis.c, m88k-dis.c: Don't include libbfd.h. Changed calls
[deliverable/binutils-gdb.git] / bfd / coff-mips.c
CommitLineData
1f29e30b 1/* BFD back-end for MIPS Extended-Coff files.
f6409552 2 Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
8fa0d3a0 3 Original version by Per Bothner.
f6409552 4 Full support added by Ian Lance Taylor, ian@cygnus.com.
1327fb29 5
68b70212 6This file is part of BFD, the Binary File Descriptor library.
23b0b558 7
68b70212 8This program is free software; you can redistribute it and/or modify
23b0b558 9it under the terms of the GNU General Public License as published by
68b70212
JG
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
23b0b558 12
68b70212 13This program is distributed in the hope that it will be useful,
23b0b558
JG
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
68b70212
JG
19along with this program; if not, write to the Free Software
20Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
1327fb29 21
23b0b558 22#include "bfd.h"
dd4646ca 23#include "sysdep.h"
1327fb29 24#include "libbfd.h"
8fa0d3a0 25#include "seclet.h"
dae31cf5
ILT
26#include "coff/internal.h"
27#include "coff/sym.h"
28#include "coff/symconst.h"
29#include "coff/ecoff.h"
30#include "coff/mips.h"
31#include "libcoff.h"
32#include "libecoff.h"
33\f
34/* Prototypes for static functions. */
c3fe0c41 35
dae31cf5
ILT
36static boolean mips_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));
37static PTR mips_ecoff_mkobject_hook PARAMS ((bfd *abfd, PTR filehdr,
38 PTR aouthdr));
39static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
40 struct internal_reloc *));
41static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
42 const struct internal_reloc *,
43 PTR));
44\f
8fa0d3a0 45
dae31cf5
ILT
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.
8fa0d3a0 51
dae31cf5
ILT
52 Get the generic COFF swapping routines, except for the reloc,
53 symbol, and lineno ones. Give them ecoff names. */
54#define MIPSECOFF
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
64#include "coffswap.h"
8fa0d3a0 65
dae31cf5
ILT
66/* Get the ECOFF swapping routines. */
67#define ECOFF_32
68#include "ecoffswap.h"
69\f
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. */
73
74static const struct ecoff_backend_data mips_ecoff_backend_data =
75{
76 /* Supported architecture. */
77 bfd_arch_mips,
78 /* Big endian magic number. */
79 MIPS_MAGIC_BIG,
80 /* Little endian magic number. */
81 MIPS_MAGIC_LITTLE,
82 /* Alignment of debugging information. E.g., 4. */
83 4,
84 /* The page boundary used to align sections in a demand-paged
85 executable file. E.g., 0x1000. */
86 0x1000,
87 /* Bitsize of constructor entries. */
88 32,
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. */
99 ecoff_swap_hdr_in,
100 ecoff_swap_dnr_in,
101 ecoff_swap_pdr_in,
102 ecoff_swap_sym_in,
103 ecoff_swap_opt_in,
104 ecoff_swap_fdr_in,
105 ecoff_swap_rfd_in,
106 ecoff_swap_ext_in,
107 /* Functions to swap out external symbolic data. */
108 ecoff_swap_hdr_out,
109 ecoff_swap_dnr_out,
110 ecoff_swap_pdr_out,
111 ecoff_swap_sym_out,
112 ecoff_swap_opt_out,
113 ecoff_swap_fdr_out,
114 ecoff_swap_rfd_out,
115 ecoff_swap_ext_out,
116 /* External reloc size. */
117 RELSZ,
118 /* Reloc swapping functions. */
119 mips_ecoff_swap_reloc_in,
120 mips_ecoff_swap_reloc_out
121};
122\f
123/* See whether the magic number matches. */
8fa0d3a0 124
dae31cf5
ILT
125static boolean
126mips_ecoff_bad_format_hook (abfd, filehdr)
127 bfd *abfd;
128 PTR filehdr;
129{
130 struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
8fa0d3a0 131
dae31cf5 132 if (MIPS_ECOFF_BADMAG (*internal_f))
8fa0d3a0
ILT
133 return false;
134
8fa0d3a0
ILT
135 return true;
136}
c3fe0c41 137
dae31cf5 138/* Create an ECOFF object. */
c3fe0c41
ILT
139
140static boolean
dae31cf5 141mips_ecoff_mkobject (abfd)
f6409552 142 bfd *abfd;
c3fe0c41 143{
dae31cf5
ILT
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)
c3fe0c41
ILT
147 {
148 bfd_error = no_memory;
149 return false;
150 }
c3fe0c41 151
dae31cf5 152 ecoff_data (abfd)->backend_data = &mips_ecoff_backend_data;
c3fe0c41 153
dae31cf5
ILT
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);
c3fe0c41
ILT
157
158 return true;
159}
160
dae31cf5 161/* Create the MIPS ECOFF backend specific information. */
c3fe0c41 162
dae31cf5
ILT
163static PTR
164mips_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
f6409552 165 bfd *abfd;
dae31cf5
ILT
166 PTR filehdr;
167 PTR aouthdr;
c3fe0c41 168{
dae31cf5
ILT
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;
c3fe0c41 172
dae31cf5
ILT
173 if (mips_ecoff_mkobject (abfd) == false)
174 return NULL;
c3fe0c41 175
dae31cf5
ILT
176 ecoff = ecoff_data (abfd);
177 ecoff->gp_size = 8;
178 ecoff->sym_filepos = internal_f->f_symptr;
23ba15b7 179
dae31cf5 180 if (internal_a != (struct internal_aouthdr *) NULL)
c3fe0c41 181 {
dae31cf5 182 int i;
23ba15b7 183
dae31cf5
ILT
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;
c3fe0c41
ILT
192 }
193
dae31cf5
ILT
194 return (PTR) ecoff;
195}
196\f
197/* Reloc handling. MIPS ECOFF relocs are packed into 8 bytes in
198 external form. They use a bit which indicates whether the symbol
199 is external. */
23ba15b7 200
dae31cf5 201/* Swap a reloc in. */
23ba15b7 202
dae31cf5
ILT
203static void
204mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
205 bfd *abfd;
206 PTR ext_ptr;
207 struct internal_reloc *intern;
208{
209 const RELOC *ext = (RELOC *) ext_ptr;
23ba15b7 210
dae31cf5
ILT
211 intern->r_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_vaddr);
212 if (abfd->xvec->header_byteorder_big_p != false)
213 {
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;
23ba15b7 223 }
dae31cf5 224 else
23ba15b7 225 {
dae31cf5
ILT
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;
23ba15b7 235 }
c3fe0c41
ILT
236}
237
dae31cf5 238/* Swap a reloc out. */
c3fe0c41 239
dae31cf5
ILT
240static void
241mips_ecoff_swap_reloc_out (abfd, intern, dst)
f6409552 242 bfd *abfd;
dae31cf5
ILT
243 const struct internal_reloc *intern;
244 PTR dst;
c3fe0c41 245{
dae31cf5 246 RELOC *ext = (RELOC *) dst;
c3fe0c41 247
dae31cf5
ILT
248 bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);
249 if (abfd->xvec->header_byteorder_big_p != false)
c3fe0c41 250 {
dae31cf5
ILT
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));
c3fe0c41 257 }
dae31cf5 258 else
c3fe0c41 259 {
dae31cf5
ILT
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));
c3fe0c41 266 }
c3fe0c41
ILT
267}
268\f
de17306e
ILT
269#ifdef HOST_IRIX4
270
271#include <core.out.h>
272
273struct sgi_core_struct
274{
275 int sig;
276 char cmd[CORE_NAMESIZE];
277};
278
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)
282
283static asection *
284make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
285 bfd *abfd;
286 CONST char *name;
287 flagword flags;
288 bfd_size_type _raw_size;
289 bfd_vma vma;
290 file_ptr filepos;
291{
292 asection *asect;
293
294 asect = bfd_make_section (abfd, name);
295 if (!asect)
296 return NULL;
297
298 asect->flags = flags;
299 asect->_raw_size = _raw_size;
300 asect->vma = vma;
301 asect->filepos = filepos;
302 asect->alignment_power = 4;
303
304 return asect;
305}
306
307static bfd_target *
308ecoff_core_file_p (abfd)
309 bfd *abfd;
310{
311 int val;
312 int i;
313 char *secname;
314 struct coreout coreout;
315 struct idesc *idg, *idf, *ids;
316
317 val = bfd_read ((PTR)&coreout, 1, sizeof coreout, abfd);
318 if (val != sizeof coreout)
319 return 0;
320
321 if (coreout.c_magic != CORE_MAGIC
322 || coreout.c_version != CORE_VERSION1)
323 return 0;
324
325 core_hdr (abfd) = (struct sgi_core_struct *) bfd_zalloc (abfd, sizeof (struct sgi_core_struct));
326 if (!core_hdr (abfd))
327 return NULL;
328
329 strncpy (core_command (abfd), coreout.c_name, CORE_NAMESIZE);
330 core_signal (abfd) = coreout.c_sigcause;
331
332 bfd_seek (abfd, coreout.c_vmapoffset, SEEK_SET);
333
334 for (i = 0; i < coreout.c_nvmap; i++)
335 {
336 struct vmap vmap;
337
338 val = bfd_read ((PTR)&vmap, 1, sizeof vmap, abfd);
339 if (val != sizeof vmap)
340 break;
341
342 switch (vmap.v_type)
343 {
344 case VDATA:
345 secname = ".data";
346 break;
347 case VSTACK:
348 secname = ".stack";
349 break;
350 default:
351 continue;
352 }
353
354 if (!make_bfd_asection (abfd, secname,
355 SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS,
356 vmap.v_len,
357 vmap.v_vaddr,
358 vmap.v_offset,
359 2))
360 return NULL;
361 }
362
363 /* Make sure that the regs are contiguous within the core file. */
364
365 idg = &coreout.c_idesc[I_GPREGS];
366 idf = &coreout.c_idesc[I_FPREGS];
367 ids = &coreout.c_idesc[I_SPECREGS];
368
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 */
372
373 bfd_seek (abfd, idg->i_offset, SEEK_SET);
374
375 make_bfd_asection (abfd, ".reg",
376 SEC_ALLOC+SEC_HAS_CONTENTS,
377 idg->i_len + idf->i_len + ids->i_len,
378 0,
379 idg->i_offset);
380
381 /* OK, we believe you. You're a core file (sure, sure). */
382
383 return abfd->xvec;
384}
385
386static char *
387ecoff_core_file_failing_command (abfd)
388 bfd *abfd;
389{
390 return core_command (abfd);
391}
392
393static int
394ecoff_core_file_failing_signal (abfd)
395 bfd *abfd;
396{
397 return core_signal (abfd);
398}
399
400static boolean
401ecoff_core_file_matches_executable_p (core_bfd, exec_bfd)
402 bfd *core_bfd, *exec_bfd;
403{
404 return true; /* XXX - FIXME */
405}
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
412#endif
413\f
f6409552
ILT
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. */
417
dae31cf5 418static CONST bfd_coff_backend_data mips_ecoff_std_swap_table = {
515c4292
ILT
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 */
dae31cf5
ILT
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,
515c4292 428 FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, true,
dae31cf5
ILT
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,
f6409552 432 ecoff_styp_to_sec_flags, ecoff_make_section_hook, ecoff_set_alignment_hook,
515c4292
ILT
433 ecoff_slurp_symbol_table
434};
435
1327fb29 436bfd_target ecoff_little_vec =
294eaca4
SC
437{
438 "ecoff-littlemips", /* name */
515c4292 439 bfd_target_ecoff_flavour,
294eaca4
SC
440 false, /* data byte order is little */
441 false, /* header byte order is little */
442
443 (HAS_RELOC | EXEC_P | /* object flags */
444 HAS_LINENO | HAS_DEBUG |
de17306e 445 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
294eaca4
SC
446
447 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* sect
448 flags */
449 0, /* leading underscore */
de17306e 450 ' ', /* ar_pad_char */
294eaca4 451 15, /* ar_max_namelen */
de17306e 452 4, /* minimum alignment power */
14e3c2e4
JK
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 */
294eaca4 459
515c4292 460 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
c3fe0c41 461 ecoff_archive_p, _bfd_dummy_target},
dae31cf5
ILT
462 {bfd_false, mips_ecoff_mkobject, /* bfd_set_format */
463 _bfd_generic_mkarchive, bfd_false},
c3fe0c41
ILT
464 {bfd_false, ecoff_write_object_contents, /* bfd_write_contents */
465 _bfd_write_archive_contents, bfd_false},
515c4292 466 JUMP_TABLE (ecoff),
dae31cf5 467 (PTR) &mips_ecoff_std_swap_table
515c4292 468};
1327fb29
SC
469
470bfd_target ecoff_big_vec =
294eaca4
SC
471{
472 "ecoff-bigmips", /* name */
515c4292 473 bfd_target_ecoff_flavour,
294eaca4
SC
474 true, /* data byte order is big */
475 true, /* header byte order is big */
476
477 (HAS_RELOC | EXEC_P | /* object flags */
478 HAS_LINENO | HAS_DEBUG |
de17306e 479 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
294eaca4
SC
480
481 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* sect flags */
482 0, /* leading underscore */
483 ' ', /* ar_pad_char */
de17306e
ILT
484 15, /* ar_max_namelen */
485 4, /* minimum alignment power */
14e3c2e4
JK
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,
294eaca4 492 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
de17306e 493 ecoff_archive_p, ecoff_core_file_p},
dae31cf5
ILT
494 {bfd_false, mips_ecoff_mkobject, /* bfd_set_format */
495 _bfd_generic_mkarchive, bfd_false},
515c4292 496 {bfd_false, ecoff_write_object_contents, /* bfd_write_contents */
c3fe0c41 497 _bfd_write_archive_contents, bfd_false},
515c4292 498 JUMP_TABLE(ecoff),
dae31cf5 499 (PTR) &mips_ecoff_std_swap_table
515c4292
ILT
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
502 as well. */
503};
This page took 0.108527 seconds and 4 git commands to generate.