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