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