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