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