1 /* MIPS-specific support for 64-bit ELF
2 Copyright 1996 Free Software Foundation, Inc.
3 Ian Lance Taylor, Cygnus Support
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 /* This file supports the 64-bit MIPS ELF ABI.
23 The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
24 overrides the usual ELF reloc handling, and handles reading and
25 writing the relocations here. */
35 /* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
36 use ECOFF. However, we support it anyhow for an easier changeover. */
38 #include "coff/symconst.h"
39 #include "coff/internal.h"
40 #include "coff/ecoff.h"
41 /* The 64 bit versions of the mdebug data structures are in alpha.h. */
42 #include "coff/alpha.h"
44 #include "ecoffswap.h"
46 static void mips_elf64_swap_reloc_in
47 PARAMS ((bfd
*, const Elf64_Mips_External_Rel
*,
48 Elf64_Mips_Internal_Rel
*));
49 static void mips_elf64_swap_reloca_in
50 PARAMS ((bfd
*, const Elf64_Mips_External_Rela
*,
51 Elf64_Mips_Internal_Rela
*));
53 static void mips_elf64_swap_reloc_out
54 PARAMS ((bfd
*, const Elf64_Mips_Internal_Rel
*,
55 Elf64_Mips_External_Rel
*));
57 static void mips_elf64_swap_reloca_out
58 PARAMS ((bfd
*, const Elf64_Mips_Internal_Rela
*,
59 Elf64_Mips_External_Rela
*));
60 static reloc_howto_type
*mips_elf64_reloc_type_lookup
61 PARAMS ((bfd
*, bfd_reloc_code_real_type
));
62 static long mips_elf64_get_reloc_upper_bound
PARAMS ((bfd
*, asection
*));
63 static boolean mips_elf64_slurp_one_reloc_table
64 PARAMS ((bfd
*, asection
*, asymbol
**, const Elf_Internal_Shdr
*));
65 static boolean mips_elf64_slurp_reloc_table
66 PARAMS ((bfd
*, asection
*, asymbol
**));
67 static void mips_elf64_write_relocs
PARAMS ((bfd
*, asection
*, PTR
));
68 static boolean mips_elf64_section_from_shdr
69 PARAMS ((bfd
*, Elf_Internal_Shdr
*, char *));
70 static boolean mips_elf64_section_processing
71 PARAMS ((bfd
*, Elf_Internal_Shdr
*));
73 /* The relocation types. */
75 enum mips_elf64_reloc_type
100 R_MIPS_GOT_OFST
= 21,
101 R_MIPS_GOT_HI16
= 22,
102 R_MIPS_GOT_LO16
= 23,
104 R_MIPS_INSERT_A
= 25,
105 R_MIPS_INSERT_B
= 26,
109 R_MIPS_CALL_HI16
= 30,
110 R_MIPS_CALL_LO16
= 31,
111 R_MIPS_SCN_DISP
= 32,
113 R_MIPS_ADD_IMMEDIATE
= 34,
118 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
119 from smaller values. Start with zero, widen, *then* decrement. */
120 #define MINUS_ONE (((bfd_vma)0) - 1)
122 /* The relocation table used for SHT_REL sections. */
124 static reloc_howto_type mips_elf64_howto_table_rel
[] =
127 HOWTO (R_MIPS_NONE
, /* type */
129 0, /* size (0 = byte, 1 = short, 2 = long) */
131 false, /* pc_relative */
133 complain_overflow_dont
, /* complain_on_overflow */
134 bfd_elf_generic_reloc
, /* special_function */
135 "R_MIPS_NONE", /* name */
136 false, /* partial_inplace */
139 false), /* pcrel_offset */
141 /* 16 bit relocation. */
142 HOWTO (R_MIPS_16
, /* type */
144 1, /* size (0 = byte, 1 = short, 2 = long) */
146 false, /* pc_relative */
148 complain_overflow_bitfield
, /* complain_on_overflow */
149 bfd_elf_generic_reloc
, /* special_function */
150 "R_MIPS_16", /* name */
151 true, /* partial_inplace */
152 0xffff, /* src_mask */
153 0xffff, /* dst_mask */
154 false), /* pcrel_offset */
156 /* 32 bit relocation. */
157 HOWTO (R_MIPS_32
, /* type */
159 2, /* size (0 = byte, 1 = short, 2 = long) */
161 false, /* pc_relative */
163 complain_overflow_bitfield
, /* complain_on_overflow */
164 bfd_elf_generic_reloc
, /* special_function */
165 "R_MIPS_32", /* name */
166 true, /* partial_inplace */
167 0xffffffff, /* src_mask */
168 0xffffffff, /* dst_mask */
169 false), /* pcrel_offset */
171 /* 32 bit symbol relative relocation. */
172 HOWTO (R_MIPS_REL32
, /* type */
174 2, /* size (0 = byte, 1 = short, 2 = long) */
176 false, /* pc_relative */
178 complain_overflow_bitfield
, /* complain_on_overflow */
179 bfd_elf_generic_reloc
, /* special_function */
180 "R_MIPS_REL32", /* name */
181 true, /* partial_inplace */
182 0xffffffff, /* src_mask */
183 0xffffffff, /* dst_mask */
184 false), /* pcrel_offset */
186 /* 26 bit branch address. */
187 HOWTO (R_MIPS_26
, /* type */
189 2, /* size (0 = byte, 1 = short, 2 = long) */
191 false, /* pc_relative */
193 complain_overflow_dont
, /* complain_on_overflow */
194 /* This needs complex overflow
195 detection, because the upper four
196 bits must match the PC. */
197 bfd_elf_generic_reloc
, /* special_function */
198 "R_MIPS_26", /* name */
199 true, /* partial_inplace */
200 0x3ffffff, /* src_mask */
201 0x3ffffff, /* dst_mask */
202 false), /* pcrel_offset */
204 /* High 16 bits of symbol value. */
205 HOWTO (R_MIPS_HI16
, /* type */
207 2, /* size (0 = byte, 1 = short, 2 = long) */
209 false, /* pc_relative */
211 complain_overflow_dont
, /* complain_on_overflow */
212 _bfd_mips_elf_hi16_reloc
, /* special_function */
213 "R_MIPS_HI16", /* name */
214 true, /* partial_inplace */
215 0xffff, /* src_mask */
216 0xffff, /* dst_mask */
217 false), /* pcrel_offset */
219 /* Low 16 bits of symbol value. */
220 HOWTO (R_MIPS_LO16
, /* type */
222 2, /* size (0 = byte, 1 = short, 2 = long) */
224 false, /* pc_relative */
226 complain_overflow_dont
, /* complain_on_overflow */
227 _bfd_mips_elf_lo16_reloc
, /* special_function */
228 "R_MIPS_LO16", /* name */
229 true, /* partial_inplace */
230 0xffff, /* src_mask */
231 0xffff, /* dst_mask */
232 false), /* pcrel_offset */
234 /* GP relative reference. */
235 HOWTO (R_MIPS_GPREL16
, /* type */
237 2, /* size (0 = byte, 1 = short, 2 = long) */
239 false, /* pc_relative */
241 complain_overflow_signed
, /* complain_on_overflow */
242 _bfd_mips_elf_gprel16_reloc
, /* special_function */
243 "R_MIPS_GPREL16", /* name */
244 true, /* partial_inplace */
245 0xffff, /* src_mask */
246 0xffff, /* dst_mask */
247 false), /* pcrel_offset */
249 /* Reference to literal section. */
250 HOWTO (R_MIPS_LITERAL
, /* type */
252 2, /* size (0 = byte, 1 = short, 2 = long) */
254 false, /* pc_relative */
256 complain_overflow_signed
, /* complain_on_overflow */
257 _bfd_mips_elf_gprel16_reloc
, /* special_function */
258 "R_MIPS_LITERAL", /* name */
259 true, /* partial_inplace */
260 0xffff, /* src_mask */
261 0xffff, /* dst_mask */
262 false), /* pcrel_offset */
264 /* Reference to global offset table. */
265 HOWTO (R_MIPS_GOT16
, /* type */
267 2, /* size (0 = byte, 1 = short, 2 = long) */
269 false, /* pc_relative */
271 complain_overflow_signed
, /* complain_on_overflow */
272 _bfd_mips_elf_got16_reloc
, /* special_function */
273 "R_MIPS_GOT16", /* name */
274 false, /* partial_inplace */
276 0xffff, /* dst_mask */
277 false), /* pcrel_offset */
279 /* 16 bit PC relative reference. */
280 HOWTO (R_MIPS_PC16
, /* type */
282 2, /* size (0 = byte, 1 = short, 2 = long) */
284 true, /* pc_relative */
286 complain_overflow_signed
, /* complain_on_overflow */
287 bfd_elf_generic_reloc
, /* special_function */
288 "R_MIPS_PC16", /* name */
289 true, /* partial_inplace */
290 0xffff, /* src_mask */
291 0xffff, /* dst_mask */
292 false), /* pcrel_offset */
294 /* 16 bit call through global offset table. */
295 /* FIXME: This is not handled correctly. */
296 HOWTO (R_MIPS_CALL16
, /* type */
298 2, /* size (0 = byte, 1 = short, 2 = long) */
300 false, /* pc_relative */
302 complain_overflow_signed
, /* complain_on_overflow */
303 bfd_elf_generic_reloc
, /* special_function */
304 "R_MIPS_CALL16", /* name */
305 false, /* partial_inplace */
307 0xffff, /* dst_mask */
308 false), /* pcrel_offset */
310 /* 32 bit GP relative reference. */
311 HOWTO (R_MIPS_GPREL32
, /* type */
313 2, /* size (0 = byte, 1 = short, 2 = long) */
315 false, /* pc_relative */
317 complain_overflow_bitfield
, /* complain_on_overflow */
318 _bfd_mips_elf_gprel32_reloc
, /* special_function */
319 "R_MIPS_GPREL32", /* name */
320 true, /* partial_inplace */
321 0xffffffff, /* src_mask */
322 0xffffffff, /* dst_mask */
323 false), /* pcrel_offset */
329 /* A 5 bit shift field. */
330 HOWTO (R_MIPS_SHIFT5
, /* type */
332 2, /* size (0 = byte, 1 = short, 2 = long) */
334 false, /* pc_relative */
336 complain_overflow_bitfield
, /* complain_on_overflow */
337 bfd_elf_generic_reloc
, /* special_function */
338 "R_MIPS_SHIFT5", /* name */
339 true, /* partial_inplace */
340 0x000007c0, /* src_mask */
341 0x000007c0, /* dst_mask */
342 false), /* pcrel_offset */
344 /* A 6 bit shift field. */
345 /* FIXME: This is not handled correctly; a special function is
346 needed to put the most significant bit in the right place. */
347 HOWTO (R_MIPS_SHIFT6
, /* type */
349 2, /* size (0 = byte, 1 = short, 2 = long) */
351 false, /* pc_relative */
353 complain_overflow_bitfield
, /* complain_on_overflow */
354 bfd_elf_generic_reloc
, /* special_function */
355 "R_MIPS_SHIFT6", /* name */
356 true, /* partial_inplace */
357 0x000007c4, /* src_mask */
358 0x000007c4, /* dst_mask */
359 false), /* pcrel_offset */
361 /* 64 bit relocation. */
362 HOWTO (R_MIPS_64
, /* type */
364 4, /* size (0 = byte, 1 = short, 2 = long) */
366 false, /* pc_relative */
368 complain_overflow_bitfield
, /* complain_on_overflow */
369 bfd_elf_generic_reloc
, /* special_function */
370 "R_MIPS_64", /* name */
371 true, /* partial_inplace */
372 MINUS_ONE
, /* src_mask */
373 MINUS_ONE
, /* dst_mask */
374 false), /* pcrel_offset */
376 /* Displacement in the global offset table. */
377 /* FIXME: Not handled correctly. */
378 HOWTO (R_MIPS_GOT_DISP
, /* type */
380 2, /* size (0 = byte, 1 = short, 2 = long) */
382 false, /* pc_relative */
384 complain_overflow_bitfield
, /* complain_on_overflow */
385 bfd_elf_generic_reloc
, /* special_function */
386 "R_MIPS_GOT_DISP", /* name */
387 true, /* partial_inplace */
388 0x0000ffff, /* src_mask */
389 0x0000ffff, /* dst_mask */
390 false), /* pcrel_offset */
392 /* Displacement to page pointer in the global offset table. */
393 /* FIXME: Not handled correctly. */
394 HOWTO (R_MIPS_GOT_PAGE
, /* type */
396 2, /* size (0 = byte, 1 = short, 2 = long) */
398 false, /* pc_relative */
400 complain_overflow_bitfield
, /* complain_on_overflow */
401 bfd_elf_generic_reloc
, /* special_function */
402 "R_MIPS_GOT_PAGE", /* name */
403 true, /* partial_inplace */
404 0x0000ffff, /* src_mask */
405 0x0000ffff, /* dst_mask */
406 false), /* pcrel_offset */
408 /* Offset from page pointer in the global offset table. */
409 /* FIXME: Not handled correctly. */
410 HOWTO (R_MIPS_GOT_OFST
, /* type */
412 2, /* size (0 = byte, 1 = short, 2 = long) */
414 false, /* pc_relative */
416 complain_overflow_bitfield
, /* complain_on_overflow */
417 bfd_elf_generic_reloc
, /* special_function */
418 "R_MIPS_GOT_OFST", /* name */
419 true, /* partial_inplace */
420 0x0000ffff, /* src_mask */
421 0x0000ffff, /* dst_mask */
422 false), /* pcrel_offset */
424 /* High 16 bits of displacement in global offset table. */
425 /* FIXME: Not handled correctly. */
426 HOWTO (R_MIPS_GOT_HI16
, /* type */
428 2, /* size (0 = byte, 1 = short, 2 = long) */
430 false, /* pc_relative */
432 complain_overflow_dont
, /* complain_on_overflow */
433 bfd_elf_generic_reloc
, /* special_function */
434 "R_MIPS_GOT_HI16", /* name */
435 true, /* partial_inplace */
436 0x0000ffff, /* src_mask */
437 0x0000ffff, /* dst_mask */
438 false), /* pcrel_offset */
440 /* Low 16 bits of displacement in global offset table. */
441 /* FIXME: Not handled correctly. */
442 HOWTO (R_MIPS_GOT_LO16
, /* type */
444 2, /* size (0 = byte, 1 = short, 2 = long) */
446 false, /* pc_relative */
448 complain_overflow_dont
, /* complain_on_overflow */
449 bfd_elf_generic_reloc
, /* special_function */
450 "R_MIPS_GOT_LO16", /* name */
451 true, /* partial_inplace */
452 0x0000ffff, /* src_mask */
453 0x0000ffff, /* dst_mask */
454 false), /* pcrel_offset */
456 /* 64 bit substraction. */
457 /* FIXME: Not handled correctly. */
458 HOWTO (R_MIPS_SUB
, /* type */
460 4, /* size (0 = byte, 1 = short, 2 = long) */
462 false, /* pc_relative */
464 complain_overflow_bitfield
, /* complain_on_overflow */
465 bfd_elf_generic_reloc
, /* special_function */
466 "R_MIPS_SUB", /* name */
467 true, /* partial_inplace */
468 MINUS_ONE
, /* src_mask */
469 MINUS_ONE
, /* dst_mask */
470 false), /* pcrel_offset */
472 /* Insert the addend as an instruction. */
473 /* FIXME: Not handled correctly. */
474 HOWTO (R_MIPS_INSERT_A
, /* type */
476 0, /* size (0 = byte, 1 = short, 2 = long) */
478 false, /* pc_relative */
480 complain_overflow_dont
, /* complain_on_overflow */
481 bfd_elf_generic_reloc
, /* special_function */
482 "R_MIPS_INSERT_A", /* name */
483 false, /* partial_inplace */
486 false), /* pcrel_offset */
488 /* Insert the addend as an instruction, and change all relocations
489 to refer to the old instruction at the address. */
490 /* FIXME: Not handled correctly. */
491 HOWTO (R_MIPS_INSERT_B
, /* type */
493 0, /* size (0 = byte, 1 = short, 2 = long) */
495 false, /* pc_relative */
497 complain_overflow_dont
, /* complain_on_overflow */
498 bfd_elf_generic_reloc
, /* special_function */
499 "R_MIPS_INSERT_B", /* name */
500 false, /* partial_inplace */
503 false), /* pcrel_offset */
505 /* Delete a 32 bit instruction. */
506 /* FIXME: Not handled correctly. */
507 HOWTO (R_MIPS_DELETE
, /* type */
509 0, /* size (0 = byte, 1 = short, 2 = long) */
511 false, /* pc_relative */
513 complain_overflow_dont
, /* complain_on_overflow */
514 bfd_elf_generic_reloc
, /* special_function */
515 "R_MIPS_DELETE", /* name */
516 false, /* partial_inplace */
519 false), /* pcrel_offset */
521 /* Get the higher value of a 64 bit addend. */
522 /* FIXME: Not handled correctly. */
523 HOWTO (R_MIPS_HIGHER
, /* type */
525 2, /* size (0 = byte, 1 = short, 2 = long) */
527 false, /* pc_relative */
529 complain_overflow_dont
, /* complain_on_overflow */
530 bfd_elf_generic_reloc
, /* special_function */
531 "R_MIPS_HIGHER", /* name */
532 true, /* partial_inplace */
533 0xffff, /* src_mask */
534 0xffff, /* dst_mask */
535 false), /* pcrel_offset */
537 /* Get the highest value of a 64 bit addend. */
538 /* FIXME: Not handled correctly. */
539 HOWTO (R_MIPS_HIGHEST
, /* type */
541 2, /* size (0 = byte, 1 = short, 2 = long) */
543 false, /* pc_relative */
545 complain_overflow_dont
, /* complain_on_overflow */
546 bfd_elf_generic_reloc
, /* special_function */
547 "R_MIPS_HIGHEST", /* name */
548 true, /* partial_inplace */
549 0xffff, /* src_mask */
550 0xffff, /* dst_mask */
551 false), /* pcrel_offset */
553 /* High 16 bits of displacement in global offset table. */
554 /* FIXME: Not handled correctly. */
555 HOWTO (R_MIPS_CALL_HI16
, /* type */
557 2, /* size (0 = byte, 1 = short, 2 = long) */
559 false, /* pc_relative */
561 complain_overflow_dont
, /* complain_on_overflow */
562 bfd_elf_generic_reloc
, /* special_function */
563 "R_MIPS_CALL_HI16", /* name */
564 true, /* partial_inplace */
565 0x0000ffff, /* src_mask */
566 0x0000ffff, /* dst_mask */
567 false), /* pcrel_offset */
569 /* Low 16 bits of displacement in global offset table. */
570 /* FIXME: Not handled correctly. */
571 HOWTO (R_MIPS_CALL_LO16
, /* type */
573 2, /* size (0 = byte, 1 = short, 2 = long) */
575 false, /* pc_relative */
577 complain_overflow_dont
, /* complain_on_overflow */
578 bfd_elf_generic_reloc
, /* special_function */
579 "R_MIPS_CALL_LO16", /* name */
580 true, /* partial_inplace */
581 0x0000ffff, /* src_mask */
582 0x0000ffff, /* dst_mask */
583 false), /* pcrel_offset */
585 /* I'm not sure what the remaining relocs are, but they are defined
588 HOWTO (R_MIPS_SCN_DISP
, /* type */
590 0, /* size (0 = byte, 1 = short, 2 = long) */
592 false, /* pc_relative */
594 complain_overflow_dont
, /* complain_on_overflow */
595 bfd_elf_generic_reloc
, /* special_function */
596 "R_MIPS_SCN_DISP", /* name */
597 false, /* partial_inplace */
600 false), /* pcrel_offset */
602 HOWTO (R_MIPS_REL16
, /* type */
604 0, /* size (0 = byte, 1 = short, 2 = long) */
606 false, /* pc_relative */
608 complain_overflow_dont
, /* complain_on_overflow */
609 bfd_elf_generic_reloc
, /* special_function */
610 "R_MIPS_REL16", /* name */
611 false, /* partial_inplace */
614 false), /* pcrel_offset */
616 HOWTO (R_MIPS_ADD_IMMEDIATE
, /* type */
618 0, /* size (0 = byte, 1 = short, 2 = long) */
620 false, /* pc_relative */
622 complain_overflow_dont
, /* complain_on_overflow */
623 bfd_elf_generic_reloc
, /* special_function */
624 "R_MIPS_ADD_IMMEDIATE", /* name */
625 false, /* partial_inplace */
628 false), /* pcrel_offset */
630 HOWTO (R_MIPS_PJUMP
, /* type */
632 0, /* size (0 = byte, 1 = short, 2 = long) */
634 false, /* pc_relative */
636 complain_overflow_dont
, /* complain_on_overflow */
637 bfd_elf_generic_reloc
, /* special_function */
638 "R_MIPS_PJUMP", /* name */
639 false, /* partial_inplace */
642 false), /* pcrel_offset */
644 HOWTO (R_MIPS_RELGOT
, /* type */
646 0, /* size (0 = byte, 1 = short, 2 = long) */
648 false, /* pc_relative */
650 complain_overflow_dont
, /* complain_on_overflow */
651 bfd_elf_generic_reloc
, /* special_function */
652 "R_MIPS_RELGOT", /* name */
653 false, /* partial_inplace */
656 false) /* pcrel_offset */
659 /* The relocation table used for SHT_RELA sections. */
661 static reloc_howto_type mips_elf64_howto_table_rela
[] =
664 HOWTO (R_MIPS_NONE
, /* type */
666 0, /* size (0 = byte, 1 = short, 2 = long) */
668 false, /* pc_relative */
670 complain_overflow_dont
, /* complain_on_overflow */
671 bfd_elf_generic_reloc
, /* special_function */
672 "R_MIPS_NONE", /* name */
673 false, /* partial_inplace */
676 false), /* pcrel_offset */
678 /* 16 bit relocation. */
679 HOWTO (R_MIPS_16
, /* type */
681 1, /* size (0 = byte, 1 = short, 2 = long) */
683 false, /* pc_relative */
685 complain_overflow_bitfield
, /* complain_on_overflow */
686 bfd_elf_generic_reloc
, /* special_function */
687 "R_MIPS_16", /* name */
688 true, /* partial_inplace */
690 0xffff, /* dst_mask */
691 false), /* pcrel_offset */
693 /* 32 bit relocation. */
694 HOWTO (R_MIPS_32
, /* type */
696 2, /* size (0 = byte, 1 = short, 2 = long) */
698 false, /* pc_relative */
700 complain_overflow_bitfield
, /* complain_on_overflow */
701 bfd_elf_generic_reloc
, /* special_function */
702 "R_MIPS_32", /* name */
703 true, /* partial_inplace */
705 0xffffffff, /* dst_mask */
706 false), /* pcrel_offset */
708 /* 32 bit symbol relative relocation. */
709 HOWTO (R_MIPS_REL32
, /* type */
711 2, /* size (0 = byte, 1 = short, 2 = long) */
713 false, /* pc_relative */
715 complain_overflow_bitfield
, /* complain_on_overflow */
716 bfd_elf_generic_reloc
, /* special_function */
717 "R_MIPS_REL32", /* name */
718 true, /* partial_inplace */
720 0xffffffff, /* dst_mask */
721 false), /* pcrel_offset */
723 /* 26 bit branch address. */
724 HOWTO (R_MIPS_26
, /* type */
726 2, /* size (0 = byte, 1 = short, 2 = long) */
728 false, /* pc_relative */
730 complain_overflow_dont
, /* complain_on_overflow */
731 /* This needs complex overflow
732 detection, because the upper four
733 bits must match the PC. */
734 bfd_elf_generic_reloc
, /* special_function */
735 "R_MIPS_26", /* name */
736 true, /* partial_inplace */
738 0x3ffffff, /* dst_mask */
739 false), /* pcrel_offset */
741 /* High 16 bits of symbol value. */
742 HOWTO (R_MIPS_HI16
, /* type */
744 2, /* size (0 = byte, 1 = short, 2 = long) */
746 false, /* pc_relative */
748 complain_overflow_dont
, /* complain_on_overflow */
749 bfd_elf_generic_reloc
, /* special_function */
750 "R_MIPS_HI16", /* name */
751 true, /* partial_inplace */
753 0xffff, /* dst_mask */
754 false), /* pcrel_offset */
756 /* Low 16 bits of symbol value. */
757 HOWTO (R_MIPS_LO16
, /* type */
759 2, /* size (0 = byte, 1 = short, 2 = long) */
761 false, /* pc_relative */
763 complain_overflow_dont
, /* complain_on_overflow */
764 bfd_elf_generic_reloc
, /* special_function */
765 "R_MIPS_LO16", /* name */
766 true, /* partial_inplace */
768 0xffff, /* dst_mask */
769 false), /* pcrel_offset */
771 /* GP relative reference. */
772 HOWTO (R_MIPS_GPREL16
, /* type */
774 2, /* size (0 = byte, 1 = short, 2 = long) */
776 false, /* pc_relative */
778 complain_overflow_signed
, /* complain_on_overflow */
779 _bfd_mips_elf_gprel16_reloc
, /* special_function */
780 "R_MIPS_GPREL16", /* name */
781 true, /* partial_inplace */
783 0xffff, /* dst_mask */
784 false), /* pcrel_offset */
786 /* Reference to literal section. */
787 HOWTO (R_MIPS_LITERAL
, /* type */
789 2, /* size (0 = byte, 1 = short, 2 = long) */
791 false, /* pc_relative */
793 complain_overflow_signed
, /* complain_on_overflow */
794 _bfd_mips_elf_gprel16_reloc
, /* special_function */
795 "R_MIPS_LITERAL", /* name */
796 true, /* partial_inplace */
798 0xffff, /* dst_mask */
799 false), /* pcrel_offset */
801 /* Reference to global offset table. */
802 /* FIXME: This is not handled correctly. */
803 HOWTO (R_MIPS_GOT16
, /* type */
805 2, /* size (0 = byte, 1 = short, 2 = long) */
807 false, /* pc_relative */
809 complain_overflow_signed
, /* complain_on_overflow */
810 bfd_elf_generic_reloc
, /* special_function */
811 "R_MIPS_GOT16", /* name */
812 false, /* partial_inplace */
814 0xffff, /* dst_mask */
815 false), /* pcrel_offset */
817 /* 16 bit PC relative reference. */
818 HOWTO (R_MIPS_PC16
, /* type */
820 2, /* size (0 = byte, 1 = short, 2 = long) */
822 true, /* pc_relative */
824 complain_overflow_signed
, /* complain_on_overflow */
825 bfd_elf_generic_reloc
, /* special_function */
826 "R_MIPS_PC16", /* name */
827 true, /* partial_inplace */
829 0xffff, /* dst_mask */
830 false), /* pcrel_offset */
832 /* 16 bit call through global offset table. */
833 /* FIXME: This is not handled correctly. */
834 HOWTO (R_MIPS_CALL16
, /* type */
836 2, /* size (0 = byte, 1 = short, 2 = long) */
838 false, /* pc_relative */
840 complain_overflow_signed
, /* complain_on_overflow */
841 bfd_elf_generic_reloc
, /* special_function */
842 "R_MIPS_CALL16", /* name */
843 false, /* partial_inplace */
845 0xffff, /* dst_mask */
846 false), /* pcrel_offset */
848 /* 32 bit GP relative reference. */
849 HOWTO (R_MIPS_GPREL32
, /* type */
851 2, /* size (0 = byte, 1 = short, 2 = long) */
853 false, /* pc_relative */
855 complain_overflow_bitfield
, /* complain_on_overflow */
856 _bfd_mips_elf_gprel32_reloc
, /* special_function */
857 "R_MIPS_GPREL32", /* name */
858 true, /* partial_inplace */
860 0xffffffff, /* dst_mask */
861 false), /* pcrel_offset */
867 /* A 5 bit shift field. */
868 HOWTO (R_MIPS_SHIFT5
, /* type */
870 2, /* size (0 = byte, 1 = short, 2 = long) */
872 false, /* pc_relative */
874 complain_overflow_bitfield
, /* complain_on_overflow */
875 bfd_elf_generic_reloc
, /* special_function */
876 "R_MIPS_SHIFT5", /* name */
877 true, /* partial_inplace */
879 0x000007c0, /* dst_mask */
880 false), /* pcrel_offset */
882 /* A 6 bit shift field. */
883 /* FIXME: This is not handled correctly; a special function is
884 needed to put the most significant bit in the right place. */
885 HOWTO (R_MIPS_SHIFT6
, /* type */
887 2, /* size (0 = byte, 1 = short, 2 = long) */
889 false, /* pc_relative */
891 complain_overflow_bitfield
, /* complain_on_overflow */
892 bfd_elf_generic_reloc
, /* special_function */
893 "R_MIPS_SHIFT6", /* name */
894 true, /* partial_inplace */
896 0x000007c4, /* dst_mask */
897 false), /* pcrel_offset */
899 /* 64 bit relocation. */
900 HOWTO (R_MIPS_64
, /* type */
902 4, /* size (0 = byte, 1 = short, 2 = long) */
904 false, /* pc_relative */
906 complain_overflow_bitfield
, /* complain_on_overflow */
907 bfd_elf_generic_reloc
, /* special_function */
908 "R_MIPS_64", /* name */
909 true, /* partial_inplace */
911 MINUS_ONE
, /* dst_mask */
912 false), /* pcrel_offset */
914 /* Displacement in the global offset table. */
915 /* FIXME: Not handled correctly. */
916 HOWTO (R_MIPS_GOT_DISP
, /* type */
918 2, /* size (0 = byte, 1 = short, 2 = long) */
920 false, /* pc_relative */
922 complain_overflow_bitfield
, /* complain_on_overflow */
923 bfd_elf_generic_reloc
, /* special_function */
924 "R_MIPS_GOT_DISP", /* name */
925 true, /* partial_inplace */
927 0x0000ffff, /* dst_mask */
928 false), /* pcrel_offset */
930 /* Displacement to page pointer in the global offset table. */
931 /* FIXME: Not handled correctly. */
932 HOWTO (R_MIPS_GOT_PAGE
, /* type */
934 2, /* size (0 = byte, 1 = short, 2 = long) */
936 false, /* pc_relative */
938 complain_overflow_bitfield
, /* complain_on_overflow */
939 bfd_elf_generic_reloc
, /* special_function */
940 "R_MIPS_GOT_PAGE", /* name */
941 true, /* partial_inplace */
943 0x0000ffff, /* dst_mask */
944 false), /* pcrel_offset */
946 /* Offset from page pointer in the global offset table. */
947 /* FIXME: Not handled correctly. */
948 HOWTO (R_MIPS_GOT_OFST
, /* type */
950 2, /* size (0 = byte, 1 = short, 2 = long) */
952 false, /* pc_relative */
954 complain_overflow_bitfield
, /* complain_on_overflow */
955 bfd_elf_generic_reloc
, /* special_function */
956 "R_MIPS_GOT_OFST", /* name */
957 true, /* partial_inplace */
959 0x0000ffff, /* dst_mask */
960 false), /* pcrel_offset */
962 /* High 16 bits of displacement in global offset table. */
963 /* FIXME: Not handled correctly. */
964 HOWTO (R_MIPS_GOT_HI16
, /* type */
966 2, /* size (0 = byte, 1 = short, 2 = long) */
968 false, /* pc_relative */
970 complain_overflow_dont
, /* complain_on_overflow */
971 bfd_elf_generic_reloc
, /* special_function */
972 "R_MIPS_GOT_HI16", /* name */
973 true, /* partial_inplace */
975 0x0000ffff, /* dst_mask */
976 false), /* pcrel_offset */
978 /* Low 16 bits of displacement in global offset table. */
979 /* FIXME: Not handled correctly. */
980 HOWTO (R_MIPS_GOT_LO16
, /* type */
982 2, /* size (0 = byte, 1 = short, 2 = long) */
984 false, /* pc_relative */
986 complain_overflow_dont
, /* complain_on_overflow */
987 bfd_elf_generic_reloc
, /* special_function */
988 "R_MIPS_GOT_LO16", /* name */
989 true, /* partial_inplace */
991 0x0000ffff, /* dst_mask */
992 false), /* pcrel_offset */
994 /* 64 bit substraction. */
995 /* FIXME: Not handled correctly. */
996 HOWTO (R_MIPS_SUB
, /* type */
998 4, /* size (0 = byte, 1 = short, 2 = long) */
1000 false, /* pc_relative */
1002 complain_overflow_bitfield
, /* complain_on_overflow */
1003 bfd_elf_generic_reloc
, /* special_function */
1004 "R_MIPS_SUB", /* name */
1005 true, /* partial_inplace */
1007 MINUS_ONE
, /* dst_mask */
1008 false), /* pcrel_offset */
1010 /* Insert the addend as an instruction. */
1011 /* FIXME: Not handled correctly. */
1012 HOWTO (R_MIPS_INSERT_A
, /* type */
1014 0, /* size (0 = byte, 1 = short, 2 = long) */
1016 false, /* pc_relative */
1018 complain_overflow_dont
, /* complain_on_overflow */
1019 bfd_elf_generic_reloc
, /* special_function */
1020 "R_MIPS_INSERT_A", /* name */
1021 false, /* partial_inplace */
1024 false), /* pcrel_offset */
1026 /* Insert the addend as an instruction, and change all relocations
1027 to refer to the old instruction at the address. */
1028 /* FIXME: Not handled correctly. */
1029 HOWTO (R_MIPS_INSERT_B
, /* type */
1031 0, /* size (0 = byte, 1 = short, 2 = long) */
1033 false, /* pc_relative */
1035 complain_overflow_dont
, /* complain_on_overflow */
1036 bfd_elf_generic_reloc
, /* special_function */
1037 "R_MIPS_INSERT_B", /* name */
1038 false, /* partial_inplace */
1041 false), /* pcrel_offset */
1043 /* Delete a 32 bit instruction. */
1044 /* FIXME: Not handled correctly. */
1045 HOWTO (R_MIPS_DELETE
, /* type */
1047 0, /* size (0 = byte, 1 = short, 2 = long) */
1049 false, /* pc_relative */
1051 complain_overflow_dont
, /* complain_on_overflow */
1052 bfd_elf_generic_reloc
, /* special_function */
1053 "R_MIPS_DELETE", /* name */
1054 false, /* partial_inplace */
1057 false), /* pcrel_offset */
1059 /* Get the higher value of a 64 bit addend. */
1060 /* FIXME: Not handled correctly. */
1061 HOWTO (R_MIPS_HIGHER
, /* type */
1063 2, /* size (0 = byte, 1 = short, 2 = long) */
1065 false, /* pc_relative */
1067 complain_overflow_dont
, /* complain_on_overflow */
1068 bfd_elf_generic_reloc
, /* special_function */
1069 "R_MIPS_HIGHER", /* name */
1070 true, /* partial_inplace */
1072 0xffff, /* dst_mask */
1073 false), /* pcrel_offset */
1075 /* Get the highest value of a 64 bit addend. */
1076 /* FIXME: Not handled correctly. */
1077 HOWTO (R_MIPS_HIGHEST
, /* type */
1079 2, /* size (0 = byte, 1 = short, 2 = long) */
1081 false, /* pc_relative */
1083 complain_overflow_dont
, /* complain_on_overflow */
1084 bfd_elf_generic_reloc
, /* special_function */
1085 "R_MIPS_HIGHEST", /* name */
1086 true, /* partial_inplace */
1088 0xffff, /* dst_mask */
1089 false), /* pcrel_offset */
1091 /* High 16 bits of displacement in global offset table. */
1092 /* FIXME: Not handled correctly. */
1093 HOWTO (R_MIPS_CALL_HI16
, /* type */
1095 2, /* size (0 = byte, 1 = short, 2 = long) */
1097 false, /* pc_relative */
1099 complain_overflow_dont
, /* complain_on_overflow */
1100 bfd_elf_generic_reloc
, /* special_function */
1101 "R_MIPS_CALL_HI16", /* name */
1102 true, /* partial_inplace */
1104 0x0000ffff, /* dst_mask */
1105 false), /* pcrel_offset */
1107 /* Low 16 bits of displacement in global offset table. */
1108 /* FIXME: Not handled correctly. */
1109 HOWTO (R_MIPS_CALL_LO16
, /* type */
1111 2, /* size (0 = byte, 1 = short, 2 = long) */
1113 false, /* pc_relative */
1115 complain_overflow_dont
, /* complain_on_overflow */
1116 bfd_elf_generic_reloc
, /* special_function */
1117 "R_MIPS_CALL_LO16", /* name */
1118 true, /* partial_inplace */
1120 0x0000ffff, /* dst_mask */
1121 false), /* pcrel_offset */
1123 /* I'm not sure what the remaining relocs are, but they are defined
1126 HOWTO (R_MIPS_SCN_DISP
, /* type */
1128 0, /* size (0 = byte, 1 = short, 2 = long) */
1130 false, /* pc_relative */
1132 complain_overflow_dont
, /* complain_on_overflow */
1133 bfd_elf_generic_reloc
, /* special_function */
1134 "R_MIPS_SCN_DISP", /* name */
1135 false, /* partial_inplace */
1138 false), /* pcrel_offset */
1140 HOWTO (R_MIPS_REL16
, /* type */
1142 0, /* size (0 = byte, 1 = short, 2 = long) */
1144 false, /* pc_relative */
1146 complain_overflow_dont
, /* complain_on_overflow */
1147 bfd_elf_generic_reloc
, /* special_function */
1148 "R_MIPS_REL16", /* name */
1149 false, /* partial_inplace */
1152 false), /* pcrel_offset */
1154 HOWTO (R_MIPS_ADD_IMMEDIATE
, /* type */
1156 0, /* size (0 = byte, 1 = short, 2 = long) */
1158 false, /* pc_relative */
1160 complain_overflow_dont
, /* complain_on_overflow */
1161 bfd_elf_generic_reloc
, /* special_function */
1162 "R_MIPS_ADD_IMMEDIATE", /* name */
1163 false, /* partial_inplace */
1166 false), /* pcrel_offset */
1168 HOWTO (R_MIPS_PJUMP
, /* type */
1170 0, /* size (0 = byte, 1 = short, 2 = long) */
1172 false, /* pc_relative */
1174 complain_overflow_dont
, /* complain_on_overflow */
1175 bfd_elf_generic_reloc
, /* special_function */
1176 "R_MIPS_PJUMP", /* name */
1177 false, /* partial_inplace */
1180 false), /* pcrel_offset */
1182 HOWTO (R_MIPS_RELGOT
, /* type */
1184 0, /* size (0 = byte, 1 = short, 2 = long) */
1186 false, /* pc_relative */
1188 complain_overflow_dont
, /* complain_on_overflow */
1189 bfd_elf_generic_reloc
, /* special_function */
1190 "R_MIPS_RELGOT", /* name */
1191 false, /* partial_inplace */
1194 false) /* pcrel_offset */
1197 /* Swap in a MIPS 64-bit Rel reloc. */
1200 mips_elf64_swap_reloc_in (abfd
, src
, dst
)
1202 const Elf64_Mips_External_Rel
*src
;
1203 Elf64_Mips_Internal_Rel
*dst
;
1205 dst
->r_offset
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_offset
);
1206 dst
->r_sym
= bfd_h_get_32 (abfd
, (bfd_byte
*) src
->r_sym
);
1207 dst
->r_ssym
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_ssym
);
1208 dst
->r_type3
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type3
);
1209 dst
->r_type2
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type2
);
1210 dst
->r_type
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type
);
1213 /* Swap in a MIPS 64-bit Rela reloc. */
1216 mips_elf64_swap_reloca_in (abfd
, src
, dst
)
1218 const Elf64_Mips_External_Rela
*src
;
1219 Elf64_Mips_Internal_Rela
*dst
;
1221 dst
->r_offset
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_offset
);
1222 dst
->r_sym
= bfd_h_get_32 (abfd
, (bfd_byte
*) src
->r_sym
);
1223 dst
->r_ssym
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_ssym
);
1224 dst
->r_type3
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type3
);
1225 dst
->r_type2
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type2
);
1226 dst
->r_type
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type
);
1227 dst
->r_addend
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_addend
);
1232 /* This is not currently used. */
1234 /* Swap out a MIPS 64-bit Rel reloc. */
1237 mips_elf64_swap_reloc_out (abfd
, src
, dst
)
1239 const Elf64_Mips_Internal_Rel
*src
;
1240 Elf64_Mips_External_Rel
*dst
;
1242 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1243 bfd_h_put_32 (abfd
, src
->r_sym
, (bfd_byte
*) dst
->r_sym
);
1244 bfd_h_put_8 (abfd
, src
->r_ssym
, (bfd_byte
*) dst
->r_ssym
);
1245 bfd_h_put_8 (abfd
, src
->r_type3
, (bfd_byte
*) dst
->r_type3
);
1246 bfd_h_put_8 (abfd
, src
->r_type2
, (bfd_byte
*) dst
->r_type2
);
1247 bfd_h_put_8 (abfd
, src
->r_type
, (bfd_byte
*) dst
->r_type
);
1252 /* Swap out a MIPS 64-bit Rela reloc. */
1255 mips_elf64_swap_reloca_out (abfd
, src
, dst
)
1257 const Elf64_Mips_Internal_Rela
*src
;
1258 Elf64_Mips_External_Rela
*dst
;
1260 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1261 bfd_h_put_32 (abfd
, src
->r_sym
, (bfd_byte
*) dst
->r_sym
);
1262 bfd_h_put_8 (abfd
, src
->r_ssym
, (bfd_byte
*) dst
->r_ssym
);
1263 bfd_h_put_8 (abfd
, src
->r_type3
, (bfd_byte
*) dst
->r_type3
);
1264 bfd_h_put_8 (abfd
, src
->r_type2
, (bfd_byte
*) dst
->r_type2
);
1265 bfd_h_put_8 (abfd
, src
->r_type
, (bfd_byte
*) dst
->r_type
);
1266 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1269 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1271 struct elf_reloc_map
1273 bfd_reloc_code_real_type bfd_reloc_val
;
1274 enum mips_elf64_reloc_type elf_reloc_val
;
1277 static CONST
struct elf_reloc_map mips_reloc_map
[] =
1279 { BFD_RELOC_NONE
, R_MIPS_NONE
, },
1280 { BFD_RELOC_16
, R_MIPS_16
},
1281 { BFD_RELOC_32
, R_MIPS_32
},
1282 { BFD_RELOC_64
, R_MIPS_64
},
1283 { BFD_RELOC_CTOR
, R_MIPS_64
},
1284 { BFD_RELOC_32_PCREL
, R_MIPS_REL32
},
1285 { BFD_RELOC_MIPS_JMP
, R_MIPS_26
},
1286 { BFD_RELOC_HI16_S
, R_MIPS_HI16
},
1287 { BFD_RELOC_LO16
, R_MIPS_LO16
},
1288 { BFD_RELOC_MIPS_GPREL
, R_MIPS_GPREL16
},
1289 { BFD_RELOC_MIPS_LITERAL
, R_MIPS_LITERAL
},
1290 { BFD_RELOC_MIPS_GOT16
, R_MIPS_GOT16
},
1291 { BFD_RELOC_16_PCREL
, R_MIPS_PC16
},
1292 { BFD_RELOC_MIPS_CALL16
, R_MIPS_CALL16
},
1293 { BFD_RELOC_MIPS_GPREL32
, R_MIPS_GPREL32
},
1294 { BFD_RELOC_MIPS_GOT_HI16
, R_MIPS_GOT_HI16
},
1295 { BFD_RELOC_MIPS_GOT_LO16
, R_MIPS_GOT_LO16
},
1296 { BFD_RELOC_MIPS_CALL_HI16
, R_MIPS_CALL_HI16
},
1297 { BFD_RELOC_MIPS_CALL_LO16
, R_MIPS_CALL_LO16
}
1300 /* Given a BFD reloc type, return a howto structure. */
1302 static reloc_howto_type
*
1303 mips_elf64_reloc_type_lookup (abfd
, code
)
1305 bfd_reloc_code_real_type code
;
1309 for (i
= 0; i
< sizeof (mips_reloc_map
) / sizeof (struct elf_reloc_map
); i
++)
1311 if (mips_reloc_map
[i
].bfd_reloc_val
== code
)
1315 v
= (int) mips_reloc_map
[i
].elf_reloc_val
;
1316 return &mips_elf64_howto_table_rel
[v
];
1323 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1324 to three relocs, we must tell the user to allocate more space. */
1327 mips_elf64_get_reloc_upper_bound (abfd
, sec
)
1331 return (sec
->reloc_count
* 3 + 1) * sizeof (arelent
*);
1334 /* Read the relocations from one reloc section. */
1337 mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
, rel_hdr
)
1341 const Elf_Internal_Shdr
*rel_hdr
;
1343 PTR allocated
= NULL
;
1344 bfd_byte
*native_relocs
;
1350 reloc_howto_type
*howto_table
;
1352 allocated
= (PTR
) bfd_malloc (rel_hdr
->sh_size
);
1353 if (allocated
== NULL
)
1356 if (bfd_seek (abfd
, rel_hdr
->sh_offset
, SEEK_SET
) != 0
1357 || (bfd_read (allocated
, 1, rel_hdr
->sh_size
, abfd
) != rel_hdr
->sh_size
))
1360 native_relocs
= (bfd_byte
*) allocated
;
1362 relents
= asect
->relocation
+ asect
->reloc_count
;
1364 entsize
= rel_hdr
->sh_entsize
;
1365 BFD_ASSERT (entsize
== sizeof (Elf64_Mips_External_Rel
)
1366 || entsize
== sizeof (Elf64_Mips_External_Rela
));
1368 count
= rel_hdr
->sh_size
/ entsize
;
1370 if (entsize
== sizeof (Elf64_Mips_External_Rel
))
1371 howto_table
= mips_elf64_howto_table_rel
;
1373 howto_table
= mips_elf64_howto_table_rela
;
1376 for (i
= 0; i
< count
; i
++, native_relocs
+= entsize
)
1378 Elf64_Mips_Internal_Rela rela
;
1379 boolean used_sym
, used_ssym
;
1382 if (entsize
== sizeof (Elf64_Mips_External_Rela
))
1383 mips_elf64_swap_reloca_in (abfd
,
1384 (Elf64_Mips_External_Rela
*) native_relocs
,
1388 Elf64_Mips_Internal_Rel rel
;
1390 mips_elf64_swap_reloc_in (abfd
,
1391 (Elf64_Mips_External_Rel
*) native_relocs
,
1393 rela
.r_offset
= rel
.r_offset
;
1394 rela
.r_sym
= rel
.r_sym
;
1395 rela
.r_ssym
= rel
.r_ssym
;
1396 rela
.r_type3
= rel
.r_type3
;
1397 rela
.r_type2
= rel
.r_type2
;
1398 rela
.r_type
= rel
.r_type
;
1402 /* Each entry represents up to three actual relocations. */
1406 for (ir
= 0; ir
< 3; ir
++)
1408 enum mips_elf64_reloc_type type
;
1415 type
= (enum mips_elf64_reloc_type
) rela
.r_type
;
1418 type
= (enum mips_elf64_reloc_type
) rela
.r_type2
;
1421 type
= (enum mips_elf64_reloc_type
) rela
.r_type3
;
1425 if (type
== R_MIPS_NONE
)
1427 /* There are no more relocations in this entry. If this
1428 is the first entry, we need to generate a dummy
1429 relocation so that the generic linker knows that
1430 there has been a break in the sequence of relocations
1431 applying to a particular address. */
1434 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1435 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1436 relent
->address
= rela
.r_offset
;
1438 relent
->address
= rela
.r_offset
- asect
->vma
;
1440 relent
->howto
= &howto_table
[(int) R_MIPS_NONE
];
1446 /* Some types require symbols, whereas some do not. */
1450 case R_MIPS_LITERAL
:
1451 case R_MIPS_INSERT_A
:
1452 case R_MIPS_INSERT_B
:
1454 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1460 if (rela
.r_sym
== 0)
1461 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1466 ps
= symbols
+ rela
.r_sym
- 1;
1468 if ((s
->flags
& BSF_SECTION_SYM
) == 0)
1469 relent
->sym_ptr_ptr
= ps
;
1471 relent
->sym_ptr_ptr
= s
->section
->symbol_ptr_ptr
;
1476 else if (! used_ssym
)
1478 switch (rela
.r_ssym
)
1481 relent
->sym_ptr_ptr
=
1482 bfd_abs_section_ptr
->symbol_ptr_ptr
;
1488 /* FIXME: I think these need to be handled using
1489 special howto structures. */
1501 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1506 /* The address of an ELF reloc is section relative for an
1507 object file, and absolute for an executable file or
1508 shared library. The address of a BFD reloc is always
1509 section relative. */
1510 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1511 relent
->address
= rela
.r_offset
;
1513 relent
->address
= rela
.r_offset
- asect
->vma
;
1515 relent
->addend
= rela
.r_addend
;
1517 relent
->howto
= &howto_table
[(int) type
];
1523 asect
->reloc_count
+= relent
- relents
;
1525 if (allocated
!= NULL
)
1531 if (allocated
!= NULL
)
1536 /* Read the relocations. On Irix 6, there can be two reloc sections
1537 associated with a single data section. */
1540 mips_elf64_slurp_reloc_table (abfd
, asect
, symbols
)
1545 struct bfd_elf_section_data
* const d
= elf_section_data (asect
);
1547 if (asect
->relocation
!= NULL
1548 || (asect
->flags
& SEC_RELOC
) == 0
1549 || asect
->reloc_count
== 0)
1552 /* Allocate space for 3 arelent structures for each Rel structure. */
1553 asect
->relocation
= ((arelent
*)
1555 asect
->reloc_count
* 3 * sizeof (arelent
)));
1556 if (asect
->relocation
== NULL
)
1559 /* The slurp_one_reloc_table routine increments reloc_count. */
1560 asect
->reloc_count
= 0;
1562 if (! mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
, &d
->rel_hdr
))
1564 if (d
->rel_hdr2
!= NULL
)
1566 if (! mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
,
1574 /* Write out the relocations. */
1577 mips_elf64_write_relocs (abfd
, sec
, data
)
1582 boolean
*failedp
= (boolean
*) data
;
1584 Elf_Internal_Shdr
*rela_hdr
;
1585 Elf64_Mips_External_Rela
*ext_rela
;
1587 asymbol
*last_sym
= 0;
1588 int last_sym_idx
= 0;
1590 /* If we have already failed, don't do anything. */
1594 if ((sec
->flags
& SEC_RELOC
) == 0)
1597 /* The linker backend writes the relocs out itself, and sets the
1598 reloc_count field to zero to inhibit writing them here. Also,
1599 sometimes the SEC_RELOC flag gets set even when there aren't any
1601 if (sec
->reloc_count
== 0)
1604 /* We can combine up to three relocs that refer to the same address
1605 if the latter relocs have no associated symbol. */
1607 for (idx
= 0; idx
< sec
->reloc_count
; idx
++)
1614 addr
= sec
->orelocation
[idx
]->address
;
1615 for (i
= 0; i
< 2; i
++)
1619 if (idx
+ 1 >= sec
->reloc_count
)
1621 r
= sec
->orelocation
[idx
+ 1];
1622 if (r
->address
!= addr
1623 || ! bfd_is_abs_section ((*r
->sym_ptr_ptr
)->section
)
1624 || (*r
->sym_ptr_ptr
)->value
!= 0)
1627 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1633 rela_hdr
= &elf_section_data (sec
)->rel_hdr
;
1635 rela_hdr
->sh_size
= rela_hdr
->sh_entsize
* count
;
1636 rela_hdr
->contents
= (PTR
) bfd_alloc (abfd
, rela_hdr
->sh_size
);
1637 if (rela_hdr
->contents
== NULL
)
1643 ext_rela
= (Elf64_Mips_External_Rela
*) rela_hdr
->contents
;
1644 for (idx
= 0; idx
< sec
->reloc_count
; idx
++, ext_rela
++)
1647 Elf64_Mips_Internal_Rela int_rela
;
1652 ptr
= sec
->orelocation
[idx
];
1654 /* The address of an ELF reloc is section relative for an object
1655 file, and absolute for an executable file or shared library.
1656 The address of a BFD reloc is always section relative. */
1657 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1658 int_rela
.r_offset
= ptr
->address
;
1660 int_rela
.r_offset
= ptr
->address
+ sec
->vma
;
1662 sym
= *ptr
->sym_ptr_ptr
;
1663 if (sym
== last_sym
)
1668 n
= _bfd_elf_symbol_from_bfd_symbol (abfd
, &sym
);
1679 int_rela
.r_addend
= ptr
->addend
;
1681 int_rela
.r_ssym
= RSS_UNDEF
;
1683 if ((*ptr
->sym_ptr_ptr
)->the_bfd
->xvec
!= abfd
->xvec
1684 && ! _bfd_elf_validate_reloc (abfd
, ptr
))
1690 int_rela
.r_type
= ptr
->howto
->type
;
1691 int_rela
.r_type2
= (int) R_MIPS_NONE
;
1692 int_rela
.r_type3
= (int) R_MIPS_NONE
;
1694 for (i
= 0; i
< 2; i
++)
1698 if (idx
+ 1 >= sec
->reloc_count
)
1700 r
= sec
->orelocation
[idx
+ 1];
1701 if (r
->address
!= ptr
->address
1702 || ! bfd_is_abs_section ((*r
->sym_ptr_ptr
)->section
)
1703 || (*r
->sym_ptr_ptr
)->value
!= 0)
1706 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1709 int_rela
.r_type2
= r
->howto
->type
;
1711 int_rela
.r_type3
= r
->howto
->type
;
1716 mips_elf64_swap_reloca_out (abfd
, &int_rela
, ext_rela
);
1719 BFD_ASSERT (ext_rela
- (Elf64_Mips_External_Rela
*) rela_hdr
->contents
1723 /* The .MIPS.options section holds register information in an
1724 Elf64_Reginfo structure. These routines swap them in and out.
1725 They are globally visible because they are used outside of BFD. */
1728 bfd_mips_elf64_swap_reginfo_in (abfd
, ex
, in
)
1730 const Elf64_External_RegInfo
*ex
;
1731 Elf64_Internal_RegInfo
*in
;
1733 in
->ri_gprmask
= bfd_h_get_32 (abfd
, (bfd_byte
*) ex
->ri_gprmask
);
1734 in
->ri_pad
= bfd_h_get_32 (abfd
, (bfd_byte
*) ex
->ri_pad
);
1735 in
->ri_cprmask
[0] = bfd_h_get_32 (abfd
, (bfd_byte
*) ex
->ri_cprmask
[0]);
1736 in
->ri_cprmask
[1] = bfd_h_get_32 (abfd
, (bfd_byte
*) ex
->ri_cprmask
[1]);
1737 in
->ri_cprmask
[2] = bfd_h_get_32 (abfd
, (bfd_byte
*) ex
->ri_cprmask
[2]);
1738 in
->ri_cprmask
[3] = bfd_h_get_32 (abfd
, (bfd_byte
*) ex
->ri_cprmask
[3]);
1739 in
->ri_gp_value
= bfd_h_get_64 (abfd
, (bfd_byte
*) ex
->ri_gp_value
);
1743 bfd_mips_elf64_swap_reginfo_out (abfd
, in
, ex
)
1745 const Elf64_Internal_RegInfo
*in
;
1746 Elf64_External_RegInfo
*ex
;
1748 bfd_h_put_32 (abfd
, (bfd_vma
) in
->ri_gprmask
,
1749 (bfd_byte
*) ex
->ri_gprmask
);
1750 bfd_h_put_32 (abfd
, (bfd_vma
) in
->ri_pad
,
1751 (bfd_byte
*) ex
->ri_pad
);
1752 bfd_h_put_32 (abfd
, (bfd_vma
) in
->ri_cprmask
[0],
1753 (bfd_byte
*) ex
->ri_cprmask
[0]);
1754 bfd_h_put_32 (abfd
, (bfd_vma
) in
->ri_cprmask
[1],
1755 (bfd_byte
*) ex
->ri_cprmask
[1]);
1756 bfd_h_put_32 (abfd
, (bfd_vma
) in
->ri_cprmask
[2],
1757 (bfd_byte
*) ex
->ri_cprmask
[2]);
1758 bfd_h_put_32 (abfd
, (bfd_vma
) in
->ri_cprmask
[3],
1759 (bfd_byte
*) ex
->ri_cprmask
[3]);
1760 bfd_h_put_64 (abfd
, (bfd_vma
) in
->ri_gp_value
,
1761 (bfd_byte
*) ex
->ri_gp_value
);
1764 /* Handle a 64-bit MIPS ELF specific section. */
1767 mips_elf64_section_from_shdr (abfd
, hdr
, name
)
1769 Elf_Internal_Shdr
*hdr
;
1772 if (! _bfd_mips_elf_section_from_shdr (abfd
, hdr
, name
))
1775 /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
1776 set the gp value based on what we find. We may see both
1777 SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
1778 they should agree. */
1779 if (hdr
->sh_type
== SHT_MIPS_OPTIONS
)
1781 bfd_byte
*contents
, *l
, *lend
;
1783 contents
= (bfd_byte
*) bfd_malloc (hdr
->sh_size
);
1784 if (contents
== NULL
)
1786 if (! bfd_get_section_contents (abfd
, hdr
->bfd_section
, contents
,
1787 (file_ptr
) 0, hdr
->sh_size
))
1793 lend
= contents
+ hdr
->sh_size
;
1794 while (l
+ sizeof (Elf_External_Options
) <= lend
)
1796 Elf_Internal_Options intopt
;
1798 bfd_mips_elf_swap_options_in (abfd
, (Elf_External_Options
*) l
,
1800 if (intopt
.kind
== ODK_REGINFO
)
1802 Elf64_Internal_RegInfo intreg
;
1804 bfd_mips_elf64_swap_reginfo_in
1806 ((Elf64_External_RegInfo
*)
1807 (l
+ sizeof (Elf_External_Options
))),
1809 elf_gp (abfd
) = intreg
.ri_gp_value
;
1819 /* Work over a section just before writing it out. We update the GP
1820 value in the SHT_MIPS_OPTIONS section based on the value we are
1824 mips_elf64_section_processing (abfd
, hdr
)
1826 Elf_Internal_Shdr
*hdr
;
1828 if (hdr
->sh_type
== SHT_MIPS_OPTIONS
1829 && hdr
->bfd_section
!= NULL
1830 && elf_section_data (hdr
->bfd_section
) != NULL
1831 && elf_section_data (hdr
->bfd_section
)->tdata
!= NULL
)
1833 bfd_byte
*contents
, *l
, *lend
;
1835 /* We stored the section contents in the elf_section_data tdata
1836 field in the set_section_contents routine. We save the
1837 section contents so that we don't have to read them again.
1838 At this point we know that elf_gp is set, so we can look
1839 through the section contents to see if there is an
1840 ODK_REGINFO structure. */
1842 contents
= (bfd_byte
*) elf_section_data (hdr
->bfd_section
)->tdata
;
1844 lend
= contents
+ hdr
->sh_size
;
1845 while (l
+ sizeof (Elf_External_Options
) <= lend
)
1847 Elf_Internal_Options intopt
;
1849 bfd_mips_elf_swap_options_in (abfd
, (Elf_External_Options
*) l
,
1851 if (intopt
.kind
== ODK_REGINFO
)
1858 + sizeof (Elf_External_Options
)
1859 + (sizeof (Elf64_External_RegInfo
) - 8)),
1862 bfd_h_put_64 (abfd
, elf_gp (abfd
), buf
);
1863 if (bfd_write (buf
, 1, 8, abfd
) != 8)
1870 return _bfd_mips_elf_section_processing (abfd
, hdr
);
1873 /* ECOFF swapping routines. These are used when dealing with the
1874 .mdebug section, which is in the ECOFF debugging format. */
1875 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap
=
1877 /* Symbol table magic number. */
1879 /* Alignment of debugging information. E.g., 4. */
1881 /* Sizes of external symbolic information. */
1882 sizeof (struct hdr_ext
),
1883 sizeof (struct dnr_ext
),
1884 sizeof (struct pdr_ext
),
1885 sizeof (struct sym_ext
),
1886 sizeof (struct opt_ext
),
1887 sizeof (struct fdr_ext
),
1888 sizeof (struct rfd_ext
),
1889 sizeof (struct ext_ext
),
1890 /* Functions to swap in external symbolic data. */
1899 _bfd_ecoff_swap_tir_in
,
1900 _bfd_ecoff_swap_rndx_in
,
1901 /* Functions to swap out external symbolic data. */
1910 _bfd_ecoff_swap_tir_out
,
1911 _bfd_ecoff_swap_rndx_out
,
1912 /* Function to read in symbolic data. */
1913 _bfd_mips_elf_read_ecoff_info
1916 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
1917 standard ELF. This structure is used to redirect the relocation
1918 handling routines. */
1920 const struct elf_size_info mips_elf64_size_info
=
1922 sizeof (Elf64_External_Ehdr
),
1923 sizeof (Elf64_External_Phdr
),
1924 sizeof (Elf64_External_Shdr
),
1925 sizeof (Elf64_Mips_External_Rel
),
1926 sizeof (Elf64_Mips_External_Rela
),
1927 sizeof (Elf64_External_Sym
),
1928 sizeof (Elf64_External_Dyn
),
1929 sizeof (Elf_External_Note
),
1934 bfd_elf64_write_out_phdrs
,
1935 bfd_elf64_write_shdrs_and_ehdr
,
1936 mips_elf64_write_relocs
,
1937 bfd_elf64_swap_symbol_out
,
1938 mips_elf64_slurp_reloc_table
,
1939 bfd_elf64_slurp_symbol_table
,
1940 bfd_elf64_swap_dyn_in
1943 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
1944 #define TARGET_LITTLE_NAME "elf64-littlemips"
1945 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
1946 #define TARGET_BIG_NAME "elf64-bigmips"
1947 #define ELF_ARCH bfd_arch_mips
1948 #define ELF_MACHINE_CODE EM_MIPS
1949 #define ELF_MAXPAGESIZE 0x1000
1950 #define elf_backend_size_info mips_elf64_size_info
1951 #define elf_backend_object_p _bfd_mips_elf_object_p
1952 #define elf_backend_section_from_shdr mips_elf64_section_from_shdr
1953 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
1954 #define elf_backend_section_from_bfd_section \
1955 _bfd_mips_elf_section_from_bfd_section
1956 #define elf_backend_section_processing mips_elf64_section_processing
1957 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
1958 #define elf_backend_final_write_processing \
1959 _bfd_mips_elf_final_write_processing
1960 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
1962 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
1963 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
1964 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
1965 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
1966 #define bfd_elf64_bfd_copy_private_bfd_data \
1967 _bfd_mips_elf_copy_private_bfd_data
1968 #define bfd_elf64_bfd_merge_private_bfd_data \
1969 _bfd_mips_elf_merge_private_bfd_data
1970 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
1972 #include "elf64-target.h"