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