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 
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 
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 
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 
233 /* See whether the magic number matches.  */
234 
235 static bfd_boolean
mips_ecoff_bad_format_hook(bfd * abfd,void * filehdr)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 
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
mips_ecoff_swap_reloc_in(bfd * abfd,void * ext_ptr,struct internal_reloc * intern)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
mips_ecoff_swap_reloc_out(bfd * abfd,const struct internal_reloc * intern,void * dst)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
mips_adjust_reloc_in(bfd * abfd,const struct internal_reloc * intern,arelent * rptr)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
mips_adjust_reloc_out(bfd * abfd ATTRIBUTE_UNUSED,const arelent * rel ATTRIBUTE_UNUSED,struct internal_reloc * intern ATTRIBUTE_UNUSED)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
mips_generic_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry,asymbol * symbol,void * data ATTRIBUTE_UNUSED,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)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
mips_refhi_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)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
mips_reflo_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)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
mips_gprel_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)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 *
mips_bfd_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)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 *
mips_bfd_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)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 
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
mips_relocate_hi(struct internal_reloc * refhi,struct internal_reloc * reflo,bfd * input_bfd,asection * input_section,bfd_byte * contents,bfd_vma relocation)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
mips_relocate_section(bfd * output_bfd,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,void * external_relocs)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 /* This is the ECOFF backend structure.  The backend field of the
1241    target vector points to this.  */
1242 
1243 static const struct ecoff_backend_data mips_ecoff_backend_data =
1244 {
1245   /* COFF backend structure.  */
1246   {
1247     (void (*) (bfd *,void *,int,int,int,int,void *)) bfd_void, /* aux_in */
1248     (void (*) (bfd *,void *,void *)) bfd_void, /* sym_in */
1249     (void (*) (bfd *,void *,void *)) bfd_void, /* lineno_in */
1250     (unsigned (*) (bfd *,void *,int,int,int,int,void *)) bfd_void,/*aux_out*/
1251     (unsigned (*) (bfd *,void *,void *)) bfd_void, /* sym_out */
1252     (unsigned (*) (bfd *,void *,void *)) bfd_void, /* lineno_out */
1253     (unsigned (*) (bfd *,void *,void *)) bfd_void, /* reloc_out */
1254     mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
1255     mips_ecoff_swap_scnhdr_out,
1256     FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE,
1257     ECOFF_NO_LONG_SECTION_NAMES, 4, FALSE, 2, 32768,
1258     mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
1259     mips_ecoff_swap_scnhdr_in, NULL,
1260     mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
1261     _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
1262     _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
1263     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1264     NULL, NULL, NULL
1265   },
1266   /* Supported architecture.  */
1267   bfd_arch_mips,
1268   /* Initial portion of armap string.  */
1269   "__________",
1270   /* The page boundary used to align sections in a demand-paged
1271      executable file.  E.g., 0x1000.  */
1272   0x1000,
1273   /* TRUE if the .rdata section is part of the text segment, as on the
1274      Alpha.  FALSE if .rdata is part of the data segment, as on the
1275      MIPS.  */
1276   FALSE,
1277   /* Bitsize of constructor entries.  */
1278   32,
1279   /* Reloc to use for constructor entries.  */
1280   &mips_howto_table[MIPS_R_REFWORD],
1281   {
1282     /* Symbol table magic number.  */
1283     magicSym,
1284     /* Alignment of debugging information.  E.g., 4.  */
1285     4,
1286     /* Sizes of external symbolic information.  */
1287     sizeof (struct hdr_ext),
1288     sizeof (struct dnr_ext),
1289     sizeof (struct pdr_ext),
1290     sizeof (struct sym_ext),
1291     sizeof (struct opt_ext),
1292     sizeof (struct fdr_ext),
1293     sizeof (struct rfd_ext),
1294     sizeof (struct ext_ext),
1295     /* Functions to swap in external symbolic data.  */
1296     ecoff_swap_hdr_in,
1297     ecoff_swap_dnr_in,
1298     ecoff_swap_pdr_in,
1299     ecoff_swap_sym_in,
1300     ecoff_swap_opt_in,
1301     ecoff_swap_fdr_in,
1302     ecoff_swap_rfd_in,
1303     ecoff_swap_ext_in,
1304     _bfd_ecoff_swap_tir_in,
1305     _bfd_ecoff_swap_rndx_in,
1306     /* Functions to swap out external symbolic data.  */
1307     ecoff_swap_hdr_out,
1308     ecoff_swap_dnr_out,
1309     ecoff_swap_pdr_out,
1310     ecoff_swap_sym_out,
1311     ecoff_swap_opt_out,
1312     ecoff_swap_fdr_out,
1313     ecoff_swap_rfd_out,
1314     ecoff_swap_ext_out,
1315     _bfd_ecoff_swap_tir_out,
1316     _bfd_ecoff_swap_rndx_out,
1317     /* Function to read in symbolic data.  */
1318     _bfd_ecoff_slurp_symbolic_info
1319   },
1320   /* External reloc size.  */
1321   RELSZ,
1322   /* Reloc swapping functions.  */
1323   mips_ecoff_swap_reloc_in,
1324   mips_ecoff_swap_reloc_out,
1325   /* Backend reloc tweaking.  */
1326   mips_adjust_reloc_in,
1327   mips_adjust_reloc_out,
1328   /* Relocate section contents while linking.  */
1329   mips_relocate_section,
1330   /* Do final adjustments to filehdr and aouthdr.  */
1331   NULL,
1332   /* Read an element from an archive at a given file position.  */
1333   _bfd_get_elt_at_filepos
1334 };
1335 
1336 /* Looking up a reloc type is MIPS specific.  */
1337 #define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
1338 #define _bfd_ecoff_bfd_reloc_name_lookup mips_bfd_reloc_name_lookup
1339 
1340 /* Getting relocated section contents is generic.  */
1341 #define _bfd_ecoff_bfd_get_relocated_section_contents \
1342   bfd_generic_get_relocated_section_contents
1343 
1344 /* Handling file windows is generic.  */
1345 #define _bfd_ecoff_get_section_contents_in_window \
1346   _bfd_generic_get_section_contents_in_window
1347 
1348 /* Relaxing sections is MIPS specific.  */
1349 #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
1350 
1351 /* GC of sections is not done.  */
1352 #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
1353 
1354 /* Input section flags is not implemented.  */
1355 #define _bfd_ecoff_bfd_lookup_section_flags bfd_generic_lookup_section_flags
1356 
1357 /* Merging of sections is not done.  */
1358 #define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
1359 
1360 #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
1361 #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
1362 #define _bfd_ecoff_section_already_linked \
1363   _bfd_coff_section_already_linked
1364 #define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol
1365 #define _bfd_ecoff_bfd_define_start_stop bfd_generic_define_start_stop
1366 #define _bfd_ecoff_set_reloc _bfd_generic_set_reloc
1367 
1368 extern const bfd_target mips_ecoff_be_vec;
1369 
1370 const bfd_target mips_ecoff_le_vec =
1371 {
1372   "ecoff-littlemips",		/* name */
1373   bfd_target_ecoff_flavour,
1374   BFD_ENDIAN_LITTLE,		/* data byte order is little */
1375   BFD_ENDIAN_LITTLE,		/* header byte order is little */
1376 
1377   (HAS_RELOC | EXEC_P |		/* object flags */
1378    HAS_LINENO | HAS_DEBUG |
1379    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1380 
1381   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1382   0,				/* leading underscore */
1383   ' ',				/* ar_pad_char */
1384   15,				/* ar_max_namelen */
1385   0,				/* match priority.  */
1386   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1387      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1388      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1389   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1390      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1391      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
1392 
1393   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1394      bfd_generic_archive_p, _bfd_dummy_target},
1395   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
1396      _bfd_generic_mkarchive, bfd_false},
1397   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1398      _bfd_write_archive_contents, bfd_false},
1399 
1400      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1401      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1402      BFD_JUMP_TABLE_CORE (_bfd_nocore),
1403      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1404      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1405      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1406      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1407      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1408      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1409 
1410   & mips_ecoff_be_vec,
1411 
1412   & mips_ecoff_backend_data
1413 };
1414 
1415 const bfd_target mips_ecoff_be_vec =
1416 {
1417   "ecoff-bigmips",		/* name */
1418   bfd_target_ecoff_flavour,
1419   BFD_ENDIAN_BIG,		/* data byte order is big */
1420   BFD_ENDIAN_BIG,		/* header byte order is big */
1421 
1422   (HAS_RELOC | EXEC_P |		/* object flags */
1423    HAS_LINENO | HAS_DEBUG |
1424    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1425 
1426   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1427   0,				/* leading underscore */
1428   ' ',				/* ar_pad_char */
1429   15,				/* ar_max_namelen */
1430   0,				/* match priority.  */
1431   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1432      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1433      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
1434   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1435      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1436      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
1437  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1438     bfd_generic_archive_p, _bfd_dummy_target},
1439  {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
1440     _bfd_generic_mkarchive, bfd_false},
1441  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1442     _bfd_write_archive_contents, bfd_false},
1443 
1444      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1445      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1446      BFD_JUMP_TABLE_CORE (_bfd_nocore),
1447      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1448      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1449      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1450      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1451      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1452      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1453 
1454   & mips_ecoff_le_vec,
1455 
1456   & mips_ecoff_backend_data
1457 };
1458 
1459 const bfd_target mips_ecoff_bele_vec =
1460 {
1461   "ecoff-biglittlemips",		/* name */
1462   bfd_target_ecoff_flavour,
1463   BFD_ENDIAN_LITTLE,		/* data byte order is little */
1464   BFD_ENDIAN_BIG,		/* header byte order is big */
1465 
1466   (HAS_RELOC | EXEC_P |		/* object flags */
1467    HAS_LINENO | HAS_DEBUG |
1468    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1469 
1470   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1471   0,				/* leading underscore */
1472   ' ',				/* ar_pad_char */
1473   15,				/* ar_max_namelen */
1474   0,				/* match priority.  */
1475   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1476      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1477      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1478   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1479      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1480      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
1481 
1482   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1483      bfd_generic_archive_p, _bfd_dummy_target},
1484   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
1485      _bfd_generic_mkarchive, bfd_false},
1486   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1487      _bfd_write_archive_contents, bfd_false},
1488 
1489      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1490      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1491      BFD_JUMP_TABLE_CORE (_bfd_nocore),
1492      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1493      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1494      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1495      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1496      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1497      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1498 
1499   NULL,
1500 
1501   & mips_ecoff_backend_data
1502 };
1503