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