1/* BFD back-end for MIPS Extended-Coff files.
2   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3   2000, 2001, 2002, 2003, 2004
4   Free Software Foundation, Inc.
5   Original version by Per Bothner.
6   Full support added by Ian Lance Taylor, ian@cygnus.com.
7
8This file is part of BFD, the Binary File Descriptor library.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2 of the License, or
13(at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24#include "bfd.h"
25#include "sysdep.h"
26#include "bfdlink.h"
27#include "libbfd.h"
28#include "coff/internal.h"
29#include "coff/sym.h"
30#include "coff/symconst.h"
31#include "coff/ecoff.h"
32#include "coff/mips.h"
33#include "libcoff.h"
34#include "libecoff.h"
35
36/* Prototypes for static functions.  */
37
38static bfd_boolean mips_ecoff_bad_format_hook
39  PARAMS ((bfd *abfd, PTR filehdr));
40static void mips_ecoff_swap_reloc_in
41  PARAMS ((bfd *, PTR, struct internal_reloc *));
42static void mips_ecoff_swap_reloc_out
43  PARAMS ((bfd *, const struct internal_reloc *, PTR));
44static void mips_adjust_reloc_in
45  PARAMS ((bfd *, const struct internal_reloc *, arelent *));
46static void mips_adjust_reloc_out
47  PARAMS ((bfd *, const arelent *, struct internal_reloc *));
48static bfd_reloc_status_type mips_generic_reloc
49  PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
50	   asection *section, bfd *output_bfd, char **error));
51static bfd_reloc_status_type mips_refhi_reloc
52  PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
53	   asection *section, bfd *output_bfd, char **error));
54static bfd_reloc_status_type mips_reflo_reloc
55  PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
56	   asection *section, bfd *output_bfd, char **error));
57static bfd_reloc_status_type mips_gprel_reloc
58  PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
59	   asection *section, bfd *output_bfd, char **error));
60static void mips_relocate_hi
61  PARAMS ((struct internal_reloc *refhi, struct internal_reloc *reflo,
62	   bfd *input_bfd, asection *input_section, bfd_byte *contents,
63	   bfd_vma relocation));
64static bfd_boolean mips_relocate_section
65  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR));
66static reloc_howto_type *mips_bfd_reloc_type_lookup
67  PARAMS ((bfd *, bfd_reloc_code_real_type));
68
69/* ECOFF has COFF sections, but the debugging information is stored in
70   a completely different format.  ECOFF targets use some of the
71   swapping routines from coffswap.h, and some of the generic COFF
72   routines in coffgen.c, but, unlike the real COFF targets, do not
73   use coffcode.h itself.
74
75   Get the generic COFF swapping routines, except for the reloc,
76   symbol, and lineno ones.  Give them ECOFF names.  */
77#define MIPSECOFF
78#define NO_COFF_RELOCS
79#define NO_COFF_SYMBOLS
80#define NO_COFF_LINENOS
81#define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
82#define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
83#define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
84#define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
85#define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
86#define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
87#include "coffswap.h"
88
89/* Get the ECOFF swapping routines.  */
90#define ECOFF_32
91#include "ecoffswap.h"
92
93/* How to process the various relocs types.  */
94
95static reloc_howto_type mips_howto_table[] =
96{
97  /* Reloc type 0 is ignored.  The reloc reading code ensures that
98     this is a reference to the .abs section, which will cause
99     bfd_perform_relocation to do nothing.  */
100  HOWTO (MIPS_R_IGNORE,	/* type */
101	 0,			/* rightshift */
102	 0,			/* size (0 = byte, 1 = short, 2 = long) */
103	 8,			/* bitsize */
104	 FALSE,			/* pc_relative */
105	 0,			/* bitpos */
106	 complain_overflow_dont, /* complain_on_overflow */
107	 0,			/* special_function */
108	 "IGNORE",		/* name */
109	 FALSE,			/* partial_inplace */
110	 0,			/* src_mask */
111	 0,			/* dst_mask */
112	 FALSE),		/* pcrel_offset */
113
114  /* A 16 bit reference to a symbol, normally from a data section.  */
115  HOWTO (MIPS_R_REFHALF,	/* type */
116	 0,			/* rightshift */
117	 1,			/* size (0 = byte, 1 = short, 2 = long) */
118	 16,			/* bitsize */
119	 FALSE,			/* pc_relative */
120	 0,			/* bitpos */
121	 complain_overflow_bitfield, /* complain_on_overflow */
122	 mips_generic_reloc,	/* special_function */
123	 "REFHALF",		/* name */
124	 TRUE,			/* partial_inplace */
125	 0xffff,		/* src_mask */
126	 0xffff,		/* dst_mask */
127	 FALSE),		/* pcrel_offset */
128
129  /* A 32 bit reference to a symbol, normally from a data section.  */
130  HOWTO (MIPS_R_REFWORD,	/* type */
131	 0,			/* rightshift */
132	 2,			/* size (0 = byte, 1 = short, 2 = long) */
133	 32,			/* bitsize */
134	 FALSE,			/* pc_relative */
135	 0,			/* bitpos */
136	 complain_overflow_bitfield, /* complain_on_overflow */
137	 mips_generic_reloc,	/* special_function */
138	 "REFWORD",		/* name */
139	 TRUE,			/* partial_inplace */
140	 0xffffffff,		/* src_mask */
141	 0xffffffff,		/* dst_mask */
142	 FALSE),		/* pcrel_offset */
143
144  /* A 26 bit absolute jump address.  */
145  HOWTO (MIPS_R_JMPADDR,	/* type */
146	 2,			/* rightshift */
147	 2,			/* size (0 = byte, 1 = short, 2 = long) */
148	 26,			/* bitsize */
149	 FALSE,			/* pc_relative */
150	 0,			/* bitpos */
151	 complain_overflow_dont, /* complain_on_overflow */
152	 			/* This needs complex overflow
153				   detection, because the upper four
154				   bits must match the PC.  */
155	 mips_generic_reloc,	/* special_function */
156	 "JMPADDR",		/* name */
157	 TRUE,			/* partial_inplace */
158	 0x3ffffff,		/* src_mask */
159	 0x3ffffff,		/* dst_mask */
160	 FALSE),		/* pcrel_offset */
161
162  /* The high 16 bits of a symbol value.  Handled by the function
163     mips_refhi_reloc.  */
164  HOWTO (MIPS_R_REFHI,		/* type */
165	 16,			/* rightshift */
166	 2,			/* size (0 = byte, 1 = short, 2 = long) */
167	 16,			/* bitsize */
168	 FALSE,			/* pc_relative */
169	 0,			/* bitpos */
170	 complain_overflow_bitfield, /* complain_on_overflow */
171	 mips_refhi_reloc,	/* special_function */
172	 "REFHI",		/* name */
173	 TRUE,			/* partial_inplace */
174	 0xffff,		/* src_mask */
175	 0xffff,		/* dst_mask */
176	 FALSE),		/* pcrel_offset */
177
178  /* The low 16 bits of a symbol value.  */
179  HOWTO (MIPS_R_REFLO,		/* type */
180	 0,			/* rightshift */
181	 2,			/* size (0 = byte, 1 = short, 2 = long) */
182	 16,			/* bitsize */
183	 FALSE,			/* pc_relative */
184	 0,			/* bitpos */
185	 complain_overflow_dont, /* complain_on_overflow */
186	 mips_reflo_reloc,	/* special_function */
187	 "REFLO",		/* name */
188	 TRUE,			/* partial_inplace */
189	 0xffff,		/* src_mask */
190	 0xffff,		/* dst_mask */
191	 FALSE),		/* pcrel_offset */
192
193  /* A reference to an offset from the gp register.  Handled by the
194     function mips_gprel_reloc.  */
195  HOWTO (MIPS_R_GPREL,		/* type */
196	 0,			/* rightshift */
197	 2,			/* size (0 = byte, 1 = short, 2 = long) */
198	 16,			/* bitsize */
199	 FALSE,			/* pc_relative */
200	 0,			/* bitpos */
201	 complain_overflow_signed, /* complain_on_overflow */
202	 mips_gprel_reloc,	/* special_function */
203	 "GPREL",		/* name */
204	 TRUE,			/* partial_inplace */
205	 0xffff,		/* src_mask */
206	 0xffff,		/* dst_mask */
207	 FALSE),		/* pcrel_offset */
208
209  /* A reference to a literal using an offset from the gp register.
210     Handled by the function mips_gprel_reloc.  */
211  HOWTO (MIPS_R_LITERAL,	/* type */
212	 0,			/* rightshift */
213	 2,			/* size (0 = byte, 1 = short, 2 = long) */
214	 16,			/* bitsize */
215	 FALSE,			/* pc_relative */
216	 0,			/* bitpos */
217	 complain_overflow_signed, /* complain_on_overflow */
218	 mips_gprel_reloc,	/* special_function */
219	 "LITERAL",		/* name */
220	 TRUE,			/* partial_inplace */
221	 0xffff,		/* src_mask */
222	 0xffff,		/* dst_mask */
223	 FALSE),		/* pcrel_offset */
224
225  EMPTY_HOWTO (8),
226  EMPTY_HOWTO (9),
227  EMPTY_HOWTO (10),
228  EMPTY_HOWTO (11),
229
230  /* FIXME: This relocation is used (internally only) to represent branches
231     when assembling.  It should never appear in output files, and
232     be removed.  (It used to be used for embedded-PIC support.)  */
233  HOWTO (MIPS_R_PCREL16,	/* type */
234	 2,			/* rightshift */
235	 2,			/* size (0 = byte, 1 = short, 2 = long) */
236	 16,			/* bitsize */
237	 TRUE,			/* pc_relative */
238	 0,			/* bitpos */
239	 complain_overflow_signed, /* complain_on_overflow */
240	 mips_generic_reloc,	/* special_function */
241	 "PCREL16",		/* name */
242	 TRUE,			/* partial_inplace */
243	 0xffff,		/* src_mask */
244	 0xffff,		/* dst_mask */
245	 TRUE),			/* pcrel_offset */
246};
247
248#define MIPS_HOWTO_COUNT \
249  (sizeof mips_howto_table / sizeof mips_howto_table[0])
250
251/* See whether the magic number matches.  */
252
253static bfd_boolean
254mips_ecoff_bad_format_hook (abfd, filehdr)
255     bfd *abfd;
256     PTR filehdr;
257{
258  struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
259
260  switch (internal_f->f_magic)
261    {
262    case MIPS_MAGIC_1:
263      /* I don't know what endianness this implies.  */
264      return TRUE;
265
266    case MIPS_MAGIC_BIG:
267    case MIPS_MAGIC_BIG2:
268    case MIPS_MAGIC_BIG3:
269      return bfd_big_endian (abfd);
270
271    case MIPS_MAGIC_LITTLE:
272    case MIPS_MAGIC_LITTLE2:
273    case MIPS_MAGIC_LITTLE3:
274      return bfd_little_endian (abfd);
275
276    default:
277      return FALSE;
278    }
279}
280
281/* Reloc handling.  MIPS ECOFF relocs are packed into 8 bytes in
282   external form.  They use a bit which indicates whether the symbol
283   is external.  */
284
285/* Swap a reloc in.  */
286
287static void
288mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
289     bfd *abfd;
290     PTR ext_ptr;
291     struct internal_reloc *intern;
292{
293  const RELOC *ext = (RELOC *) ext_ptr;
294
295  intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
296  if (bfd_header_big_endian (abfd))
297    {
298      intern->r_symndx = (((int) ext->r_bits[0]
299			   << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
300			  | ((int) ext->r_bits[1]
301			     << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
302			  | ((int) ext->r_bits[2]
303			     << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
304      intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
305			>> RELOC_BITS3_TYPE_SH_BIG);
306      intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
307    }
308  else
309    {
310      intern->r_symndx = (((int) ext->r_bits[0]
311			   << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
312			  | ((int) ext->r_bits[1]
313			     << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
314			  | ((int) ext->r_bits[2]
315			     << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
316      intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
317			 >> RELOC_BITS3_TYPE_SH_LITTLE)
318			| ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
319			   << RELOC_BITS3_TYPEHI_SH_LITTLE));
320      intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
321    }
322}
323
324/* Swap a reloc out.  */
325
326static void
327mips_ecoff_swap_reloc_out (abfd, intern, dst)
328     bfd *abfd;
329     const struct internal_reloc *intern;
330     PTR dst;
331{
332  RELOC *ext = (RELOC *) dst;
333  long r_symndx;
334
335  BFD_ASSERT (intern->r_extern
336	      || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
337
338  r_symndx = intern->r_symndx;
339
340  H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr);
341  if (bfd_header_big_endian (abfd))
342    {
343      ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
344      ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
345      ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
346      ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
347			 & RELOC_BITS3_TYPE_BIG)
348			| (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
349    }
350  else
351    {
352      ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
353      ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
354      ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
355      ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
356			 & RELOC_BITS3_TYPE_LITTLE)
357			| ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
358			    & RELOC_BITS3_TYPEHI_LITTLE))
359			| (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
360    }
361}
362
363/* Finish canonicalizing a reloc.  Part of this is generic to all
364   ECOFF targets, and that part is in ecoff.c.  The rest is done in
365   this backend routine.  It must fill in the howto field.  */
366
367static void
368mips_adjust_reloc_in (abfd, intern, rptr)
369     bfd *abfd;
370     const struct internal_reloc *intern;
371     arelent *rptr;
372{
373  if (intern->r_type > MIPS_R_PCREL16)
374    abort ();
375
376  if (! intern->r_extern
377      && (intern->r_type == MIPS_R_GPREL
378	  || intern->r_type == MIPS_R_LITERAL))
379    rptr->addend += ecoff_data (abfd)->gp;
380
381  /* If the type is MIPS_R_IGNORE, make sure this is a reference to
382     the absolute section so that the reloc is ignored.  */
383  if (intern->r_type == MIPS_R_IGNORE)
384    rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
385
386  rptr->howto = &mips_howto_table[intern->r_type];
387}
388
389/* Make any adjustments needed to a reloc before writing it out.  None
390   are needed for MIPS.  */
391
392static void
393mips_adjust_reloc_out (abfd, rel, intern)
394     bfd *abfd ATTRIBUTE_UNUSED;
395     const arelent *rel ATTRIBUTE_UNUSED;
396     struct internal_reloc *intern ATTRIBUTE_UNUSED;
397{
398}
399
400/* ECOFF relocs are either against external symbols, or against
401   sections.  If we are producing relocatable output, and the reloc
402   is against an external symbol, and nothing has given us any
403   additional addend, the resulting reloc will also be against the
404   same symbol.  In such a case, we don't want to change anything
405   about the way the reloc is handled, since it will all be done at
406   final link time.  Rather than put special case code into
407   bfd_perform_relocation, all the reloc types use this howto
408   function.  It just short circuits the reloc if producing
409   relocatable output against an external symbol.  */
410
411static bfd_reloc_status_type
412mips_generic_reloc (abfd,
413		    reloc_entry,
414		    symbol,
415		    data,
416		    input_section,
417		    output_bfd,
418		    error_message)
419     bfd *abfd ATTRIBUTE_UNUSED;
420     arelent *reloc_entry;
421     asymbol *symbol;
422     PTR data ATTRIBUTE_UNUSED;
423     asection *input_section;
424     bfd *output_bfd;
425     char **error_message ATTRIBUTE_UNUSED;
426{
427  if (output_bfd != (bfd *) NULL
428      && (symbol->flags & BSF_SECTION_SYM) == 0
429      && reloc_entry->addend == 0)
430    {
431      reloc_entry->address += input_section->output_offset;
432      return bfd_reloc_ok;
433    }
434
435  return bfd_reloc_continue;
436}
437
438/* Do a REFHI relocation.  This has to be done in combination with a
439   REFLO reloc, because there is a carry from the REFLO to the REFHI.
440   Here we just save the information we need; we do the actual
441   relocation when we see the REFLO.  MIPS ECOFF requires that the
442   REFLO immediately follow the REFHI.  As a GNU extension, we permit
443   an arbitrary number of HI relocs to be associated with a single LO
444   reloc.  This extension permits gcc to output the HI and LO relocs
445   itself.  */
446
447struct mips_hi
448{
449  struct mips_hi *next;
450  bfd_byte *addr;
451  bfd_vma addend;
452};
453
454/* FIXME: This should not be a static variable.  */
455
456static struct mips_hi *mips_refhi_list;
457
458static bfd_reloc_status_type
459mips_refhi_reloc (abfd,
460		  reloc_entry,
461		  symbol,
462		  data,
463		  input_section,
464		  output_bfd,
465		  error_message)
466     bfd *abfd ATTRIBUTE_UNUSED;
467     arelent *reloc_entry;
468     asymbol *symbol;
469     PTR data;
470     asection *input_section;
471     bfd *output_bfd;
472     char **error_message ATTRIBUTE_UNUSED;
473{
474  bfd_reloc_status_type ret;
475  bfd_vma relocation;
476  struct mips_hi *n;
477
478  /* If we're relocating, and this an external symbol, we don't want
479     to change anything.  */
480  if (output_bfd != (bfd *) NULL
481      && (symbol->flags & BSF_SECTION_SYM) == 0
482      && reloc_entry->addend == 0)
483    {
484      reloc_entry->address += input_section->output_offset;
485      return bfd_reloc_ok;
486    }
487
488  ret = bfd_reloc_ok;
489  if (bfd_is_und_section (symbol->section)
490      && output_bfd == (bfd *) NULL)
491    ret = bfd_reloc_undefined;
492
493  if (bfd_is_com_section (symbol->section))
494    relocation = 0;
495  else
496    relocation = symbol->value;
497
498  relocation += symbol->section->output_section->vma;
499  relocation += symbol->section->output_offset;
500  relocation += reloc_entry->addend;
501
502  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
503    return bfd_reloc_outofrange;
504
505  /* Save the information, and let REFLO do the actual relocation.  */
506  n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
507  if (n == NULL)
508    return bfd_reloc_outofrange;
509  n->addr = (bfd_byte *) data + reloc_entry->address;
510  n->addend = relocation;
511  n->next = mips_refhi_list;
512  mips_refhi_list = n;
513
514  if (output_bfd != (bfd *) NULL)
515    reloc_entry->address += input_section->output_offset;
516
517  return ret;
518}
519
520/* Do a REFLO relocation.  This is a straightforward 16 bit inplace
521   relocation; this function exists in order to do the REFHI
522   relocation described above.  */
523
524static bfd_reloc_status_type
525mips_reflo_reloc (abfd,
526		  reloc_entry,
527		  symbol,
528		  data,
529		  input_section,
530		  output_bfd,
531		  error_message)
532     bfd *abfd;
533     arelent *reloc_entry;
534     asymbol *symbol;
535     PTR data;
536     asection *input_section;
537     bfd *output_bfd;
538     char **error_message;
539{
540  if (mips_refhi_list != NULL)
541    {
542      struct mips_hi *l;
543
544      l = mips_refhi_list;
545      while (l != NULL)
546	{
547	  unsigned long insn;
548	  unsigned long val;
549	  unsigned long vallo;
550	  struct mips_hi *next;
551
552	  /* Do the REFHI relocation.  Note that we actually don't
553	     need to know anything about the REFLO itself, except
554	     where to find the low 16 bits of the addend needed by the
555	     REFHI.  */
556	  insn = bfd_get_32 (abfd, l->addr);
557	  vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
558		   & 0xffff);
559	  val = ((insn & 0xffff) << 16) + vallo;
560	  val += l->addend;
561
562	  /* The low order 16 bits are always treated as a signed
563	     value.  Therefore, a negative value in the low order bits
564	     requires an adjustment in the high order bits.  We need
565	     to make this adjustment in two ways: once for the bits we
566	     took from the data, and once for the bits we are putting
567	     back in to the data.  */
568	  if ((vallo & 0x8000) != 0)
569	    val -= 0x10000;
570	  if ((val & 0x8000) != 0)
571	    val += 0x10000;
572
573	  insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
574	  bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
575
576	  next = l->next;
577	  free (l);
578	  l = next;
579	}
580
581      mips_refhi_list = NULL;
582    }
583
584  /* Now do the REFLO reloc in the usual way.  */
585  return mips_generic_reloc (abfd, reloc_entry, symbol, data,
586			      input_section, output_bfd, error_message);
587}
588
589/* Do a GPREL relocation.  This is a 16 bit value which must become
590   the offset from the gp register.  */
591
592static bfd_reloc_status_type
593mips_gprel_reloc (abfd,
594		  reloc_entry,
595		  symbol,
596		  data,
597		  input_section,
598		  output_bfd,
599		  error_message)
600     bfd *abfd;
601     arelent *reloc_entry;
602     asymbol *symbol;
603     PTR data;
604     asection *input_section;
605     bfd *output_bfd;
606     char **error_message;
607{
608  bfd_boolean relocatable;
609  bfd_vma gp;
610  bfd_vma relocation;
611  unsigned long val;
612  unsigned long insn;
613
614  /* If we're relocating, and this is an external symbol with no
615     addend, we don't want to change anything.  We will only have an
616     addend if this is a newly created reloc, not read from an ECOFF
617     file.  */
618  if (output_bfd != (bfd *) NULL
619      && (symbol->flags & BSF_SECTION_SYM) == 0
620      && reloc_entry->addend == 0)
621    {
622      reloc_entry->address += input_section->output_offset;
623      return bfd_reloc_ok;
624    }
625
626  if (output_bfd != (bfd *) NULL)
627    relocatable = TRUE;
628  else
629    {
630      relocatable = FALSE;
631      output_bfd = symbol->section->output_section->owner;
632    }
633
634  if (bfd_is_und_section (symbol->section) && ! relocatable)
635    return bfd_reloc_undefined;
636
637  /* We have to figure out the gp value, so that we can adjust the
638     symbol value correctly.  We look up the symbol _gp in the output
639     BFD.  If we can't find it, we're stuck.  We cache it in the ECOFF
640     target data.  We don't need to adjust the symbol value for an
641     external symbol if we are producing relocatable output.  */
642  gp = _bfd_get_gp_value (output_bfd);
643  if (gp == 0
644      && (! relocatable
645	  || (symbol->flags & BSF_SECTION_SYM) != 0))
646    {
647      if (relocatable)
648	{
649	  /* Make up a value.  */
650	  gp = symbol->section->output_section->vma + 0x4000;
651	  _bfd_set_gp_value (output_bfd, gp);
652	}
653      else
654	{
655	  unsigned int count;
656	  asymbol **sym;
657	  unsigned int i;
658
659	  count = bfd_get_symcount (output_bfd);
660	  sym = bfd_get_outsymbols (output_bfd);
661
662	  if (sym == (asymbol **) NULL)
663	    i = count;
664	  else
665	    {
666	      for (i = 0; i < count; i++, sym++)
667		{
668		  register const char *name;
669
670		  name = bfd_asymbol_name (*sym);
671		  if (*name == '_' && strcmp (name, "_gp") == 0)
672		    {
673		      gp = bfd_asymbol_value (*sym);
674		      _bfd_set_gp_value (output_bfd, gp);
675		      break;
676		    }
677		}
678	    }
679
680	  if (i >= count)
681	    {
682	      /* Only get the error once.  */
683	      gp = 4;
684	      _bfd_set_gp_value (output_bfd, gp);
685	      *error_message =
686		(char *) _("GP relative relocation when _gp not defined");
687	      return bfd_reloc_dangerous;
688	    }
689	}
690    }
691
692  if (bfd_is_com_section (symbol->section))
693    relocation = 0;
694  else
695    relocation = symbol->value;
696
697  relocation += symbol->section->output_section->vma;
698  relocation += symbol->section->output_offset;
699
700  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
701    return bfd_reloc_outofrange;
702
703  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
704
705  /* Set val to the offset into the section or symbol.  */
706  val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
707  if (val & 0x8000)
708    val -= 0x10000;
709
710  /* Adjust val for the final section location and GP value.  If we
711     are producing relocatable output, we don't want to do this for
712     an external symbol.  */
713  if (! relocatable
714      || (symbol->flags & BSF_SECTION_SYM) != 0)
715    val += relocation - gp;
716
717  insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff);
718  bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address);
719
720  if (relocatable)
721    reloc_entry->address += input_section->output_offset;
722
723  /* Make sure it fit in 16 bits.  */
724  if ((long) val >= 0x8000 || (long) val < -0x8000)
725    return bfd_reloc_overflow;
726
727  return bfd_reloc_ok;
728}
729
730/* Get the howto structure for a generic reloc type.  */
731
732static reloc_howto_type *
733mips_bfd_reloc_type_lookup (abfd, code)
734     bfd *abfd ATTRIBUTE_UNUSED;
735     bfd_reloc_code_real_type code;
736{
737  int mips_type;
738
739  switch (code)
740    {
741    case BFD_RELOC_16:
742      mips_type = MIPS_R_REFHALF;
743      break;
744    case BFD_RELOC_32:
745    case BFD_RELOC_CTOR:
746      mips_type = MIPS_R_REFWORD;
747      break;
748    case BFD_RELOC_MIPS_JMP:
749      mips_type = MIPS_R_JMPADDR;
750      break;
751    case BFD_RELOC_HI16_S:
752      mips_type = MIPS_R_REFHI;
753      break;
754    case BFD_RELOC_LO16:
755      mips_type = MIPS_R_REFLO;
756      break;
757    case BFD_RELOC_GPREL16:
758      mips_type = MIPS_R_GPREL;
759      break;
760    case BFD_RELOC_MIPS_LITERAL:
761      mips_type = MIPS_R_LITERAL;
762      break;
763    case BFD_RELOC_16_PCREL_S2:
764      mips_type = MIPS_R_PCREL16;
765      break;
766    default:
767      return (reloc_howto_type *) NULL;
768    }
769
770  return &mips_howto_table[mips_type];
771}
772
773/* A helper routine for mips_relocate_section which handles the REFHI
774   relocations.  The REFHI relocation must be followed by a REFLO
775   relocation, and the addend used is formed from the addends of both
776   instructions.  */
777
778static void
779mips_relocate_hi (refhi, reflo, input_bfd, input_section, contents,
780		  relocation)
781     struct internal_reloc *refhi;
782     struct internal_reloc *reflo;
783     bfd *input_bfd;
784     asection *input_section;
785     bfd_byte *contents;
786     bfd_vma relocation;
787{
788  unsigned long insn;
789  unsigned long val;
790  unsigned long vallo;
791
792  if (refhi == NULL)
793    return;
794
795  insn = bfd_get_32 (input_bfd,
796		     contents + refhi->r_vaddr - input_section->vma);
797  if (reflo == NULL)
798    vallo = 0;
799  else
800    vallo = (bfd_get_32 (input_bfd,
801			 contents + reflo->r_vaddr - input_section->vma)
802	     & 0xffff);
803
804  val = ((insn & 0xffff) << 16) + vallo;
805  val += relocation;
806
807  /* The low order 16 bits are always treated as a signed value.
808     Therefore, a negative value in the low order bits requires an
809     adjustment in the high order bits.  We need to make this
810     adjustment in two ways: once for the bits we took from the data,
811     and once for the bits we are putting back in to the data.  */
812  if ((vallo & 0x8000) != 0)
813    val -= 0x10000;
814
815  if ((val & 0x8000) != 0)
816    val += 0x10000;
817
818  insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
819  bfd_put_32 (input_bfd, (bfd_vma) insn,
820	      contents + refhi->r_vaddr - input_section->vma);
821}
822
823/* Relocate a section while linking a MIPS ECOFF file.  */
824
825static bfd_boolean
826mips_relocate_section (output_bfd, info, input_bfd, input_section,
827		       contents, external_relocs)
828     bfd *output_bfd;
829     struct bfd_link_info *info;
830     bfd *input_bfd;
831     asection *input_section;
832     bfd_byte *contents;
833     PTR external_relocs;
834{
835  asection **symndx_to_section;
836  struct ecoff_link_hash_entry **sym_hashes;
837  bfd_vma gp;
838  bfd_boolean gp_undefined;
839  struct external_reloc *ext_rel;
840  struct external_reloc *ext_rel_end;
841  unsigned int i;
842  bfd_boolean got_lo;
843  struct internal_reloc lo_int_rel;
844  bfd_size_type amt;
845
846  BFD_ASSERT (input_bfd->xvec->byteorder
847	      == output_bfd->xvec->byteorder);
848
849  /* We keep a table mapping the symndx found in an internal reloc to
850     the appropriate section.  This is faster than looking up the
851     section by name each time.  */
852  symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
853  if (symndx_to_section == (asection **) NULL)
854    {
855      amt = NUM_RELOC_SECTIONS * sizeof (asection *);
856      symndx_to_section = (asection **) bfd_alloc (input_bfd, amt);
857      if (!symndx_to_section)
858	return FALSE;
859
860      symndx_to_section[RELOC_SECTION_NONE] = NULL;
861      symndx_to_section[RELOC_SECTION_TEXT] =
862	bfd_get_section_by_name (input_bfd, ".text");
863      symndx_to_section[RELOC_SECTION_RDATA] =
864	bfd_get_section_by_name (input_bfd, ".rdata");
865      symndx_to_section[RELOC_SECTION_DATA] =
866	bfd_get_section_by_name (input_bfd, ".data");
867      symndx_to_section[RELOC_SECTION_SDATA] =
868	bfd_get_section_by_name (input_bfd, ".sdata");
869      symndx_to_section[RELOC_SECTION_SBSS] =
870	bfd_get_section_by_name (input_bfd, ".sbss");
871      symndx_to_section[RELOC_SECTION_BSS] =
872	bfd_get_section_by_name (input_bfd, ".bss");
873      symndx_to_section[RELOC_SECTION_INIT] =
874	bfd_get_section_by_name (input_bfd, ".init");
875      symndx_to_section[RELOC_SECTION_LIT8] =
876	bfd_get_section_by_name (input_bfd, ".lit8");
877      symndx_to_section[RELOC_SECTION_LIT4] =
878	bfd_get_section_by_name (input_bfd, ".lit4");
879      symndx_to_section[RELOC_SECTION_XDATA] = NULL;
880      symndx_to_section[RELOC_SECTION_PDATA] = NULL;
881      symndx_to_section[RELOC_SECTION_FINI] =
882	bfd_get_section_by_name (input_bfd, ".fini");
883      symndx_to_section[RELOC_SECTION_LITA] = NULL;
884      symndx_to_section[RELOC_SECTION_ABS] = NULL;
885
886      ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
887    }
888
889  sym_hashes = ecoff_data (input_bfd)->sym_hashes;
890
891  gp = _bfd_get_gp_value (output_bfd);
892  if (gp == 0)
893    gp_undefined = TRUE;
894  else
895    gp_undefined = FALSE;
896
897  got_lo = FALSE;
898
899  ext_rel = (struct external_reloc *) external_relocs;
900  ext_rel_end = ext_rel + input_section->reloc_count;
901  for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
902    {
903      struct internal_reloc int_rel;
904      bfd_boolean use_lo = FALSE;
905      bfd_vma addend;
906      reloc_howto_type *howto;
907      struct ecoff_link_hash_entry *h = NULL;
908      asection *s = NULL;
909      bfd_vma relocation;
910      bfd_reloc_status_type r;
911
912      if (! got_lo)
913	mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);
914      else
915	{
916	  int_rel = lo_int_rel;
917	  got_lo = FALSE;
918	}
919
920      BFD_ASSERT (int_rel.r_type
921		  < sizeof mips_howto_table / sizeof mips_howto_table[0]);
922
923      /* The REFHI reloc requires special handling.  It must be followed
924	 by a REFLO reloc, and the addend is formed from both relocs.  */
925      if (int_rel.r_type == MIPS_R_REFHI)
926	{
927	  struct external_reloc *lo_ext_rel;
928
929	  /* As a GNU extension, permit an arbitrary number of REFHI
930             relocs before the REFLO reloc.  This permits gcc to emit
931	     the HI and LO relocs itself.  */
932	  for (lo_ext_rel = ext_rel + 1;
933	       lo_ext_rel < ext_rel_end;
934	       lo_ext_rel++)
935	    {
936	      mips_ecoff_swap_reloc_in (input_bfd, (PTR) lo_ext_rel,
937					&lo_int_rel);
938	      if (lo_int_rel.r_type != int_rel.r_type)
939		break;
940	    }
941
942	  if (lo_ext_rel < ext_rel_end
943	      && lo_int_rel.r_type == MIPS_R_REFLO
944	      && int_rel.r_extern == lo_int_rel.r_extern
945	      && int_rel.r_symndx == lo_int_rel.r_symndx)
946	    {
947	      use_lo = TRUE;
948	      if (lo_ext_rel == ext_rel + 1)
949		got_lo = TRUE;
950	    }
951	}
952
953      howto = &mips_howto_table[int_rel.r_type];
954
955      if (int_rel.r_extern)
956	{
957	  h = sym_hashes[int_rel.r_symndx];
958	  /* If h is NULL, that means that there is a reloc against an
959	     external symbol which we thought was just a debugging
960	     symbol.  This should not happen.  */
961	  if (h == (struct ecoff_link_hash_entry *) NULL)
962	    abort ();
963	}
964      else
965	{
966	  if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
967	    s = NULL;
968	  else
969	    s = symndx_to_section[int_rel.r_symndx];
970
971	  if (s == (asection *) NULL)
972	    abort ();
973	}
974
975      /* The GPREL reloc uses an addend: the difference in the GP
976	 values.  */
977      if (int_rel.r_type != MIPS_R_GPREL
978	  && int_rel.r_type != MIPS_R_LITERAL)
979	addend = 0;
980      else
981	{
982	  if (gp_undefined)
983	    {
984	      if (! ((*info->callbacks->reloc_dangerous)
985		     (info, _("GP relative relocation used when GP not defined"),
986		      input_bfd, input_section,
987		      int_rel.r_vaddr - input_section->vma)))
988		return FALSE;
989	      /* Only give the error once per link.  */
990	      gp = 4;
991	      _bfd_set_gp_value (output_bfd, gp);
992	      gp_undefined = FALSE;
993	    }
994	  if (! int_rel.r_extern)
995	    {
996	      /* This is a relocation against a section.  The current
997		 addend in the instruction is the difference between
998		 INPUT_SECTION->vma and the GP value of INPUT_BFD.  We
999		 must change this to be the difference between the
1000		 final definition (which will end up in RELOCATION)
1001		 and the GP value of OUTPUT_BFD (which is in GP).  */
1002	      addend = ecoff_data (input_bfd)->gp - gp;
1003	    }
1004	  else if (! info->relocatable
1005		   || h->root.type == bfd_link_hash_defined
1006		   || h->root.type == bfd_link_hash_defweak)
1007	    {
1008	      /* This is a relocation against a defined symbol.  The
1009		 current addend in the instruction is simply the
1010		 desired offset into the symbol (normally zero).  We
1011		 are going to change this into a relocation against a
1012		 defined symbol, so we want the instruction to hold
1013		 the difference between the final definition of the
1014		 symbol (which will end up in RELOCATION) and the GP
1015		 value of OUTPUT_BFD (which is in GP).  */
1016	      addend = - gp;
1017	    }
1018	  else
1019	    {
1020	      /* This is a relocation against an undefined or common
1021		 symbol.  The current addend in the instruction is
1022		 simply the desired offset into the symbol (normally
1023		 zero).  We are generating relocatable output, and we
1024		 aren't going to define this symbol, so we just leave
1025		 the instruction alone.  */
1026	      addend = 0;
1027	    }
1028	}
1029
1030      if (info->relocatable)
1031	{
1032	  /* We are generating relocatable output, and must convert
1033	     the existing reloc.  */
1034	  if (int_rel.r_extern)
1035	    {
1036	      if ((h->root.type == bfd_link_hash_defined
1037		   || h->root.type == bfd_link_hash_defweak)
1038		  && ! bfd_is_abs_section (h->root.u.def.section))
1039		{
1040		  const char *name;
1041
1042		  /* This symbol is defined in the output.  Convert
1043		     the reloc from being against the symbol to being
1044		     against the section.  */
1045
1046		  /* Clear the r_extern bit.  */
1047		  int_rel.r_extern = 0;
1048
1049		  /* Compute a new r_symndx value.  */
1050		  s = h->root.u.def.section;
1051		  name = bfd_get_section_name (output_bfd,
1052					       s->output_section);
1053
1054		  int_rel.r_symndx = -1;
1055		  switch (name[1])
1056		    {
1057		    case 'b':
1058		      if (strcmp (name, ".bss") == 0)
1059			int_rel.r_symndx = RELOC_SECTION_BSS;
1060		      break;
1061		    case 'd':
1062		      if (strcmp (name, ".data") == 0)
1063			int_rel.r_symndx = RELOC_SECTION_DATA;
1064		      break;
1065		    case 'f':
1066		      if (strcmp (name, ".fini") == 0)
1067			int_rel.r_symndx = RELOC_SECTION_FINI;
1068		      break;
1069		    case 'i':
1070		      if (strcmp (name, ".init") == 0)
1071			int_rel.r_symndx = RELOC_SECTION_INIT;
1072		      break;
1073		    case 'l':
1074		      if (strcmp (name, ".lit8") == 0)
1075			int_rel.r_symndx = RELOC_SECTION_LIT8;
1076		      else if (strcmp (name, ".lit4") == 0)
1077			int_rel.r_symndx = RELOC_SECTION_LIT4;
1078		      break;
1079		    case 'r':
1080		      if (strcmp (name, ".rdata") == 0)
1081			int_rel.r_symndx = RELOC_SECTION_RDATA;
1082		      break;
1083		    case 's':
1084		      if (strcmp (name, ".sdata") == 0)
1085			int_rel.r_symndx = RELOC_SECTION_SDATA;
1086		      else if (strcmp (name, ".sbss") == 0)
1087			int_rel.r_symndx = RELOC_SECTION_SBSS;
1088		      break;
1089		    case 't':
1090		      if (strcmp (name, ".text") == 0)
1091			int_rel.r_symndx = RELOC_SECTION_TEXT;
1092		      break;
1093		    }
1094
1095		  if (int_rel.r_symndx == -1)
1096		    abort ();
1097
1098		  /* Add the section VMA and the symbol value.  */
1099		  relocation = (h->root.u.def.value
1100				+ s->output_section->vma
1101				+ s->output_offset);
1102
1103		  /* For a PC relative relocation, the object file
1104		     currently holds just the addend.  We must adjust
1105		     by the address to get the right value.  */
1106		  if (howto->pc_relative)
1107		    relocation -= int_rel.r_vaddr - input_section->vma;
1108
1109		  h = NULL;
1110		}
1111	      else
1112		{
1113		  /* Change the symndx value to the right one for the
1114		     output BFD.  */
1115		  int_rel.r_symndx = h->indx;
1116		  if (int_rel.r_symndx == -1)
1117		    {
1118		      /* This symbol is not being written out.  */
1119		      if (! ((*info->callbacks->unattached_reloc)
1120			     (info, h->root.root.string, input_bfd,
1121			      input_section,
1122			      int_rel.r_vaddr - input_section->vma)))
1123			return FALSE;
1124		      int_rel.r_symndx = 0;
1125		    }
1126		  relocation = 0;
1127		}
1128	    }
1129	  else
1130	    {
1131	      /* This is a relocation against a section.  Adjust the
1132		 value by the amount the section moved.  */
1133	      relocation = (s->output_section->vma
1134			    + s->output_offset
1135			    - s->vma);
1136	    }
1137
1138	  relocation += addend;
1139	  addend = 0;
1140
1141	  /* Adjust a PC relative relocation by removing the reference
1142	     to the original address in the section and including the
1143	     reference to the new address.  */
1144	  if (howto->pc_relative)
1145	    relocation -= (input_section->output_section->vma
1146			   + input_section->output_offset
1147			   - input_section->vma);
1148
1149	  /* Adjust the contents.  */
1150	  if (relocation == 0)
1151	    r = bfd_reloc_ok;
1152	  else
1153	    {
1154	      if (int_rel.r_type != MIPS_R_REFHI)
1155		r = _bfd_relocate_contents (howto, input_bfd, relocation,
1156					    (contents
1157					     + int_rel.r_vaddr
1158					     - input_section->vma));
1159	      else
1160		{
1161		  mips_relocate_hi (&int_rel,
1162				    use_lo ? &lo_int_rel : NULL,
1163				    input_bfd, input_section, contents,
1164				    relocation);
1165		  r = bfd_reloc_ok;
1166		}
1167	    }
1168
1169	  /* Adjust the reloc address.  */
1170	  int_rel.r_vaddr += (input_section->output_section->vma
1171			      + input_section->output_offset
1172			      - input_section->vma);
1173
1174	  /* Save the changed reloc information.  */
1175	  mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);
1176	}
1177      else
1178	{
1179	  /* We are producing a final executable.  */
1180	  if (int_rel.r_extern)
1181	    {
1182	      /* This is a reloc against a symbol.  */
1183	      if (h->root.type == bfd_link_hash_defined
1184		  || h->root.type == bfd_link_hash_defweak)
1185		{
1186		  asection *hsec;
1187
1188		  hsec = h->root.u.def.section;
1189		  relocation = (h->root.u.def.value
1190				+ hsec->output_section->vma
1191				+ hsec->output_offset);
1192		}
1193	      else
1194		{
1195		  if (! ((*info->callbacks->undefined_symbol)
1196			 (info, h->root.root.string, input_bfd,
1197			  input_section,
1198			  int_rel.r_vaddr - input_section->vma, TRUE)))
1199		    return FALSE;
1200		  relocation = 0;
1201		}
1202	    }
1203	  else
1204	    {
1205	      /* This is a reloc against a section.  */
1206	      relocation = (s->output_section->vma
1207			    + s->output_offset
1208			    - s->vma);
1209
1210	      /* A PC relative reloc is already correct in the object
1211		 file.  Make it look like a pcrel_offset relocation by
1212		 adding in the start address.  */
1213	      if (howto->pc_relative)
1214		relocation += int_rel.r_vaddr;
1215	    }
1216
1217	  if (int_rel.r_type != MIPS_R_REFHI)
1218	    r = _bfd_final_link_relocate (howto,
1219					  input_bfd,
1220					  input_section,
1221					  contents,
1222					  (int_rel.r_vaddr
1223					   - input_section->vma),
1224					  relocation,
1225					  addend);
1226	  else
1227	    {
1228	      mips_relocate_hi (&int_rel,
1229				use_lo ? &lo_int_rel : NULL,
1230				input_bfd, input_section, contents,
1231				relocation);
1232	      r = bfd_reloc_ok;
1233	    }
1234	}
1235
1236      /* MIPS_R_JMPADDR requires peculiar overflow detection.  The
1237	 instruction provides a 28 bit address (the two lower bits are
1238	 implicit zeroes) which is combined with the upper four bits
1239	 of the instruction address.  */
1240      if (r == bfd_reloc_ok
1241	  && int_rel.r_type == MIPS_R_JMPADDR
1242	  && (((relocation
1243		+ addend
1244		+ (int_rel.r_extern ? 0 : s->vma))
1245	       & 0xf0000000)
1246	      != ((input_section->output_section->vma
1247		   + input_section->output_offset
1248		   + (int_rel.r_vaddr - input_section->vma))
1249		  & 0xf0000000)))
1250	r = bfd_reloc_overflow;
1251
1252      if (r != bfd_reloc_ok)
1253	{
1254	  switch (r)
1255	    {
1256	    default:
1257	    case bfd_reloc_outofrange:
1258	      abort ();
1259	    case bfd_reloc_overflow:
1260	      {
1261		const char *name;
1262
1263		if (int_rel.r_extern)
1264		  name = h->root.root.string;
1265		else
1266		  name = bfd_section_name (input_bfd, s);
1267		if (! ((*info->callbacks->reloc_overflow)
1268		       (info, name, howto->name, (bfd_vma) 0,
1269			input_bfd, input_section,
1270			int_rel.r_vaddr - input_section->vma)))
1271		  return FALSE;
1272	      }
1273	      break;
1274	    }
1275	}
1276    }
1277
1278  return TRUE;
1279}
1280
1281/* This is the ECOFF backend structure.  The backend field of the
1282   target vector points to this.  */
1283
1284static const struct ecoff_backend_data mips_ecoff_backend_data =
1285{
1286  /* COFF backend structure.  */
1287  {
1288    (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
1289    (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
1290    (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
1291    (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
1292    (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
1293    (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
1294    (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
1295    mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
1296    mips_ecoff_swap_scnhdr_out,
1297    FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, FALSE, 4, FALSE, 2,
1298    mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
1299    mips_ecoff_swap_scnhdr_in, NULL,
1300    mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
1301    _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
1302    _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
1303    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1304    NULL, NULL
1305  },
1306  /* Supported architecture.  */
1307  bfd_arch_mips,
1308  /* Initial portion of armap string.  */
1309  "__________",
1310  /* The page boundary used to align sections in a demand-paged
1311     executable file.  E.g., 0x1000.  */
1312  0x1000,
1313  /* TRUE if the .rdata section is part of the text segment, as on the
1314     Alpha.  FALSE if .rdata is part of the data segment, as on the
1315     MIPS.  */
1316  FALSE,
1317  /* Bitsize of constructor entries.  */
1318  32,
1319  /* Reloc to use for constructor entries.  */
1320  &mips_howto_table[MIPS_R_REFWORD],
1321  {
1322    /* Symbol table magic number.  */
1323    magicSym,
1324    /* Alignment of debugging information.  E.g., 4.  */
1325    4,
1326    /* Sizes of external symbolic information.  */
1327    sizeof (struct hdr_ext),
1328    sizeof (struct dnr_ext),
1329    sizeof (struct pdr_ext),
1330    sizeof (struct sym_ext),
1331    sizeof (struct opt_ext),
1332    sizeof (struct fdr_ext),
1333    sizeof (struct rfd_ext),
1334    sizeof (struct ext_ext),
1335    /* Functions to swap in external symbolic data.  */
1336    ecoff_swap_hdr_in,
1337    ecoff_swap_dnr_in,
1338    ecoff_swap_pdr_in,
1339    ecoff_swap_sym_in,
1340    ecoff_swap_opt_in,
1341    ecoff_swap_fdr_in,
1342    ecoff_swap_rfd_in,
1343    ecoff_swap_ext_in,
1344    _bfd_ecoff_swap_tir_in,
1345    _bfd_ecoff_swap_rndx_in,
1346    /* Functions to swap out external symbolic data.  */
1347    ecoff_swap_hdr_out,
1348    ecoff_swap_dnr_out,
1349    ecoff_swap_pdr_out,
1350    ecoff_swap_sym_out,
1351    ecoff_swap_opt_out,
1352    ecoff_swap_fdr_out,
1353    ecoff_swap_rfd_out,
1354    ecoff_swap_ext_out,
1355    _bfd_ecoff_swap_tir_out,
1356    _bfd_ecoff_swap_rndx_out,
1357    /* Function to read in symbolic data.  */
1358    _bfd_ecoff_slurp_symbolic_info
1359  },
1360  /* External reloc size.  */
1361  RELSZ,
1362  /* Reloc swapping functions.  */
1363  mips_ecoff_swap_reloc_in,
1364  mips_ecoff_swap_reloc_out,
1365  /* Backend reloc tweaking.  */
1366  mips_adjust_reloc_in,
1367  mips_adjust_reloc_out,
1368  /* Relocate section contents while linking.  */
1369  mips_relocate_section,
1370  /* Do final adjustments to filehdr and aouthdr.  */
1371  NULL,
1372  /* Read an element from an archive at a given file position.  */
1373  _bfd_get_elt_at_filepos
1374};
1375
1376/* Looking up a reloc type is MIPS specific.  */
1377#define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
1378
1379/* Getting relocated section contents is generic.  */
1380#define _bfd_ecoff_bfd_get_relocated_section_contents \
1381  bfd_generic_get_relocated_section_contents
1382
1383/* Handling file windows is generic.  */
1384#define _bfd_ecoff_get_section_contents_in_window \
1385  _bfd_generic_get_section_contents_in_window
1386
1387/* Relaxing sections is MIPS specific.  */
1388#define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
1389
1390/* GC of sections is not done.  */
1391#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
1392
1393/* Merging of sections is not done.  */
1394#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
1395
1396#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
1397#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
1398#define _bfd_ecoff_section_already_linked \
1399  _bfd_generic_section_already_linked
1400
1401extern const bfd_target ecoff_big_vec;
1402
1403const bfd_target ecoff_little_vec =
1404{
1405  "ecoff-littlemips",		/* name */
1406  bfd_target_ecoff_flavour,
1407  BFD_ENDIAN_LITTLE,		/* data byte order is little */
1408  BFD_ENDIAN_LITTLE,		/* header byte order is little */
1409
1410  (HAS_RELOC | EXEC_P |		/* object flags */
1411   HAS_LINENO | HAS_DEBUG |
1412   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1413
1414  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1415  0,				/* leading underscore */
1416  ' ',				/* ar_pad_char */
1417  15,				/* ar_max_namelen */
1418  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1419     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1420     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1421  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1422     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1423     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
1424
1425  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1426     _bfd_ecoff_archive_p, _bfd_dummy_target},
1427  {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
1428     _bfd_generic_mkarchive, bfd_false},
1429  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1430     _bfd_write_archive_contents, bfd_false},
1431
1432     BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1433     BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1434     BFD_JUMP_TABLE_CORE (_bfd_nocore),
1435     BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1436     BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1437     BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1438     BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1439     BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1440     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1441
1442  & ecoff_big_vec,
1443
1444  (PTR) &mips_ecoff_backend_data
1445};
1446
1447const bfd_target ecoff_big_vec =
1448{
1449  "ecoff-bigmips",		/* name */
1450  bfd_target_ecoff_flavour,
1451  BFD_ENDIAN_BIG,		/* data byte order is big */
1452  BFD_ENDIAN_BIG,		/* header byte order is big */
1453
1454  (HAS_RELOC | EXEC_P |		/* object flags */
1455   HAS_LINENO | HAS_DEBUG |
1456   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1457
1458  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1459  0,				/* leading underscore */
1460  ' ',				/* ar_pad_char */
1461  15,				/* ar_max_namelen */
1462  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1463     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1464     bfd_getb16, bfd_getb_signed_16, bfd_putb16,
1465  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1466     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1467     bfd_getb16, bfd_getb_signed_16, bfd_putb16,
1468 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1469    _bfd_ecoff_archive_p, _bfd_dummy_target},
1470 {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
1471    _bfd_generic_mkarchive, bfd_false},
1472 {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1473    _bfd_write_archive_contents, bfd_false},
1474
1475     BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1476     BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1477     BFD_JUMP_TABLE_CORE (_bfd_nocore),
1478     BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1479     BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1480     BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1481     BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1482     BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1483     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1484
1485  & ecoff_little_vec,
1486
1487  (PTR) &mips_ecoff_backend_data
1488};
1489
1490const bfd_target ecoff_biglittle_vec =
1491{
1492  "ecoff-biglittlemips",		/* name */
1493  bfd_target_ecoff_flavour,
1494  BFD_ENDIAN_LITTLE,		/* data byte order is little */
1495  BFD_ENDIAN_BIG,		/* header byte order is big */
1496
1497  (HAS_RELOC | EXEC_P |		/* object flags */
1498   HAS_LINENO | HAS_DEBUG |
1499   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1500
1501  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1502  0,				/* leading underscore */
1503  ' ',				/* ar_pad_char */
1504  15,				/* ar_max_namelen */
1505  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1506     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1507     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1508  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1509     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1510     bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
1511
1512  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1513     _bfd_ecoff_archive_p, _bfd_dummy_target},
1514  {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
1515     _bfd_generic_mkarchive, bfd_false},
1516  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1517     _bfd_write_archive_contents, bfd_false},
1518
1519     BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1520     BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1521     BFD_JUMP_TABLE_CORE (_bfd_nocore),
1522     BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1523     BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1524     BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1525     BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1526     BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1527     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1528
1529  NULL,
1530
1531  (PTR) &mips_ecoff_backend_data
1532};
1533