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