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