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