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