1 /* MIPS-specific support for 64-bit ELF
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4 Ian Lance Taylor, Cygnus Support
5 Linker support added by Mark Mitchell, CodeSourcery, LLC.
6 <mark@codesourcery.com>
8 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
24 /* This file supports the 64-bit MIPS ELF ABI.
26 The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
27 overrides the usual ELF reloc handling, and handles reading and
28 writing the relocations here. */
39 /* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
40 use ECOFF. However, we support it anyhow for an easier changeover. */
42 #include "coff/symconst.h"
43 #include "coff/internal.h"
44 #include "coff/ecoff.h"
45 /* The 64 bit versions of the mdebug data structures are in alpha.h. */
46 #include "coff/alpha.h"
47 #define ECOFF_SIGNED_64
48 #include "ecoffswap.h"
50 static void mips_elf64_swap_reloc_in
51 PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
52 Elf64_Mips_Internal_Rel *));
53 static void mips_elf64_swap_reloca_in
54 PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
55 Elf64_Mips_Internal_Rela *));
56 static void mips_elf64_swap_reloc_out
57 PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
58 Elf64_Mips_External_Rel *));
59 static void mips_elf64_swap_reloca_out
60 PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
61 Elf64_Mips_External_Rela *));
62 static void mips_elf64_be_swap_reloc_in
63 PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rel *));
64 static void mips_elf64_be_swap_reloc_out
65 PARAMS ((bfd *, const Elf_Internal_Rel *, bfd_byte *));
66 static void mips_elf64_be_swap_reloca_in
67 PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
68 static void mips_elf64_be_swap_reloca_out
69 PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
70 static reloc_howto_type *mips_elf64_reloc_type_lookup
71 PARAMS ((bfd *, bfd_reloc_code_real_type));
72 static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
73 static boolean mips_elf64_slurp_one_reloc_table
74 PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
75 static boolean mips_elf64_slurp_reloc_table
76 PARAMS ((bfd *, asection *, asymbol **, boolean));
77 static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
79 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
80 from smaller values. Start with zero, widen, *then* decrement. */
81 #define MINUS_ONE (((bfd_vma)0) - 1)
83 /* The number of local .got entries we reserve. */
84 #define MIPS_RESERVED_GOTNO (2)
86 /* The relocation table used for SHT_REL sections. */
88 #define UNUSED_RELOC(num) { num, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
90 static reloc_howto_type mips_elf64_howto_table_rel[] =
93 HOWTO (R_MIPS_NONE, /* type */
95 0, /* size (0 = byte, 1 = short, 2 = long) */
97 false, /* pc_relative */
99 complain_overflow_dont, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_MIPS_NONE", /* name */
102 false, /* partial_inplace */
105 false), /* pcrel_offset */
107 /* 16 bit relocation. */
108 HOWTO (R_MIPS_16, /* type */
110 1, /* size (0 = byte, 1 = short, 2 = long) */
112 false, /* pc_relative */
114 complain_overflow_bitfield, /* complain_on_overflow */
115 bfd_elf_generic_reloc, /* special_function */
116 "R_MIPS_16", /* name */
117 true, /* partial_inplace */
118 0xffff, /* src_mask */
119 0xffff, /* dst_mask */
120 false), /* pcrel_offset */
122 /* 32 bit relocation. */
123 HOWTO (R_MIPS_32, /* type */
125 2, /* size (0 = byte, 1 = short, 2 = long) */
127 false, /* pc_relative */
129 complain_overflow_dont, /* complain_on_overflow */
130 bfd_elf_generic_reloc, /* special_function */
131 "R_MIPS_32", /* name */
132 true, /* partial_inplace */
133 0xffffffff, /* src_mask */
134 0xffffffff, /* dst_mask */
135 false), /* pcrel_offset */
137 /* 32 bit symbol relative relocation. */
138 HOWTO (R_MIPS_REL32, /* type */
140 2, /* size (0 = byte, 1 = short, 2 = long) */
142 false, /* pc_relative */
144 complain_overflow_dont, /* complain_on_overflow */
145 bfd_elf_generic_reloc, /* special_function */
146 "R_MIPS_REL32", /* name */
147 true, /* partial_inplace */
148 0xffffffff, /* src_mask */
149 0xffffffff, /* dst_mask */
150 false), /* pcrel_offset */
152 /* 26 bit jump address. */
153 HOWTO (R_MIPS_26, /* type */
155 2, /* size (0 = byte, 1 = short, 2 = long) */
157 false, /* pc_relative */
159 complain_overflow_dont, /* complain_on_overflow */
160 /* This needs complex overflow
161 detection, because the upper 36
162 bits must match the PC + 4. */
163 bfd_elf_generic_reloc, /* special_function */
164 "R_MIPS_26", /* name */
165 true, /* partial_inplace */
166 0x3ffffff, /* src_mask */
167 0x3ffffff, /* dst_mask */
168 false), /* pcrel_offset */
170 /* High 16 bits of symbol value. */
171 HOWTO (R_MIPS_HI16, /* type */
173 2, /* size (0 = byte, 1 = short, 2 = long) */
175 false, /* pc_relative */
177 complain_overflow_dont, /* complain_on_overflow */
178 _bfd_mips_elf_hi16_reloc, /* special_function */
179 "R_MIPS_HI16", /* name */
180 true, /* partial_inplace */
181 0xffff, /* src_mask */
182 0xffff, /* dst_mask */
183 false), /* pcrel_offset */
185 /* Low 16 bits of symbol value. */
186 HOWTO (R_MIPS_LO16, /* type */
188 2, /* size (0 = byte, 1 = short, 2 = long) */
190 false, /* pc_relative */
192 complain_overflow_dont, /* complain_on_overflow */
193 _bfd_mips_elf_lo16_reloc, /* special_function */
194 "R_MIPS_LO16", /* name */
195 true, /* partial_inplace */
196 0xffff, /* src_mask */
197 0xffff, /* dst_mask */
198 false), /* pcrel_offset */
200 /* GP relative reference. */
201 HOWTO (R_MIPS_GPREL16, /* type */
203 2, /* size (0 = byte, 1 = short, 2 = long) */
205 false, /* pc_relative */
207 complain_overflow_signed, /* complain_on_overflow */
208 _bfd_mips_elf_gprel16_reloc, /* special_function */
209 "R_MIPS_GPREL16", /* name */
210 true, /* partial_inplace */
211 0xffff, /* src_mask */
212 0xffff, /* dst_mask */
213 false), /* pcrel_offset */
215 /* Reference to literal section. */
216 HOWTO (R_MIPS_LITERAL, /* type */
218 2, /* size (0 = byte, 1 = short, 2 = long) */
220 false, /* pc_relative */
222 complain_overflow_signed, /* complain_on_overflow */
223 _bfd_mips_elf_gprel16_reloc, /* special_function */
224 "R_MIPS_LITERAL", /* name */
225 true, /* partial_inplace */
226 0xffff, /* src_mask */
227 0xffff, /* dst_mask */
228 false), /* pcrel_offset */
230 /* Reference to global offset table. */
231 HOWTO (R_MIPS_GOT16, /* type */
233 2, /* size (0 = byte, 1 = short, 2 = long) */
235 false, /* pc_relative */
237 complain_overflow_signed, /* complain_on_overflow */
238 _bfd_mips_elf_got16_reloc, /* special_function */
239 "R_MIPS_GOT16", /* name */
240 false, /* partial_inplace */
242 0xffff, /* dst_mask */
243 false), /* pcrel_offset */
245 /* 16 bit PC relative reference. */
246 HOWTO (R_MIPS_PC16, /* type */
248 2, /* size (0 = byte, 1 = short, 2 = long) */
250 true, /* pc_relative */
252 complain_overflow_signed, /* complain_on_overflow */
253 bfd_elf_generic_reloc, /* special_function */
254 "R_MIPS_PC16", /* name */
255 true, /* partial_inplace */
256 0xffff, /* src_mask */
257 0xffff, /* dst_mask */
258 false), /* pcrel_offset */
260 /* 16 bit call through global offset table. */
261 /* FIXME: This is not handled correctly. */
262 HOWTO (R_MIPS_CALL16, /* type */
264 2, /* size (0 = byte, 1 = short, 2 = long) */
266 false, /* pc_relative */
268 complain_overflow_signed, /* complain_on_overflow */
269 bfd_elf_generic_reloc, /* special_function */
270 "R_MIPS_CALL16", /* name */
271 false, /* partial_inplace */
273 0xffff, /* dst_mask */
274 false), /* pcrel_offset */
276 /* 32 bit GP relative reference. */
277 HOWTO (R_MIPS_GPREL32, /* type */
279 2, /* size (0 = byte, 1 = short, 2 = long) */
281 false, /* pc_relative */
283 complain_overflow_bitfield, /* complain_on_overflow */
284 _bfd_mips_elf_gprel32_reloc, /* special_function */
285 "R_MIPS_GPREL32", /* name */
286 true, /* partial_inplace */
287 0xffffffff, /* src_mask */
288 0xffffffff, /* dst_mask */
289 false), /* pcrel_offset */
295 /* A 5 bit shift field. */
296 HOWTO (R_MIPS_SHIFT5, /* type */
298 2, /* size (0 = byte, 1 = short, 2 = long) */
300 false, /* pc_relative */
302 complain_overflow_bitfield, /* complain_on_overflow */
303 bfd_elf_generic_reloc, /* special_function */
304 "R_MIPS_SHIFT5", /* name */
305 true, /* partial_inplace */
306 0x000007c0, /* src_mask */
307 0x000007c0, /* dst_mask */
308 false), /* pcrel_offset */
310 /* A 6 bit shift field. */
311 /* FIXME: This is not handled correctly; a special function is
312 needed to put the most significant bit in the right place. */
313 HOWTO (R_MIPS_SHIFT6, /* type */
315 2, /* size (0 = byte, 1 = short, 2 = long) */
317 false, /* pc_relative */
319 complain_overflow_bitfield, /* complain_on_overflow */
320 bfd_elf_generic_reloc, /* special_function */
321 "R_MIPS_SHIFT6", /* name */
322 true, /* partial_inplace */
323 0x000007c4, /* src_mask */
324 0x000007c4, /* dst_mask */
325 false), /* pcrel_offset */
327 /* 64 bit relocation. */
328 HOWTO (R_MIPS_64, /* type */
330 4, /* size (0 = byte, 1 = short, 2 = long) */
332 false, /* pc_relative */
334 complain_overflow_dont, /* complain_on_overflow */
335 bfd_elf_generic_reloc, /* special_function */
336 "R_MIPS_64", /* name */
337 true, /* partial_inplace */
338 MINUS_ONE, /* src_mask */
339 MINUS_ONE, /* dst_mask */
340 false), /* pcrel_offset */
342 /* Displacement in the global offset table. */
343 /* FIXME: Not handled correctly. */
344 HOWTO (R_MIPS_GOT_DISP, /* type */
346 2, /* size (0 = byte, 1 = short, 2 = long) */
348 false, /* pc_relative */
350 complain_overflow_signed, /* complain_on_overflow */
351 bfd_elf_generic_reloc, /* special_function */
352 "R_MIPS_GOT_DISP", /* name */
353 false, /* partial_inplace */
354 0x0000ffff, /* src_mask */
355 0x0000ffff, /* dst_mask */
356 false), /* pcrel_offset */
358 /* Displacement to page pointer in the global offset table. */
359 /* FIXME: Not handled correctly. */
360 HOWTO (R_MIPS_GOT_PAGE, /* type */
362 2, /* size (0 = byte, 1 = short, 2 = long) */
364 false, /* pc_relative */
366 complain_overflow_signed, /* complain_on_overflow */
367 bfd_elf_generic_reloc, /* special_function */
368 "R_MIPS_GOT_PAGE", /* name */
369 false, /* partial_inplace */
370 0x0000ffff, /* src_mask */
371 0x0000ffff, /* dst_mask */
372 false), /* pcrel_offset */
374 /* Offset from page pointer in the global offset table. */
375 /* FIXME: Not handled correctly. */
376 HOWTO (R_MIPS_GOT_OFST, /* type */
378 2, /* size (0 = byte, 1 = short, 2 = long) */
380 false, /* pc_relative */
382 complain_overflow_signed, /* complain_on_overflow */
383 bfd_elf_generic_reloc, /* special_function */
384 "R_MIPS_GOT_OFST", /* name */
385 false, /* partial_inplace */
386 0x0000ffff, /* src_mask */
387 0x0000ffff, /* dst_mask */
388 false), /* pcrel_offset */
390 /* High 16 bits of displacement in global offset table. */
391 /* FIXME: Not handled correctly. */
392 HOWTO (R_MIPS_GOT_HI16, /* type */
394 2, /* size (0 = byte, 1 = short, 2 = long) */
396 false, /* pc_relative */
398 complain_overflow_dont, /* complain_on_overflow */
399 bfd_elf_generic_reloc, /* special_function */
400 "R_MIPS_GOT_HI16", /* name */
401 false, /* partial_inplace */
402 0x0000ffff, /* src_mask */
403 0x0000ffff, /* dst_mask */
404 false), /* pcrel_offset */
406 /* Low 16 bits of displacement in global offset table. */
407 /* FIXME: Not handled correctly. */
408 HOWTO (R_MIPS_GOT_LO16, /* type */
410 2, /* size (0 = byte, 1 = short, 2 = long) */
412 false, /* pc_relative */
414 complain_overflow_dont, /* complain_on_overflow */
415 bfd_elf_generic_reloc, /* special_function */
416 "R_MIPS_GOT_LO16", /* name */
417 false, /* partial_inplace */
418 0x0000ffff, /* src_mask */
419 0x0000ffff, /* dst_mask */
420 false), /* pcrel_offset */
422 /* 64 bit substraction. */
423 /* FIXME: Not handled correctly. */
424 HOWTO (R_MIPS_SUB, /* type */
426 4, /* size (0 = byte, 1 = short, 2 = long) */
428 false, /* pc_relative */
430 complain_overflow_dont, /* complain_on_overflow */
431 bfd_elf_generic_reloc, /* special_function */
432 "R_MIPS_SUB", /* name */
433 true, /* partial_inplace */
434 MINUS_ONE, /* src_mask */
435 MINUS_ONE, /* dst_mask */
436 false), /* pcrel_offset */
438 /* Insert the addend as an instruction. */
439 /* FIXME: Not handled correctly. */
440 HOWTO (R_MIPS_INSERT_A, /* type */
442 2, /* size (0 = byte, 1 = short, 2 = long) */
444 false, /* pc_relative */
446 complain_overflow_dont, /* complain_on_overflow */
447 bfd_elf_generic_reloc, /* special_function */
448 "R_MIPS_INSERT_A", /* name */
449 true, /* partial_inplace */
450 0xffffffff, /* src_mask */
451 0xffffffff, /* dst_mask */
452 false), /* pcrel_offset */
454 /* Insert the addend as an instruction, and change all relocations
455 to refer to the old instruction at the address. */
456 /* FIXME: Not handled correctly. */
457 HOWTO (R_MIPS_INSERT_B, /* type */
459 2, /* size (0 = byte, 1 = short, 2 = long) */
461 false, /* pc_relative */
463 complain_overflow_dont, /* complain_on_overflow */
464 bfd_elf_generic_reloc, /* special_function */
465 "R_MIPS_INSERT_B", /* name */
466 true, /* partial_inplace */
467 0xffffffff, /* src_mask */
468 0xffffffff, /* dst_mask */
469 false), /* pcrel_offset */
471 /* Delete a 32 bit instruction. */
472 /* FIXME: Not handled correctly. */
473 HOWTO (R_MIPS_DELETE, /* type */
475 2, /* size (0 = byte, 1 = short, 2 = long) */
477 false, /* pc_relative */
479 complain_overflow_dont, /* complain_on_overflow */
480 bfd_elf_generic_reloc, /* special_function */
481 "R_MIPS_DELETE", /* name */
482 true, /* partial_inplace */
483 0xffffffff, /* src_mask */
484 0xffffffff, /* dst_mask */
485 false), /* pcrel_offset */
487 /* Get the higher value of a 64 bit addend. */
488 HOWTO (R_MIPS_HIGHER, /* type */
490 2, /* size (0 = byte, 1 = short, 2 = long) */
492 false, /* pc_relative */
494 complain_overflow_dont, /* complain_on_overflow */
495 bfd_elf_generic_reloc, /* special_function */
496 "R_MIPS_HIGHER", /* name */
497 true, /* partial_inplace */
498 0xffff, /* src_mask */
499 0xffff, /* dst_mask */
500 false), /* pcrel_offset */
502 /* Get the highest value of a 64 bit addend. */
503 /* FIXME: Not handled correctly. */
504 HOWTO (R_MIPS_HIGHEST, /* type */
506 2, /* size (0 = byte, 1 = short, 2 = long) */
508 false, /* pc_relative */
510 complain_overflow_dont, /* complain_on_overflow */
511 bfd_elf_generic_reloc, /* special_function */
512 "R_MIPS_HIGHEST", /* name */
513 true, /* partial_inplace */
514 0xffff, /* src_mask */
515 0xffff, /* dst_mask */
516 false), /* pcrel_offset */
518 /* High 16 bits of displacement in global offset table. */
519 /* FIXME: Not handled correctly. */
520 HOWTO (R_MIPS_CALL_HI16, /* type */
522 2, /* size (0 = byte, 1 = short, 2 = long) */
524 false, /* pc_relative */
526 complain_overflow_dont, /* complain_on_overflow */
527 bfd_elf_generic_reloc, /* special_function */
528 "R_MIPS_CALL_HI16", /* name */
529 true, /* partial_inplace */
530 0xffff, /* src_mask */
531 0xffff, /* dst_mask */
532 false), /* pcrel_offset */
534 /* Low 16 bits of displacement in global offset table. */
535 /* FIXME: Not handled correctly. */
536 HOWTO (R_MIPS_CALL_LO16, /* type */
538 2, /* size (0 = byte, 1 = short, 2 = long) */
540 false, /* pc_relative */
542 complain_overflow_dont, /* complain_on_overflow */
543 bfd_elf_generic_reloc, /* special_function */
544 "R_MIPS_CALL_LO16", /* name */
545 true, /* partial_inplace */
546 0xffff, /* src_mask */
547 0xffff, /* dst_mask */
548 false), /* pcrel_offset */
550 /* I'm not sure what the remaining relocs are, but they are defined
553 HOWTO (R_MIPS_SCN_DISP, /* type */
555 2, /* size (0 = byte, 1 = short, 2 = long) */
557 false, /* pc_relative */
559 complain_overflow_dont, /* complain_on_overflow */
560 bfd_elf_generic_reloc, /* special_function */
561 "R_MIPS_SCN_DISP", /* name */
562 true, /* partial_inplace */
563 0xffffffff, /* src_mask */
564 0xffffffff, /* dst_mask */
565 false), /* pcrel_offset */
567 HOWTO (R_MIPS_REL16, /* type */
569 1, /* size (0 = byte, 1 = short, 2 = long) */
571 false, /* pc_relative */
573 complain_overflow_signed, /* complain_on_overflow */
574 bfd_elf_generic_reloc, /* special_function */
575 "R_MIPS_REL16", /* name */
576 true, /* partial_inplace */
577 0xffff, /* src_mask */
578 0xffff, /* dst_mask */
579 false), /* pcrel_offset */
581 /* These two are obsolete. */
582 EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
583 EMPTY_HOWTO (R_MIPS_PJUMP),
585 HOWTO (R_MIPS_RELGOT, /* type */
587 2, /* size (0 = byte, 1 = short, 2 = long) */
589 false, /* pc_relative */
591 complain_overflow_dont, /* complain_on_overflow */
592 bfd_elf_generic_reloc, /* special_function */
593 "R_MIPS_RELGOT", /* name */
594 true, /* partial_inplace */
595 0xffffffff, /* src_mask */
596 0xffffffff, /* dst_mask */
597 false), /* pcrel_offset */
599 /* Protected jump conversion. This is an optimization hint. No
600 relocation is required for correctness. */
601 HOWTO (R_MIPS_JALR, /* type */
603 2, /* size (0 = byte, 1 = short, 2 = long) */
605 false, /* pc_relative */
607 complain_overflow_dont, /* complain_on_overflow */
608 bfd_elf_generic_reloc, /* special_function */
609 "R_MIPS_JALR", /* name */
610 false, /* partial_inplace */
613 false), /* pcrel_offset */
616 /* The relocation table used for SHT_RELA sections. */
618 static reloc_howto_type mips_elf64_howto_table_rela[] =
621 HOWTO (R_MIPS_NONE, /* type */
623 0, /* size (0 = byte, 1 = short, 2 = long) */
625 false, /* pc_relative */
627 complain_overflow_dont, /* complain_on_overflow */
628 bfd_elf_generic_reloc, /* special_function */
629 "R_MIPS_NONE", /* name */
630 false, /* partial_inplace */
633 false), /* pcrel_offset */
635 /* 16 bit relocation. */
636 HOWTO (R_MIPS_16, /* type */
638 1, /* size (0 = byte, 1 = short, 2 = long) */
640 false, /* pc_relative */
642 complain_overflow_bitfield, /* complain_on_overflow */
643 bfd_elf_generic_reloc, /* special_function */
644 "R_MIPS_16", /* name */
645 false, /* partial_inplace */
647 0xffff, /* dst_mask */
648 false), /* pcrel_offset */
650 /* 32 bit relocation. */
651 HOWTO (R_MIPS_32, /* type */
653 2, /* size (0 = byte, 1 = short, 2 = long) */
655 false, /* pc_relative */
657 complain_overflow_dont, /* complain_on_overflow */
658 bfd_elf_generic_reloc, /* special_function */
659 "R_MIPS_32", /* name */
660 false, /* partial_inplace */
662 0xffffffff, /* dst_mask */
663 false), /* pcrel_offset */
665 /* 32 bit symbol relative relocation. */
666 HOWTO (R_MIPS_REL32, /* type */
668 2, /* size (0 = byte, 1 = short, 2 = long) */
670 false, /* pc_relative */
672 complain_overflow_dont, /* complain_on_overflow */
673 bfd_elf_generic_reloc, /* special_function */
674 "R_MIPS_REL32", /* name */
675 false, /* partial_inplace */
677 0xffffffff, /* dst_mask */
678 false), /* pcrel_offset */
680 /* 26 bit jump address. */
681 HOWTO (R_MIPS_26, /* type */
683 2, /* size (0 = byte, 1 = short, 2 = long) */
685 false, /* pc_relative */
687 complain_overflow_dont, /* complain_on_overflow */
688 /* This needs complex overflow
689 detection, because the upper 36
690 bits must match the PC + 4. */
691 bfd_elf_generic_reloc, /* special_function */
692 "R_MIPS_26", /* name */
693 false, /* partial_inplace */
695 0x3ffffff, /* dst_mask */
696 false), /* pcrel_offset */
698 /* High 16 bits of symbol value. */
699 HOWTO (R_MIPS_HI16, /* type */
701 2, /* size (0 = byte, 1 = short, 2 = long) */
703 false, /* pc_relative */
705 complain_overflow_dont, /* complain_on_overflow */
706 bfd_elf_generic_reloc, /* special_function */
707 "R_MIPS_HI16", /* name */
708 false, /* partial_inplace */
710 0xffff, /* dst_mask */
711 false), /* pcrel_offset */
713 /* Low 16 bits of symbol value. */
714 HOWTO (R_MIPS_LO16, /* type */
716 2, /* size (0 = byte, 1 = short, 2 = long) */
718 false, /* pc_relative */
720 complain_overflow_dont, /* complain_on_overflow */
721 bfd_elf_generic_reloc, /* special_function */
722 "R_MIPS_LO16", /* name */
723 false, /* partial_inplace */
725 0xffff, /* dst_mask */
726 false), /* pcrel_offset */
728 /* GP relative reference. */
729 HOWTO (R_MIPS_GPREL16, /* type */
731 2, /* size (0 = byte, 1 = short, 2 = long) */
733 false, /* pc_relative */
735 complain_overflow_signed, /* complain_on_overflow */
736 _bfd_mips_elf_gprel16_reloc, /* special_function */
737 "R_MIPS_GPREL16", /* name */
738 true, /* partial_inplace */
740 0xffff, /* dst_mask */
741 false), /* pcrel_offset */
743 /* Reference to literal section. */
744 HOWTO (R_MIPS_LITERAL, /* type */
746 2, /* size (0 = byte, 1 = short, 2 = long) */
748 false, /* pc_relative */
750 complain_overflow_signed, /* complain_on_overflow */
751 _bfd_mips_elf_gprel16_reloc, /* special_function */
752 "R_MIPS_LITERAL", /* name */
753 true, /* partial_inplace */
755 0xffff, /* dst_mask */
756 false), /* pcrel_offset */
758 /* Reference to global offset table. */
759 /* FIXME: This is not handled correctly. */
760 HOWTO (R_MIPS_GOT16, /* type */
762 2, /* size (0 = byte, 1 = short, 2 = long) */
764 false, /* pc_relative */
766 complain_overflow_signed, /* complain_on_overflow */
767 bfd_elf_generic_reloc, /* special_function */
768 "R_MIPS_GOT16", /* name */
769 false, /* partial_inplace */
771 0xffff, /* dst_mask */
772 false), /* pcrel_offset */
774 /* 16 bit PC relative reference. */
775 HOWTO (R_MIPS_PC16, /* type */
777 2, /* size (0 = byte, 1 = short, 2 = long) */
779 true, /* pc_relative */
781 complain_overflow_signed, /* complain_on_overflow */
782 bfd_elf_generic_reloc, /* special_function */
783 "R_MIPS_PC16", /* name */
784 false, /* partial_inplace */
786 0xffff, /* dst_mask */
787 false), /* pcrel_offset */
789 /* 16 bit call through global offset table. */
790 /* FIXME: This is not handled correctly. */
791 HOWTO (R_MIPS_CALL16, /* type */
793 2, /* size (0 = byte, 1 = short, 2 = long) */
795 false, /* pc_relative */
797 complain_overflow_signed, /* complain_on_overflow */
798 bfd_elf_generic_reloc, /* special_function */
799 "R_MIPS_CALL16", /* name */
800 false, /* partial_inplace */
802 0xffff, /* dst_mask */
803 false), /* pcrel_offset */
805 /* 32 bit GP relative reference. */
806 HOWTO (R_MIPS_GPREL32, /* type */
808 2, /* size (0 = byte, 1 = short, 2 = long) */
810 false, /* pc_relative */
812 complain_overflow_bitfield, /* complain_on_overflow */
813 _bfd_mips_elf_gprel32_reloc, /* special_function */
814 "R_MIPS_GPREL32", /* name */
815 true, /* partial_inplace */
817 0xffffffff, /* dst_mask */
818 false), /* pcrel_offset */
824 /* A 5 bit shift field. */
825 HOWTO (R_MIPS_SHIFT5, /* type */
827 2, /* size (0 = byte, 1 = short, 2 = long) */
829 false, /* pc_relative */
831 complain_overflow_bitfield, /* complain_on_overflow */
832 bfd_elf_generic_reloc, /* special_function */
833 "R_MIPS_SHIFT5", /* name */
834 false, /* partial_inplace */
836 0x000007c0, /* dst_mask */
837 false), /* pcrel_offset */
839 /* A 6 bit shift field. */
840 /* FIXME: This is not handled correctly; a special function is
841 needed to put the most significant bit in the right place. */
842 HOWTO (R_MIPS_SHIFT6, /* type */
844 2, /* size (0 = byte, 1 = short, 2 = long) */
846 false, /* pc_relative */
848 complain_overflow_bitfield, /* complain_on_overflow */
849 bfd_elf_generic_reloc, /* special_function */
850 "R_MIPS_SHIFT6", /* name */
851 false, /* partial_inplace */
853 0x000007c4, /* dst_mask */
854 false), /* pcrel_offset */
856 /* 64 bit relocation. */
857 HOWTO (R_MIPS_64, /* type */
859 4, /* size (0 = byte, 1 = short, 2 = long) */
861 false, /* pc_relative */
863 complain_overflow_dont, /* complain_on_overflow */
864 bfd_elf_generic_reloc, /* special_function */
865 "R_MIPS_64", /* name */
866 false, /* partial_inplace */
868 MINUS_ONE, /* dst_mask */
869 false), /* pcrel_offset */
871 /* Displacement in the global offset table. */
872 /* FIXME: Not handled correctly. */
873 HOWTO (R_MIPS_GOT_DISP, /* type */
875 2, /* size (0 = byte, 1 = short, 2 = long) */
877 false, /* pc_relative */
879 complain_overflow_signed, /* complain_on_overflow */
880 bfd_elf_generic_reloc, /* special_function */
881 "R_MIPS_GOT_DISP", /* name */
882 false, /* partial_inplace */
884 0x0000ffff, /* dst_mask */
885 false), /* pcrel_offset */
887 /* Displacement to page pointer in the global offset table. */
888 /* FIXME: Not handled correctly. */
889 HOWTO (R_MIPS_GOT_PAGE, /* type */
891 2, /* size (0 = byte, 1 = short, 2 = long) */
893 false, /* pc_relative */
895 complain_overflow_signed, /* complain_on_overflow */
896 bfd_elf_generic_reloc, /* special_function */
897 "R_MIPS_GOT_PAGE", /* name */
898 false, /* partial_inplace */
900 0x0000ffff, /* dst_mask */
901 false), /* pcrel_offset */
903 /* Offset from page pointer in the global offset table. */
904 /* FIXME: Not handled correctly. */
905 HOWTO (R_MIPS_GOT_OFST, /* type */
907 2, /* size (0 = byte, 1 = short, 2 = long) */
909 false, /* pc_relative */
911 complain_overflow_signed, /* complain_on_overflow */
912 bfd_elf_generic_reloc, /* special_function */
913 "R_MIPS_GOT_OFST", /* name */
914 false, /* partial_inplace */
916 0x0000ffff, /* dst_mask */
917 false), /* pcrel_offset */
919 /* High 16 bits of displacement in global offset table. */
920 /* FIXME: Not handled correctly. */
921 HOWTO (R_MIPS_GOT_HI16, /* type */
923 2, /* size (0 = byte, 1 = short, 2 = long) */
925 false, /* pc_relative */
927 complain_overflow_dont, /* complain_on_overflow */
928 bfd_elf_generic_reloc, /* special_function */
929 "R_MIPS_GOT_HI16", /* name */
930 false, /* partial_inplace */
932 0x0000ffff, /* dst_mask */
933 false), /* pcrel_offset */
935 /* Low 16 bits of displacement in global offset table. */
936 /* FIXME: Not handled correctly. */
937 HOWTO (R_MIPS_GOT_LO16, /* type */
939 2, /* size (0 = byte, 1 = short, 2 = long) */
941 false, /* pc_relative */
943 complain_overflow_dont, /* complain_on_overflow */
944 bfd_elf_generic_reloc, /* special_function */
945 "R_MIPS_GOT_LO16", /* name */
946 false, /* partial_inplace */
948 0x0000ffff, /* dst_mask */
949 false), /* pcrel_offset */
951 /* 64 bit substraction. */
952 /* FIXME: Not handled correctly. */
953 HOWTO (R_MIPS_SUB, /* type */
955 4, /* size (0 = byte, 1 = short, 2 = long) */
957 false, /* pc_relative */
959 complain_overflow_dont, /* complain_on_overflow */
960 bfd_elf_generic_reloc, /* special_function */
961 "R_MIPS_SUB", /* name */
962 false, /* partial_inplace */
964 MINUS_ONE, /* dst_mask */
965 false), /* pcrel_offset */
967 /* Insert the addend as an instruction. */
968 /* FIXME: Not handled correctly. */
969 HOWTO (R_MIPS_INSERT_A, /* type */
971 2, /* size (0 = byte, 1 = short, 2 = long) */
973 false, /* pc_relative */
975 complain_overflow_dont, /* complain_on_overflow */
976 bfd_elf_generic_reloc, /* special_function */
977 "R_MIPS_INSERT_A", /* name */
978 false, /* partial_inplace */
980 0xffffffff, /* dst_mask */
981 false), /* pcrel_offset */
983 /* Insert the addend as an instruction, and change all relocations
984 to refer to the old instruction at the address. */
985 /* FIXME: Not handled correctly. */
986 HOWTO (R_MIPS_INSERT_B, /* type */
988 2, /* size (0 = byte, 1 = short, 2 = long) */
990 false, /* pc_relative */
992 complain_overflow_dont, /* complain_on_overflow */
993 bfd_elf_generic_reloc, /* special_function */
994 "R_MIPS_INSERT_B", /* name */
995 false, /* partial_inplace */
997 0xffffffff, /* dst_mask */
998 false), /* pcrel_offset */
1000 /* Delete a 32 bit instruction. */
1001 /* FIXME: Not handled correctly. */
1002 HOWTO (R_MIPS_DELETE, /* type */
1004 2, /* size (0 = byte, 1 = short, 2 = long) */
1006 false, /* pc_relative */
1008 complain_overflow_dont, /* complain_on_overflow */
1009 bfd_elf_generic_reloc, /* special_function */
1010 "R_MIPS_DELETE", /* name */
1011 false, /* partial_inplace */
1013 0xffffffff, /* dst_mask */
1014 false), /* pcrel_offset */
1016 /* Get the higher value of a 64 bit addend. */
1017 HOWTO (R_MIPS_HIGHER, /* type */
1019 2, /* size (0 = byte, 1 = short, 2 = long) */
1021 false, /* pc_relative */
1023 complain_overflow_dont, /* complain_on_overflow */
1024 bfd_elf_generic_reloc, /* special_function */
1025 "R_MIPS_HIGHER", /* name */
1026 false, /* partial_inplace */
1028 0xffff, /* dst_mask */
1029 false), /* pcrel_offset */
1031 /* Get the highest value of a 64 bit addend. */
1032 HOWTO (R_MIPS_HIGHEST, /* type */
1034 2, /* size (0 = byte, 1 = short, 2 = long) */
1036 false, /* pc_relative */
1038 complain_overflow_dont, /* complain_on_overflow */
1039 bfd_elf_generic_reloc, /* special_function */
1040 "R_MIPS_HIGHEST", /* name */
1041 false, /* partial_inplace */
1043 0xffff, /* dst_mask */
1044 false), /* pcrel_offset */
1046 /* High 16 bits of displacement in global offset table. */
1047 /* FIXME: Not handled correctly. */
1048 HOWTO (R_MIPS_CALL_HI16, /* type */
1050 2, /* size (0 = byte, 1 = short, 2 = long) */
1052 false, /* pc_relative */
1054 complain_overflow_dont, /* complain_on_overflow */
1055 bfd_elf_generic_reloc, /* special_function */
1056 "R_MIPS_CALL_HI16", /* name */
1057 false, /* partial_inplace */
1059 0xffff, /* dst_mask */
1060 false), /* pcrel_offset */
1062 /* Low 16 bits of displacement in global offset table. */
1063 /* FIXME: Not handled correctly. */
1064 HOWTO (R_MIPS_CALL_LO16, /* type */
1066 2, /* size (0 = byte, 1 = short, 2 = long) */
1068 false, /* pc_relative */
1070 complain_overflow_dont, /* complain_on_overflow */
1071 bfd_elf_generic_reloc, /* special_function */
1072 "R_MIPS_CALL_LO16", /* name */
1073 false, /* partial_inplace */
1075 0xffff, /* dst_mask */
1076 false), /* pcrel_offset */
1078 /* I'm not sure what the remaining relocs are, but they are defined
1081 HOWTO (R_MIPS_SCN_DISP, /* type */
1083 2, /* size (0 = byte, 1 = short, 2 = long) */
1085 false, /* pc_relative */
1087 complain_overflow_dont, /* complain_on_overflow */
1088 bfd_elf_generic_reloc, /* special_function */
1089 "R_MIPS_SCN_DISP", /* name */
1090 false, /* partial_inplace */
1092 0xffffffff, /* dst_mask */
1093 false), /* pcrel_offset */
1095 HOWTO (R_MIPS_REL16, /* type */
1097 1, /* size (0 = byte, 1 = short, 2 = long) */
1099 false, /* pc_relative */
1101 complain_overflow_signed, /* complain_on_overflow */
1102 bfd_elf_generic_reloc, /* special_function */
1103 "R_MIPS_REL16", /* name */
1104 false, /* partial_inplace */
1106 0xffff, /* dst_mask */
1107 false), /* pcrel_offset */
1109 /* These two are obsolete. */
1110 EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
1111 EMPTY_HOWTO (R_MIPS_PJUMP),
1113 HOWTO (R_MIPS_RELGOT, /* type */
1115 2, /* size (0 = byte, 1 = short, 2 = long) */
1117 false, /* pc_relative */
1119 complain_overflow_dont, /* complain_on_overflow */
1120 bfd_elf_generic_reloc, /* special_function */
1121 "R_MIPS_RELGOT", /* name */
1122 false, /* partial_inplace */
1124 0xffffffff, /* dst_mask */
1125 false), /* pcrel_offset */
1127 /* Protected jump conversion. This is an optimization hint. No
1128 relocation is required for correctness. */
1129 HOWTO (R_MIPS_JALR, /* type */
1131 2, /* size (0 = byte, 1 = short, 2 = long) */
1133 false, /* pc_relative */
1135 complain_overflow_dont, /* complain_on_overflow */
1136 bfd_elf_generic_reloc, /* special_function */
1137 "R_MIPS_JALR", /* name */
1138 false, /* partial_inplace */
1141 false), /* pcrel_offset */
1144 /* Swap in a MIPS 64-bit Rel reloc. */
1147 mips_elf64_swap_reloc_in (abfd, src, dst)
1149 const Elf64_Mips_External_Rel *src;
1150 Elf64_Mips_Internal_Rel *dst;
1152 dst->r_offset = H_GET_64 (abfd, src->r_offset);
1153 dst->r_sym = H_GET_32 (abfd, src->r_sym);
1154 dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1155 dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1156 dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1157 dst->r_type = H_GET_8 (abfd, src->r_type);
1160 /* Swap in a MIPS 64-bit Rela reloc. */
1163 mips_elf64_swap_reloca_in (abfd, src, dst)
1165 const Elf64_Mips_External_Rela *src;
1166 Elf64_Mips_Internal_Rela *dst;
1168 dst->r_offset = H_GET_64 (abfd, src->r_offset);
1169 dst->r_sym = H_GET_32 (abfd, src->r_sym);
1170 dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1171 dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1172 dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1173 dst->r_type = H_GET_8 (abfd, src->r_type);
1174 dst->r_addend = H_GET_S64 (abfd, src->r_addend);
1177 /* Swap out a MIPS 64-bit Rel reloc. */
1180 mips_elf64_swap_reloc_out (abfd, src, dst)
1182 const Elf64_Mips_Internal_Rel *src;
1183 Elf64_Mips_External_Rel *dst;
1185 H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1186 H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1187 H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1188 H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1189 H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1190 H_PUT_8 (abfd, src->r_type, dst->r_type);
1193 /* Swap out a MIPS 64-bit Rela reloc. */
1196 mips_elf64_swap_reloca_out (abfd, src, dst)
1198 const Elf64_Mips_Internal_Rela *src;
1199 Elf64_Mips_External_Rela *dst;
1201 H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1202 H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1203 H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1204 H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1205 H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1206 H_PUT_8 (abfd, src->r_type, dst->r_type);
1207 H_PUT_64 (abfd, src->r_addend, dst->r_addend);
1210 /* Swap in a MIPS 64-bit Rel reloc. */
1213 mips_elf64_be_swap_reloc_in (abfd, src, dst)
1215 const bfd_byte *src;
1216 Elf_Internal_Rel *dst;
1218 Elf64_Mips_Internal_Rel mirel;
1220 mips_elf64_swap_reloc_in (abfd,
1221 (const Elf64_Mips_External_Rel *) src,
1224 dst[0].r_offset = mirel.r_offset;
1225 dst[0].r_info = ELF32_R_INFO (mirel.r_sym, mirel.r_type);
1226 dst[1].r_offset = mirel.r_offset;
1227 dst[1].r_info = ELF32_R_INFO (mirel.r_ssym, mirel.r_type2);
1228 dst[2].r_offset = mirel.r_offset;
1229 dst[2].r_info = ELF32_R_INFO (STN_UNDEF, mirel.r_type3);
1232 /* Swap in a MIPS 64-bit Rela reloc. */
1235 mips_elf64_be_swap_reloca_in (abfd, src, dst)
1237 const bfd_byte *src;
1238 Elf_Internal_Rela *dst;
1240 Elf64_Mips_Internal_Rela mirela;
1242 mips_elf64_swap_reloca_in (abfd,
1243 (const Elf64_Mips_External_Rela *) src,
1246 dst[0].r_offset = mirela.r_offset;
1247 dst[0].r_info = ELF32_R_INFO (mirela.r_sym, mirela.r_type);
1248 dst[0].r_addend = mirela.r_addend;
1249 dst[1].r_offset = mirela.r_offset;
1250 dst[1].r_info = ELF32_R_INFO (mirela.r_ssym, mirela.r_type2);
1251 dst[1].r_addend = 0;
1252 dst[2].r_offset = mirela.r_offset;
1253 dst[2].r_info = ELF32_R_INFO (STN_UNDEF, mirela.r_type3);
1254 dst[2].r_addend = 0;
1257 /* Swap out a MIPS 64-bit Rel reloc. */
1260 mips_elf64_be_swap_reloc_out (abfd, src, dst)
1262 const Elf_Internal_Rel *src;
1265 Elf64_Mips_Internal_Rel mirel;
1267 mirel.r_offset = src->r_offset;
1268 mirel.r_type = ELF32_R_TYPE (src->r_info);
1269 mirel.r_sym = ELF32_R_SYM (src->r_info);
1270 mirel.r_type2 = R_MIPS_NONE;
1271 mirel.r_ssym = STN_UNDEF;
1272 mirel.r_type3 = R_MIPS_NONE;
1274 mips_elf64_swap_reloc_out (abfd, &mirel,
1275 (Elf64_Mips_External_Rel *) dst);
1278 /* Swap out a MIPS 64-bit Rela reloc. */
1281 mips_elf64_be_swap_reloca_out (abfd, src, dst)
1283 const Elf_Internal_Rela *src;
1286 Elf64_Mips_Internal_Rela mirela;
1288 mirela.r_offset = src->r_offset;
1289 mirela.r_type = ELF32_R_TYPE (src->r_info);
1290 mirela.r_addend = src->r_addend;
1291 mirela.r_sym = ELF32_R_SYM (src->r_info);
1292 mirela.r_type2 = R_MIPS_NONE;
1293 mirela.r_ssym = STN_UNDEF;
1294 mirela.r_type3 = R_MIPS_NONE;
1296 mips_elf64_swap_reloca_out (abfd, &mirela,
1297 (Elf64_Mips_External_Rela *) dst);
1300 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1302 struct elf_reloc_map
1304 bfd_reloc_code_real_type bfd_reloc_val;
1305 enum elf_mips_reloc_type elf_reloc_val;
1308 static const struct elf_reloc_map mips_reloc_map[] =
1310 { BFD_RELOC_NONE, R_MIPS_NONE, },
1311 { BFD_RELOC_16, R_MIPS_16 },
1312 { BFD_RELOC_32, R_MIPS_32 },
1313 { BFD_RELOC_64, R_MIPS_64 },
1314 { BFD_RELOC_CTOR, R_MIPS_64 },
1315 { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
1316 { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
1317 { BFD_RELOC_HI16_S, R_MIPS_HI16 },
1318 { BFD_RELOC_LO16, R_MIPS_LO16 },
1319 { BFD_RELOC_GPREL16, R_MIPS_GPREL16 },
1320 { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
1321 { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
1322 { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
1323 { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
1324 { BFD_RELOC_GPREL32, R_MIPS_GPREL32 },
1325 { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
1326 { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
1327 { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
1328 { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
1329 { BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
1330 { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
1331 { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
1332 { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP }
1335 /* Given a BFD reloc type, return a howto structure. */
1337 static reloc_howto_type *
1338 mips_elf64_reloc_type_lookup (abfd, code)
1339 bfd *abfd ATTRIBUTE_UNUSED;
1340 bfd_reloc_code_real_type code;
1344 for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
1346 if (mips_reloc_map[i].bfd_reloc_val == code)
1350 v = (int) mips_reloc_map[i].elf_reloc_val;
1351 return &mips_elf64_howto_table_rel[v];
1358 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1359 to three relocs, we must tell the user to allocate more space. */
1362 mips_elf64_get_reloc_upper_bound (abfd, sec)
1363 bfd *abfd ATTRIBUTE_UNUSED;
1366 return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
1369 /* Read the relocations from one reloc section. */
1372 mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
1376 const Elf_Internal_Shdr *rel_hdr;
1378 PTR allocated = NULL;
1379 bfd_byte *native_relocs;
1385 reloc_howto_type *howto_table;
1387 allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
1388 if (allocated == NULL)
1391 if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
1392 || (bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
1395 native_relocs = (bfd_byte *) allocated;
1397 relents = asect->relocation + asect->reloc_count;
1399 entsize = rel_hdr->sh_entsize;
1400 BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
1401 || entsize == sizeof (Elf64_Mips_External_Rela));
1403 count = rel_hdr->sh_size / entsize;
1405 if (entsize == sizeof (Elf64_Mips_External_Rel))
1406 howto_table = mips_elf64_howto_table_rel;
1408 howto_table = mips_elf64_howto_table_rela;
1411 for (i = 0; i < count; i++, native_relocs += entsize)
1413 Elf64_Mips_Internal_Rela rela;
1414 boolean used_sym, used_ssym;
1417 if (entsize == sizeof (Elf64_Mips_External_Rela))
1418 mips_elf64_swap_reloca_in (abfd,
1419 (Elf64_Mips_External_Rela *) native_relocs,
1423 Elf64_Mips_Internal_Rel rel;
1425 mips_elf64_swap_reloc_in (abfd,
1426 (Elf64_Mips_External_Rel *) native_relocs,
1428 rela.r_offset = rel.r_offset;
1429 rela.r_sym = rel.r_sym;
1430 rela.r_ssym = rel.r_ssym;
1431 rela.r_type3 = rel.r_type3;
1432 rela.r_type2 = rel.r_type2;
1433 rela.r_type = rel.r_type;
1437 /* Each entry represents up to three actual relocations. */
1441 for (ir = 0; ir < 3; ir++)
1443 enum elf_mips_reloc_type type;
1450 type = (enum elf_mips_reloc_type) rela.r_type;
1453 type = (enum elf_mips_reloc_type) rela.r_type2;
1456 type = (enum elf_mips_reloc_type) rela.r_type3;
1460 if (type == R_MIPS_NONE)
1462 /* There are no more relocations in this entry. If this
1463 is the first entry, we need to generate a dummy
1464 relocation so that the generic linker knows that
1465 there has been a break in the sequence of relocations
1466 applying to a particular address. */
1469 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1470 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1471 relent->address = rela.r_offset;
1473 relent->address = rela.r_offset - asect->vma;
1475 relent->howto = &howto_table[(int) R_MIPS_NONE];
1481 /* Some types require symbols, whereas some do not. */
1485 case R_MIPS_LITERAL:
1486 case R_MIPS_INSERT_A:
1487 case R_MIPS_INSERT_B:
1489 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1495 if (rela.r_sym == 0)
1496 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1501 ps = symbols + rela.r_sym - 1;
1503 if ((s->flags & BSF_SECTION_SYM) == 0)
1504 relent->sym_ptr_ptr = ps;
1506 relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
1511 else if (! used_ssym)
1513 switch (rela.r_ssym)
1516 relent->sym_ptr_ptr =
1517 bfd_abs_section_ptr->symbol_ptr_ptr;
1523 /* FIXME: I think these need to be handled using
1524 special howto structures. */
1536 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1541 /* The address of an ELF reloc is section relative for an
1542 object file, and absolute for an executable file or
1543 shared library. The address of a BFD reloc is always
1544 section relative. */
1545 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1546 relent->address = rela.r_offset;
1548 relent->address = rela.r_offset - asect->vma;
1550 relent->addend = rela.r_addend;
1552 relent->howto = &howto_table[(int) type];
1558 asect->reloc_count += relent - relents;
1560 if (allocated != NULL)
1566 if (allocated != NULL)
1571 /* Read the relocations. On Irix 6, there can be two reloc sections
1572 associated with a single data section. */
1575 mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
1582 struct bfd_elf_section_data * const d = elf_section_data (asect);
1586 bfd_set_error (bfd_error_invalid_operation);
1590 if (asect->relocation != NULL
1591 || (asect->flags & SEC_RELOC) == 0
1592 || asect->reloc_count == 0)
1595 /* Allocate space for 3 arelent structures for each Rel structure. */
1596 amt = asect->reloc_count;
1597 amt *= 3 * sizeof (arelent);
1598 asect->relocation = (arelent *) bfd_alloc (abfd, amt);
1599 if (asect->relocation == NULL)
1602 /* The slurp_one_reloc_table routine increments reloc_count. */
1603 asect->reloc_count = 0;
1605 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
1607 if (d->rel_hdr2 != NULL)
1609 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
1617 /* Write out the relocations. */
1620 mips_elf64_write_relocs (abfd, sec, data)
1625 boolean *failedp = (boolean *) data;
1627 Elf_Internal_Shdr *rela_hdr;
1628 Elf64_Mips_External_Rela *ext_rela;
1630 asymbol *last_sym = 0;
1631 int last_sym_idx = 0;
1633 /* If we have already failed, don't do anything. */
1637 if ((sec->flags & SEC_RELOC) == 0)
1640 /* The linker backend writes the relocs out itself, and sets the
1641 reloc_count field to zero to inhibit writing them here. Also,
1642 sometimes the SEC_RELOC flag gets set even when there aren't any
1644 if (sec->reloc_count == 0)
1647 /* We can combine up to three relocs that refer to the same address
1648 if the latter relocs have no associated symbol. */
1650 for (idx = 0; idx < sec->reloc_count; idx++)
1657 addr = sec->orelocation[idx]->address;
1658 for (i = 0; i < 2; i++)
1662 if (idx + 1 >= sec->reloc_count)
1664 r = sec->orelocation[idx + 1];
1665 if (r->address != addr
1666 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
1667 || (*r->sym_ptr_ptr)->value != 0)
1670 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1676 rela_hdr = &elf_section_data (sec)->rel_hdr;
1678 rela_hdr->sh_size = rela_hdr->sh_entsize * count;
1679 rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
1680 if (rela_hdr->contents == NULL)
1686 ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
1687 for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
1690 Elf64_Mips_Internal_Rela int_rela;
1695 ptr = sec->orelocation[idx];
1697 /* The address of an ELF reloc is section relative for an object
1698 file, and absolute for an executable file or shared library.
1699 The address of a BFD reloc is always section relative. */
1700 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1701 int_rela.r_offset = ptr->address;
1703 int_rela.r_offset = ptr->address + sec->vma;
1705 sym = *ptr->sym_ptr_ptr;
1706 if (sym == last_sym)
1711 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
1722 int_rela.r_addend = ptr->addend;
1724 int_rela.r_ssym = RSS_UNDEF;
1726 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
1727 && ! _bfd_elf_validate_reloc (abfd, ptr))
1733 int_rela.r_type = ptr->howto->type;
1734 int_rela.r_type2 = (int) R_MIPS_NONE;
1735 int_rela.r_type3 = (int) R_MIPS_NONE;
1737 for (i = 0; i < 2; i++)
1741 if (idx + 1 >= sec->reloc_count)
1743 r = sec->orelocation[idx + 1];
1744 if (r->address != ptr->address
1745 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
1746 || (*r->sym_ptr_ptr)->value != 0)
1749 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1752 int_rela.r_type2 = r->howto->type;
1754 int_rela.r_type3 = r->howto->type;
1759 mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
1762 BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
1766 /* ECOFF swapping routines. These are used when dealing with the
1767 .mdebug section, which is in the ECOFF debugging format. */
1768 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
1770 /* Symbol table magic number. */
1772 /* Alignment of debugging information. E.g., 4. */
1774 /* Sizes of external symbolic information. */
1775 sizeof (struct hdr_ext),
1776 sizeof (struct dnr_ext),
1777 sizeof (struct pdr_ext),
1778 sizeof (struct sym_ext),
1779 sizeof (struct opt_ext),
1780 sizeof (struct fdr_ext),
1781 sizeof (struct rfd_ext),
1782 sizeof (struct ext_ext),
1783 /* Functions to swap in external symbolic data. */
1792 _bfd_ecoff_swap_tir_in,
1793 _bfd_ecoff_swap_rndx_in,
1794 /* Functions to swap out external symbolic data. */
1803 _bfd_ecoff_swap_tir_out,
1804 _bfd_ecoff_swap_rndx_out,
1805 /* Function to read in symbolic data. */
1806 _bfd_mips_elf_read_ecoff_info
1809 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
1810 standard ELF. This structure is used to redirect the relocation
1811 handling routines. */
1813 const struct elf_size_info mips_elf64_size_info =
1815 sizeof (Elf64_External_Ehdr),
1816 sizeof (Elf64_External_Phdr),
1817 sizeof (Elf64_External_Shdr),
1818 sizeof (Elf64_Mips_External_Rel),
1819 sizeof (Elf64_Mips_External_Rela),
1820 sizeof (Elf64_External_Sym),
1821 sizeof (Elf64_External_Dyn),
1822 sizeof (Elf_External_Note),
1823 4, /* hash-table entry size */
1824 3, /* internal relocations per external relocations */
1829 bfd_elf64_write_out_phdrs,
1830 bfd_elf64_write_shdrs_and_ehdr,
1831 mips_elf64_write_relocs,
1832 bfd_elf64_swap_symbol_out,
1833 mips_elf64_slurp_reloc_table,
1834 bfd_elf64_slurp_symbol_table,
1835 bfd_elf64_swap_dyn_in,
1836 bfd_elf64_swap_dyn_out,
1837 mips_elf64_be_swap_reloc_in,
1838 mips_elf64_be_swap_reloc_out,
1839 mips_elf64_be_swap_reloca_in,
1840 mips_elf64_be_swap_reloca_out
1843 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
1844 #define TARGET_LITTLE_NAME "elf64-littlemips"
1845 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
1846 #define TARGET_BIG_NAME "elf64-bigmips"
1847 #define ELF_ARCH bfd_arch_mips
1848 #define ELF_MACHINE_CODE EM_MIPS
1850 #define ELF_MAXPAGESIZE 0x1000
1852 #define elf_backend_collect true
1853 #define elf_backend_type_change_ok true
1854 #define elf_backend_can_gc_sections true
1855 #define elf_backend_size_info mips_elf64_size_info
1856 #define elf_backend_object_p _bfd_mips_elf_object_p
1857 #define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
1858 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
1859 #define elf_backend_section_from_bfd_section \
1860 _bfd_mips_elf_section_from_bfd_section
1861 #define elf_backend_section_processing _bfd_mips_elf_section_processing
1862 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
1863 #define elf_backend_additional_program_headers \
1864 _bfd_mips_elf_additional_program_headers
1865 #define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
1866 #define elf_backend_final_write_processing \
1867 _bfd_mips_elf_final_write_processing
1868 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
1869 #define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook
1870 #define elf_backend_create_dynamic_sections \
1871 _bfd_mips_elf_create_dynamic_sections
1872 #define elf_backend_check_relocs _bfd_mips_elf_check_relocs
1873 #define elf_backend_adjust_dynamic_symbol \
1874 _bfd_mips_elf_adjust_dynamic_symbol
1875 #define elf_backend_always_size_sections \
1876 _bfd_mips_elf_always_size_sections
1877 #define elf_backend_size_dynamic_sections \
1878 _bfd_mips_elf_size_dynamic_sections
1879 #define elf_backend_relocate_section _bfd_mips_elf_relocate_section
1880 #define elf_backend_link_output_symbol_hook \
1881 _bfd_mips_elf_link_output_symbol_hook
1882 #define elf_backend_finish_dynamic_symbol \
1883 _bfd_mips_elf_finish_dynamic_symbol
1884 #define elf_backend_finish_dynamic_sections \
1885 _bfd_mips_elf_finish_dynamic_sections
1886 #define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook
1887 #define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
1888 #define elf_backend_got_header_size (4*MIPS_RESERVED_GOTNO)
1889 #define elf_backend_plt_header_size 0
1891 /* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
1892 * work better/work only in RELA, so we default to this. */
1893 #define elf_backend_may_use_rel_p 1
1894 #define elf_backend_may_use_rela_p 1
1895 #define elf_backend_default_use_rela_p 1
1897 /* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit
1898 MIPS-specific function only applies to IRIX5, which had no 64-bit
1900 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
1901 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
1902 #define bfd_elf64_bfd_link_hash_table_create \
1903 _bfd_mips_elf_link_hash_table_create
1904 #define bfd_elf64_bfd_final_link _bfd_mips_elf_final_link
1905 #define bfd_elf64_bfd_copy_private_bfd_data \
1906 _bfd_mips_elf_copy_private_bfd_data
1907 #define bfd_elf64_bfd_merge_private_bfd_data \
1908 _bfd_mips_elf_merge_private_bfd_data
1909 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
1910 #define bfd_elf64_bfd_print_private_bfd_data \
1911 _bfd_mips_elf_print_private_bfd_data
1913 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
1914 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
1915 #define bfd_elf64_archive_functions
1916 extern boolean bfd_elf64_archive_slurp_armap
1918 extern boolean bfd_elf64_archive_write_armap
1919 PARAMS((bfd *, unsigned int, struct orl *, unsigned int, int));
1920 #define bfd_elf64_archive_slurp_extended_name_table \
1921 _bfd_archive_coff_slurp_extended_name_table
1922 #define bfd_elf64_archive_construct_extended_name_table \
1923 _bfd_archive_coff_construct_extended_name_table
1924 #define bfd_elf64_archive_truncate_arname \
1925 _bfd_archive_coff_truncate_arname
1926 #define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
1927 #define bfd_elf64_archive_openr_next_archived_file \
1928 _bfd_archive_coff_openr_next_archived_file
1929 #define bfd_elf64_archive_get_elt_at_index \
1930 _bfd_archive_coff_get_elt_at_index
1931 #define bfd_elf64_archive_generic_stat_arch_elt \
1932 _bfd_archive_coff_generic_stat_arch_elt
1933 #define bfd_elf64_archive_update_armap_timestamp \
1934 _bfd_archive_coff_update_armap_timestamp
1936 #include "elf64-target.h"
1938 /* Support for traditional mips targets */
1940 #define INCLUDED_TARGET_FILE /* More a type of flag */
1942 #undef TARGET_LITTLE_SYM
1943 #undef TARGET_LITTLE_NAME
1944 #undef TARGET_BIG_SYM
1945 #undef TARGET_BIG_NAME
1947 #define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
1948 #define TARGET_LITTLE_NAME "elf64-tradlittlemips"
1949 #define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
1950 #define TARGET_BIG_NAME "elf64-tradbigmips"
1952 /* Include the target file again for this target */
1953 #include "elf64-target.h"