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