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