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