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 *));
71 /* The relocation types. */
73 enum mips_elf64_reloc_type
100 R_MIPS_GOT_LO16
= 23,
102 R_MIPS_INSERT_A
= 25,
103 R_MIPS_INSERT_B
= 26,
107 R_MIPS_CALL_HI16
= 30,
108 R_MIPS_CALL_LO16
= 31,
109 R_MIPS_SCN_DISP
= 32,
111 R_MIPS_ADD_IMMEDIATE
= 34,
116 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
117 from smaller values. Start with zero, widen, *then* decrement. */
118 #define MINUS_ONE (((bfd_vma)0) - 1)
120 /* FIXME: These need to be rewritten, or we need to use the versions
122 #define mips_elf_hi16_reloc bfd_elf_generic_reloc
123 #define mips_elf_lo16_reloc bfd_elf_generic_reloc
124 #define mips_elf_gprel16_reloc bfd_elf_generic_reloc
125 #define mips_elf_got16_reloc bfd_elf_generic_reloc
126 #define mips_elf_gprel32_reloc bfd_elf_generic_reloc
128 /* The relocation table used for SHT_REL sections. */
130 static reloc_howto_type mips_elf64_howto_table_rel
[] =
133 HOWTO (R_MIPS_NONE
, /* type */
135 0, /* size (0 = byte, 1 = short, 2 = long) */
137 false, /* pc_relative */
139 complain_overflow_dont
, /* complain_on_overflow */
140 bfd_elf_generic_reloc
, /* special_function */
141 "R_MIPS_NONE", /* name */
142 false, /* partial_inplace */
145 false), /* pcrel_offset */
147 /* 16 bit relocation. */
148 HOWTO (R_MIPS_16
, /* type */
150 1, /* size (0 = byte, 1 = short, 2 = long) */
152 false, /* pc_relative */
154 complain_overflow_bitfield
, /* complain_on_overflow */
155 bfd_elf_generic_reloc
, /* special_function */
156 "R_MIPS_16", /* name */
157 true, /* partial_inplace */
158 0xffff, /* src_mask */
159 0xffff, /* dst_mask */
160 false), /* pcrel_offset */
162 /* 32 bit relocation. */
163 HOWTO (R_MIPS_32
, /* type */
165 2, /* size (0 = byte, 1 = short, 2 = long) */
167 false, /* pc_relative */
169 complain_overflow_bitfield
, /* complain_on_overflow */
170 bfd_elf_generic_reloc
, /* special_function */
171 "R_MIPS_32", /* name */
172 true, /* partial_inplace */
173 0xffffffff, /* src_mask */
174 0xffffffff, /* dst_mask */
175 false), /* pcrel_offset */
177 /* 32 bit symbol relative relocation. */
178 HOWTO (R_MIPS_REL32
, /* type */
180 2, /* size (0 = byte, 1 = short, 2 = long) */
182 false, /* pc_relative */
184 complain_overflow_bitfield
, /* complain_on_overflow */
185 bfd_elf_generic_reloc
, /* special_function */
186 "R_MIPS_REL32", /* name */
187 true, /* partial_inplace */
188 0xffffffff, /* src_mask */
189 0xffffffff, /* dst_mask */
190 false), /* pcrel_offset */
192 /* 26 bit branch address. */
193 HOWTO (R_MIPS_26
, /* type */
195 2, /* size (0 = byte, 1 = short, 2 = long) */
197 false, /* pc_relative */
199 complain_overflow_dont
, /* complain_on_overflow */
200 /* This needs complex overflow
201 detection, because the upper four
202 bits must match the PC. */
203 bfd_elf_generic_reloc
, /* special_function */
204 "R_MIPS_26", /* name */
205 true, /* partial_inplace */
206 0x3ffffff, /* src_mask */
207 0x3ffffff, /* dst_mask */
208 false), /* pcrel_offset */
210 /* High 16 bits of symbol value. */
211 HOWTO (R_MIPS_HI16
, /* type */
213 2, /* size (0 = byte, 1 = short, 2 = long) */
215 false, /* pc_relative */
217 complain_overflow_dont
, /* complain_on_overflow */
218 mips_elf_hi16_reloc
, /* special_function */
219 "R_MIPS_HI16", /* name */
220 true, /* partial_inplace */
221 0xffff, /* src_mask */
222 0xffff, /* dst_mask */
223 false), /* pcrel_offset */
225 /* Low 16 bits of symbol value. */
226 HOWTO (R_MIPS_LO16
, /* type */
228 2, /* size (0 = byte, 1 = short, 2 = long) */
230 false, /* pc_relative */
232 complain_overflow_dont
, /* complain_on_overflow */
233 mips_elf_lo16_reloc
, /* special_function */
234 "R_MIPS_LO16", /* name */
235 true, /* partial_inplace */
236 0xffff, /* src_mask */
237 0xffff, /* dst_mask */
238 false), /* pcrel_offset */
240 /* GP relative reference. */
241 HOWTO (R_MIPS_GPREL16
, /* type */
243 2, /* size (0 = byte, 1 = short, 2 = long) */
245 false, /* pc_relative */
247 complain_overflow_signed
, /* complain_on_overflow */
248 mips_elf_gprel16_reloc
, /* special_function */
249 "R_MIPS_GPREL16", /* name */
250 true, /* partial_inplace */
251 0xffff, /* src_mask */
252 0xffff, /* dst_mask */
253 false), /* pcrel_offset */
255 /* Reference to literal section. */
256 HOWTO (R_MIPS_LITERAL
, /* type */
258 2, /* size (0 = byte, 1 = short, 2 = long) */
260 false, /* pc_relative */
262 complain_overflow_signed
, /* complain_on_overflow */
263 mips_elf_gprel16_reloc
, /* special_function */
264 "R_MIPS_LITERAL", /* name */
265 true, /* partial_inplace */
266 0xffff, /* src_mask */
267 0xffff, /* dst_mask */
268 false), /* pcrel_offset */
270 /* Reference to global offset table. */
271 HOWTO (R_MIPS_GOT16
, /* type */
273 2, /* size (0 = byte, 1 = short, 2 = long) */
275 false, /* pc_relative */
277 complain_overflow_signed
, /* complain_on_overflow */
278 mips_elf_got16_reloc
, /* special_function */
279 "R_MIPS_GOT16", /* name */
280 false, /* partial_inplace */
282 0xffff, /* dst_mask */
283 false), /* pcrel_offset */
285 /* 16 bit PC relative reference. */
286 HOWTO (R_MIPS_PC16
, /* type */
288 2, /* size (0 = byte, 1 = short, 2 = long) */
290 true, /* pc_relative */
292 complain_overflow_signed
, /* complain_on_overflow */
293 bfd_elf_generic_reloc
, /* special_function */
294 "R_MIPS_PC16", /* name */
295 true, /* partial_inplace */
296 0xffff, /* src_mask */
297 0xffff, /* dst_mask */
298 false), /* pcrel_offset */
300 /* 16 bit call through global offset table. */
301 /* FIXME: This is not handled correctly. */
302 HOWTO (R_MIPS_CALL16
, /* type */
304 2, /* size (0 = byte, 1 = short, 2 = long) */
306 false, /* pc_relative */
308 complain_overflow_signed
, /* complain_on_overflow */
309 bfd_elf_generic_reloc
, /* special_function */
310 "R_MIPS_CALL16", /* name */
311 false, /* partial_inplace */
313 0xffff, /* dst_mask */
314 false), /* pcrel_offset */
316 /* 32 bit GP relative reference. */
317 HOWTO (R_MIPS_GPREL32
, /* type */
319 2, /* size (0 = byte, 1 = short, 2 = long) */
321 false, /* pc_relative */
323 complain_overflow_bitfield
, /* complain_on_overflow */
324 mips_elf_gprel32_reloc
, /* special_function */
325 "R_MIPS_GPREL32", /* name */
326 true, /* partial_inplace */
327 0xffffffff, /* src_mask */
328 0xffffffff, /* dst_mask */
329 false), /* pcrel_offset */
335 /* A 5 bit shift field. */
336 HOWTO (R_MIPS_SHIFT5
, /* type */
338 2, /* size (0 = byte, 1 = short, 2 = long) */
340 false, /* pc_relative */
342 complain_overflow_bitfield
, /* complain_on_overflow */
343 bfd_elf_generic_reloc
, /* special_function */
344 "R_MIPS_SHIFT5", /* name */
345 true, /* partial_inplace */
346 0x000007c0, /* src_mask */
347 0x000007c0, /* dst_mask */
348 false), /* pcrel_offset */
350 /* A 6 bit shift field. */
351 /* FIXME: This is not handled correctly; a special function is
352 needed to put the most significant bit in the right place. */
353 HOWTO (R_MIPS_SHIFT6
, /* type */
355 2, /* size (0 = byte, 1 = short, 2 = long) */
357 false, /* pc_relative */
359 complain_overflow_bitfield
, /* complain_on_overflow */
360 bfd_elf_generic_reloc
, /* special_function */
361 "R_MIPS_SHIFT6", /* name */
362 true, /* partial_inplace */
363 0x000007c4, /* src_mask */
364 0x000007c4, /* dst_mask */
365 false), /* pcrel_offset */
367 /* 64 bit relocation. */
368 HOWTO (R_MIPS_64
, /* type */
370 4, /* size (0 = byte, 1 = short, 2 = long) */
372 false, /* pc_relative */
374 complain_overflow_bitfield
, /* complain_on_overflow */
375 bfd_elf_generic_reloc
, /* special_function */
376 "R_MIPS_64", /* name */
377 true, /* partial_inplace */
378 MINUS_ONE
, /* src_mask */
379 MINUS_ONE
, /* dst_mask */
380 false), /* pcrel_offset */
382 /* Displacement in the global offset table. */
383 /* FIXME: Not handled correctly. */
384 HOWTO (R_MIPS_GOT_DISP
, /* type */
386 2, /* size (0 = byte, 1 = short, 2 = long) */
388 false, /* pc_relative */
390 complain_overflow_bitfield
, /* complain_on_overflow */
391 bfd_elf_generic_reloc
, /* special_function */
392 "R_MIPS_GOT_DISP", /* name */
393 true, /* partial_inplace */
394 0x0000ffff, /* src_mask */
395 0x0000ffff, /* dst_mask */
396 false), /* pcrel_offset */
398 /* Displacement to page pointer in the global offset table. */
399 /* FIXME: Not handled correctly. */
400 HOWTO (R_MIPS_GOT_PAGE
, /* type */
402 2, /* size (0 = byte, 1 = short, 2 = long) */
404 false, /* pc_relative */
406 complain_overflow_bitfield
, /* complain_on_overflow */
407 bfd_elf_generic_reloc
, /* special_function */
408 "R_MIPS_GOT_PAGE", /* name */
409 true, /* partial_inplace */
410 0x0000ffff, /* src_mask */
411 0x0000ffff, /* dst_mask */
412 false), /* pcrel_offset */
414 /* Offset from page pointer in the global offset table. */
415 /* FIXME: Not handled correctly. */
416 HOWTO (R_MIPS_GOT_OFST
, /* type */
418 2, /* size (0 = byte, 1 = short, 2 = long) */
420 false, /* pc_relative */
422 complain_overflow_bitfield
, /* complain_on_overflow */
423 bfd_elf_generic_reloc
, /* special_function */
424 "R_MIPS_GOT_OFST", /* name */
425 true, /* partial_inplace */
426 0x0000ffff, /* src_mask */
427 0x0000ffff, /* dst_mask */
428 false), /* pcrel_offset */
430 /* High 16 bits of displacement in global offset table. */
431 /* FIXME: Not handled correctly. */
432 HOWTO (R_MIPS_GOT_HI16
, /* type */
434 2, /* size (0 = byte, 1 = short, 2 = long) */
436 false, /* pc_relative */
438 complain_overflow_dont
, /* complain_on_overflow */
439 bfd_elf_generic_reloc
, /* special_function */
440 "R_MIPS_GOT_HI16", /* name */
441 true, /* partial_inplace */
442 0x0000ffff, /* src_mask */
443 0x0000ffff, /* dst_mask */
444 false), /* pcrel_offset */
446 /* Low 16 bits of displacement in global offset table. */
447 /* FIXME: Not handled correctly. */
448 HOWTO (R_MIPS_GOT_LO16
, /* type */
450 2, /* size (0 = byte, 1 = short, 2 = long) */
452 false, /* pc_relative */
454 complain_overflow_dont
, /* complain_on_overflow */
455 bfd_elf_generic_reloc
, /* special_function */
456 "R_MIPS_GOT_LO16", /* name */
457 true, /* partial_inplace */
458 0x0000ffff, /* src_mask */
459 0x0000ffff, /* dst_mask */
460 false), /* pcrel_offset */
462 /* 64 bit substraction. */
463 /* FIXME: Not handled correctly. */
464 HOWTO (R_MIPS_SUB
, /* type */
466 4, /* size (0 = byte, 1 = short, 2 = long) */
468 false, /* pc_relative */
470 complain_overflow_bitfield
, /* complain_on_overflow */
471 bfd_elf_generic_reloc
, /* special_function */
472 "R_MIPS_SUB", /* name */
473 true, /* partial_inplace */
474 MINUS_ONE
, /* src_mask */
475 MINUS_ONE
, /* dst_mask */
476 false), /* pcrel_offset */
478 /* Insert the addend as an instruction. */
479 /* FIXME: Not handled correctly. */
480 HOWTO (R_MIPS_INSERT_A
, /* type */
482 0, /* size (0 = byte, 1 = short, 2 = long) */
484 false, /* pc_relative */
486 complain_overflow_dont
, /* complain_on_overflow */
487 bfd_elf_generic_reloc
, /* special_function */
488 "R_MIPS_INSERT_A", /* name */
489 false, /* partial_inplace */
492 false), /* pcrel_offset */
494 /* Insert the addend as an instruction, and change all relocations
495 to refer to the old instruction at the address. */
496 /* FIXME: Not handled correctly. */
497 HOWTO (R_MIPS_INSERT_B
, /* type */
499 0, /* size (0 = byte, 1 = short, 2 = long) */
501 false, /* pc_relative */
503 complain_overflow_dont
, /* complain_on_overflow */
504 bfd_elf_generic_reloc
, /* special_function */
505 "R_MIPS_INSERT_B", /* name */
506 false, /* partial_inplace */
509 false), /* pcrel_offset */
511 /* Delete a 32 bit instruction. */
512 /* FIXME: Not handled correctly. */
513 HOWTO (R_MIPS_DELETE
, /* type */
515 0, /* size (0 = byte, 1 = short, 2 = long) */
517 false, /* pc_relative */
519 complain_overflow_dont
, /* complain_on_overflow */
520 bfd_elf_generic_reloc
, /* special_function */
521 "R_MIPS_DELETE", /* name */
522 false, /* partial_inplace */
525 false), /* pcrel_offset */
527 /* Get the higher value of a 64 bit addend. */
528 /* FIXME: Not handled correctly. */
529 HOWTO (R_MIPS_HIGHER
, /* type */
531 2, /* size (0 = byte, 1 = short, 2 = long) */
533 false, /* pc_relative */
535 complain_overflow_dont
, /* complain_on_overflow */
536 bfd_elf_generic_reloc
, /* special_function */
537 "R_MIPS_HIGHER", /* name */
538 true, /* partial_inplace */
539 0xffff, /* src_mask */
540 0xffff, /* dst_mask */
541 false), /* pcrel_offset */
543 /* Get the highest value of a 64 bit addend. */
544 /* FIXME: Not handled correctly. */
545 HOWTO (R_MIPS_HIGHEST
, /* type */
547 2, /* size (0 = byte, 1 = short, 2 = long) */
549 false, /* pc_relative */
551 complain_overflow_dont
, /* complain_on_overflow */
552 bfd_elf_generic_reloc
, /* special_function */
553 "R_MIPS_HIGHEST", /* name */
554 true, /* partial_inplace */
555 0xffff, /* src_mask */
556 0xffff, /* dst_mask */
557 false), /* pcrel_offset */
559 /* High 16 bits of displacement in global offset table. */
560 /* FIXME: Not handled correctly. */
561 HOWTO (R_MIPS_CALL_HI16
, /* type */
563 2, /* size (0 = byte, 1 = short, 2 = long) */
565 false, /* pc_relative */
567 complain_overflow_dont
, /* complain_on_overflow */
568 bfd_elf_generic_reloc
, /* special_function */
569 "R_MIPS_CALL_HI16", /* name */
570 true, /* partial_inplace */
571 0x0000ffff, /* src_mask */
572 0x0000ffff, /* dst_mask */
573 false), /* pcrel_offset */
575 /* Low 16 bits of displacement in global offset table. */
576 /* FIXME: Not handled correctly. */
577 HOWTO (R_MIPS_CALL_LO16
, /* type */
579 2, /* size (0 = byte, 1 = short, 2 = long) */
581 false, /* pc_relative */
583 complain_overflow_dont
, /* complain_on_overflow */
584 bfd_elf_generic_reloc
, /* special_function */
585 "R_MIPS_CALL_LO16", /* name */
586 true, /* partial_inplace */
587 0x0000ffff, /* src_mask */
588 0x0000ffff, /* dst_mask */
589 false), /* pcrel_offset */
591 /* I'm not sure what the remaining relocs are, but they are defined
594 HOWTO (R_MIPS_SCN_DISP
, /* type */
596 0, /* size (0 = byte, 1 = short, 2 = long) */
598 false, /* pc_relative */
600 complain_overflow_dont
, /* complain_on_overflow */
601 bfd_elf_generic_reloc
, /* special_function */
602 "R_MIPS_SCN_DISP", /* name */
603 false, /* partial_inplace */
606 false), /* pcrel_offset */
608 HOWTO (R_MIPS_REL16
, /* type */
610 0, /* size (0 = byte, 1 = short, 2 = long) */
612 false, /* pc_relative */
614 complain_overflow_dont
, /* complain_on_overflow */
615 bfd_elf_generic_reloc
, /* special_function */
616 "R_MIPS_REL16", /* name */
617 false, /* partial_inplace */
620 false), /* pcrel_offset */
622 HOWTO (R_MIPS_ADD_IMMEDIATE
, /* type */
624 0, /* size (0 = byte, 1 = short, 2 = long) */
626 false, /* pc_relative */
628 complain_overflow_dont
, /* complain_on_overflow */
629 bfd_elf_generic_reloc
, /* special_function */
630 "R_MIPS_ADD_IMMEDIATE", /* name */
631 false, /* partial_inplace */
634 false), /* pcrel_offset */
636 HOWTO (R_MIPS_PJUMP
, /* type */
638 0, /* size (0 = byte, 1 = short, 2 = long) */
640 false, /* pc_relative */
642 complain_overflow_dont
, /* complain_on_overflow */
643 bfd_elf_generic_reloc
, /* special_function */
644 "R_MIPS_PJUMP", /* name */
645 false, /* partial_inplace */
648 false), /* pcrel_offset */
650 HOWTO (R_MIPS_RELGOT
, /* type */
652 0, /* size (0 = byte, 1 = short, 2 = long) */
654 false, /* pc_relative */
656 complain_overflow_dont
, /* complain_on_overflow */
657 bfd_elf_generic_reloc
, /* special_function */
658 "R_MIPS_RELGOT", /* name */
659 false, /* partial_inplace */
662 false) /* pcrel_offset */
665 /* The relocation table used for SHT_RELA sections. */
667 static reloc_howto_type mips_elf64_howto_table_rela
[] =
670 HOWTO (R_MIPS_NONE
, /* type */
672 0, /* size (0 = byte, 1 = short, 2 = long) */
674 false, /* pc_relative */
676 complain_overflow_dont
, /* complain_on_overflow */
677 bfd_elf_generic_reloc
, /* special_function */
678 "R_MIPS_NONE", /* name */
679 false, /* partial_inplace */
682 false), /* pcrel_offset */
684 /* 16 bit relocation. */
685 HOWTO (R_MIPS_16
, /* type */
687 1, /* size (0 = byte, 1 = short, 2 = long) */
689 false, /* pc_relative */
691 complain_overflow_bitfield
, /* complain_on_overflow */
692 bfd_elf_generic_reloc
, /* special_function */
693 "R_MIPS_16", /* name */
694 true, /* partial_inplace */
696 0xffff, /* dst_mask */
697 false), /* pcrel_offset */
699 /* 32 bit relocation. */
700 HOWTO (R_MIPS_32
, /* type */
702 2, /* size (0 = byte, 1 = short, 2 = long) */
704 false, /* pc_relative */
706 complain_overflow_bitfield
, /* complain_on_overflow */
707 bfd_elf_generic_reloc
, /* special_function */
708 "R_MIPS_32", /* name */
709 true, /* partial_inplace */
711 0xffffffff, /* dst_mask */
712 false), /* pcrel_offset */
714 /* 32 bit symbol relative relocation. */
715 HOWTO (R_MIPS_REL32
, /* type */
717 2, /* size (0 = byte, 1 = short, 2 = long) */
719 false, /* pc_relative */
721 complain_overflow_bitfield
, /* complain_on_overflow */
722 bfd_elf_generic_reloc
, /* special_function */
723 "R_MIPS_REL32", /* name */
724 true, /* partial_inplace */
726 0xffffffff, /* dst_mask */
727 false), /* pcrel_offset */
729 /* 26 bit branch address. */
730 HOWTO (R_MIPS_26
, /* type */
732 2, /* size (0 = byte, 1 = short, 2 = long) */
734 false, /* pc_relative */
736 complain_overflow_dont
, /* complain_on_overflow */
737 /* This needs complex overflow
738 detection, because the upper four
739 bits must match the PC. */
740 bfd_elf_generic_reloc
, /* special_function */
741 "R_MIPS_26", /* name */
742 true, /* partial_inplace */
744 0x3ffffff, /* dst_mask */
745 false), /* pcrel_offset */
747 /* High 16 bits of symbol value. */
748 HOWTO (R_MIPS_HI16
, /* type */
750 2, /* size (0 = byte, 1 = short, 2 = long) */
752 false, /* pc_relative */
754 complain_overflow_dont
, /* complain_on_overflow */
755 bfd_elf_generic_reloc
, /* special_function */
756 "R_MIPS_HI16", /* name */
757 true, /* partial_inplace */
759 0xffff, /* dst_mask */
760 false), /* pcrel_offset */
762 /* Low 16 bits of symbol value. */
763 HOWTO (R_MIPS_LO16
, /* type */
765 2, /* size (0 = byte, 1 = short, 2 = long) */
767 false, /* pc_relative */
769 complain_overflow_dont
, /* complain_on_overflow */
770 bfd_elf_generic_reloc
, /* special_function */
771 "R_MIPS_LO16", /* name */
772 true, /* partial_inplace */
774 0xffff, /* dst_mask */
775 false), /* pcrel_offset */
777 /* GP relative reference. */
778 HOWTO (R_MIPS_GPREL16
, /* type */
780 2, /* size (0 = byte, 1 = short, 2 = long) */
782 false, /* pc_relative */
784 complain_overflow_signed
, /* complain_on_overflow */
785 mips_elf_gprel16_reloc
, /* special_function */
786 "R_MIPS_GPREL16", /* name */
787 true, /* partial_inplace */
789 0xffff, /* dst_mask */
790 false), /* pcrel_offset */
792 /* Reference to literal section. */
793 HOWTO (R_MIPS_LITERAL
, /* type */
795 2, /* size (0 = byte, 1 = short, 2 = long) */
797 false, /* pc_relative */
799 complain_overflow_signed
, /* complain_on_overflow */
800 mips_elf_gprel16_reloc
, /* special_function */
801 "R_MIPS_LITERAL", /* name */
802 true, /* partial_inplace */
804 0xffff, /* dst_mask */
805 false), /* pcrel_offset */
807 /* Reference to global offset table. */
808 HOWTO (R_MIPS_GOT16
, /* type */
810 2, /* size (0 = byte, 1 = short, 2 = long) */
812 false, /* pc_relative */
814 complain_overflow_signed
, /* complain_on_overflow */
815 mips_elf_got16_reloc
, /* special_function */
816 "R_MIPS_GOT16", /* name */
817 false, /* partial_inplace */
819 0xffff, /* dst_mask */
820 false), /* pcrel_offset */
822 /* 16 bit PC relative reference. */
823 HOWTO (R_MIPS_PC16
, /* type */
825 2, /* size (0 = byte, 1 = short, 2 = long) */
827 true, /* pc_relative */
829 complain_overflow_signed
, /* complain_on_overflow */
830 bfd_elf_generic_reloc
, /* special_function */
831 "R_MIPS_PC16", /* name */
832 true, /* partial_inplace */
834 0xffff, /* dst_mask */
835 false), /* pcrel_offset */
837 /* 16 bit call through global offset table. */
838 /* FIXME: This is not handled correctly. */
839 HOWTO (R_MIPS_CALL16
, /* type */
841 2, /* size (0 = byte, 1 = short, 2 = long) */
843 false, /* pc_relative */
845 complain_overflow_signed
, /* complain_on_overflow */
846 bfd_elf_generic_reloc
, /* special_function */
847 "R_MIPS_CALL16", /* name */
848 false, /* partial_inplace */
850 0xffff, /* dst_mask */
851 false), /* pcrel_offset */
853 /* 32 bit GP relative reference. */
854 HOWTO (R_MIPS_GPREL32
, /* type */
856 2, /* size (0 = byte, 1 = short, 2 = long) */
858 false, /* pc_relative */
860 complain_overflow_bitfield
, /* complain_on_overflow */
861 mips_elf_gprel32_reloc
, /* special_function */
862 "R_MIPS_GPREL32", /* name */
863 true, /* partial_inplace */
865 0xffffffff, /* dst_mask */
866 false), /* pcrel_offset */
872 /* A 5 bit shift field. */
873 HOWTO (R_MIPS_SHIFT5
, /* type */
875 2, /* size (0 = byte, 1 = short, 2 = long) */
877 false, /* pc_relative */
879 complain_overflow_bitfield
, /* complain_on_overflow */
880 bfd_elf_generic_reloc
, /* special_function */
881 "R_MIPS_SHIFT5", /* name */
882 true, /* partial_inplace */
884 0x000007c0, /* dst_mask */
885 false), /* pcrel_offset */
887 /* A 6 bit shift field. */
888 /* FIXME: This is not handled correctly; a special function is
889 needed to put the most significant bit in the right place. */
890 HOWTO (R_MIPS_SHIFT6
, /* type */
892 2, /* size (0 = byte, 1 = short, 2 = long) */
894 false, /* pc_relative */
896 complain_overflow_bitfield
, /* complain_on_overflow */
897 bfd_elf_generic_reloc
, /* special_function */
898 "R_MIPS_SHIFT6", /* name */
899 true, /* partial_inplace */
901 0x000007c4, /* dst_mask */
902 false), /* pcrel_offset */
904 /* 64 bit relocation. */
905 HOWTO (R_MIPS_64
, /* type */
907 4, /* size (0 = byte, 1 = short, 2 = long) */
909 false, /* pc_relative */
911 complain_overflow_bitfield
, /* complain_on_overflow */
912 bfd_elf_generic_reloc
, /* special_function */
913 "R_MIPS_64", /* name */
914 true, /* partial_inplace */
916 MINUS_ONE
, /* dst_mask */
917 false), /* pcrel_offset */
919 /* Displacement in the global offset table. */
920 /* FIXME: Not handled correctly. */
921 HOWTO (R_MIPS_GOT_DISP
, /* type */
923 2, /* size (0 = byte, 1 = short, 2 = long) */
925 false, /* pc_relative */
927 complain_overflow_bitfield
, /* complain_on_overflow */
928 bfd_elf_generic_reloc
, /* special_function */
929 "R_MIPS_GOT_DISP", /* name */
930 true, /* partial_inplace */
932 0x0000ffff, /* dst_mask */
933 false), /* pcrel_offset */
935 /* Displacement to page pointer in the global offset table. */
936 /* FIXME: Not handled correctly. */
937 HOWTO (R_MIPS_GOT_PAGE
, /* type */
939 2, /* size (0 = byte, 1 = short, 2 = long) */
941 false, /* pc_relative */
943 complain_overflow_bitfield
, /* complain_on_overflow */
944 bfd_elf_generic_reloc
, /* special_function */
945 "R_MIPS_GOT_PAGE", /* name */
946 true, /* partial_inplace */
948 0x0000ffff, /* dst_mask */
949 false), /* pcrel_offset */
951 /* Offset from page pointer in the global offset table. */
952 /* FIXME: Not handled correctly. */
953 HOWTO (R_MIPS_GOT_OFST
, /* type */
955 2, /* size (0 = byte, 1 = short, 2 = long) */
957 false, /* pc_relative */
959 complain_overflow_bitfield
, /* complain_on_overflow */
960 bfd_elf_generic_reloc
, /* special_function */
961 "R_MIPS_GOT_OFST", /* name */
962 true, /* partial_inplace */
964 0x0000ffff, /* dst_mask */
965 false), /* pcrel_offset */
967 /* High 16 bits of displacement in global offset table. */
968 /* FIXME: Not handled correctly. */
969 HOWTO (R_MIPS_GOT_HI16
, /* 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_GOT_HI16", /* name */
978 true, /* partial_inplace */
980 0x0000ffff, /* dst_mask */
981 false), /* pcrel_offset */
983 /* Low 16 bits of displacement in global offset table. */
984 /* FIXME: Not handled correctly. */
985 HOWTO (R_MIPS_GOT_LO16
, /* type */
987 2, /* size (0 = byte, 1 = short, 2 = long) */
989 false, /* pc_relative */
991 complain_overflow_dont
, /* complain_on_overflow */
992 bfd_elf_generic_reloc
, /* special_function */
993 "R_MIPS_GOT_LO16", /* name */
994 true, /* partial_inplace */
996 0x0000ffff, /* dst_mask */
997 false), /* pcrel_offset */
999 /* 64 bit substraction. */
1000 /* FIXME: Not handled correctly. */
1001 HOWTO (R_MIPS_SUB
, /* type */
1003 4, /* size (0 = byte, 1 = short, 2 = long) */
1005 false, /* pc_relative */
1007 complain_overflow_bitfield
, /* complain_on_overflow */
1008 bfd_elf_generic_reloc
, /* special_function */
1009 "R_MIPS_SUB", /* name */
1010 true, /* partial_inplace */
1012 MINUS_ONE
, /* dst_mask */
1013 false), /* pcrel_offset */
1015 /* Insert the addend as an instruction. */
1016 /* FIXME: Not handled correctly. */
1017 HOWTO (R_MIPS_INSERT_A
, /* type */
1019 0, /* 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_INSERT_A", /* name */
1026 false, /* partial_inplace */
1029 false), /* pcrel_offset */
1031 /* Insert the addend as an instruction, and change all relocations
1032 to refer to the old instruction at the address. */
1033 /* FIXME: Not handled correctly. */
1034 HOWTO (R_MIPS_INSERT_B
, /* type */
1036 0, /* size (0 = byte, 1 = short, 2 = long) */
1038 false, /* pc_relative */
1040 complain_overflow_dont
, /* complain_on_overflow */
1041 bfd_elf_generic_reloc
, /* special_function */
1042 "R_MIPS_INSERT_B", /* name */
1043 false, /* partial_inplace */
1046 false), /* pcrel_offset */
1048 /* Delete a 32 bit instruction. */
1049 /* FIXME: Not handled correctly. */
1050 HOWTO (R_MIPS_DELETE
, /* type */
1052 0, /* size (0 = byte, 1 = short, 2 = long) */
1054 false, /* pc_relative */
1056 complain_overflow_dont
, /* complain_on_overflow */
1057 bfd_elf_generic_reloc
, /* special_function */
1058 "R_MIPS_DELETE", /* name */
1059 false, /* partial_inplace */
1062 false), /* pcrel_offset */
1064 /* Get the higher value of a 64 bit addend. */
1065 /* FIXME: Not handled correctly. */
1066 HOWTO (R_MIPS_HIGHER
, /* type */
1068 2, /* size (0 = byte, 1 = short, 2 = long) */
1070 false, /* pc_relative */
1072 complain_overflow_dont
, /* complain_on_overflow */
1073 bfd_elf_generic_reloc
, /* special_function */
1074 "R_MIPS_HIGHER", /* name */
1075 true, /* partial_inplace */
1077 0xffff, /* dst_mask */
1078 false), /* pcrel_offset */
1080 /* Get the highest value of a 64 bit addend. */
1081 /* FIXME: Not handled correctly. */
1082 HOWTO (R_MIPS_HIGHEST
, /* type */
1084 2, /* size (0 = byte, 1 = short, 2 = long) */
1086 false, /* pc_relative */
1088 complain_overflow_dont
, /* complain_on_overflow */
1089 bfd_elf_generic_reloc
, /* special_function */
1090 "R_MIPS_HIGHEST", /* name */
1091 true, /* partial_inplace */
1093 0xffff, /* dst_mask */
1094 false), /* pcrel_offset */
1096 /* High 16 bits of displacement in global offset table. */
1097 /* FIXME: Not handled correctly. */
1098 HOWTO (R_MIPS_CALL_HI16
, /* type */
1100 2, /* size (0 = byte, 1 = short, 2 = long) */
1102 false, /* pc_relative */
1104 complain_overflow_dont
, /* complain_on_overflow */
1105 bfd_elf_generic_reloc
, /* special_function */
1106 "R_MIPS_CALL_HI16", /* name */
1107 true, /* partial_inplace */
1109 0x0000ffff, /* dst_mask */
1110 false), /* pcrel_offset */
1112 /* Low 16 bits of displacement in global offset table. */
1113 /* FIXME: Not handled correctly. */
1114 HOWTO (R_MIPS_CALL_LO16
, /* type */
1116 2, /* size (0 = byte, 1 = short, 2 = long) */
1118 false, /* pc_relative */
1120 complain_overflow_dont
, /* complain_on_overflow */
1121 bfd_elf_generic_reloc
, /* special_function */
1122 "R_MIPS_CALL_LO16", /* name */
1123 true, /* partial_inplace */
1125 0x0000ffff, /* dst_mask */
1126 false), /* pcrel_offset */
1128 /* I'm not sure what the remaining relocs are, but they are defined
1131 HOWTO (R_MIPS_SCN_DISP
, /* type */
1133 0, /* size (0 = byte, 1 = short, 2 = long) */
1135 false, /* pc_relative */
1137 complain_overflow_dont
, /* complain_on_overflow */
1138 bfd_elf_generic_reloc
, /* special_function */
1139 "R_MIPS_SCN_DISP", /* name */
1140 false, /* partial_inplace */
1143 false), /* pcrel_offset */
1145 HOWTO (R_MIPS_REL16
, /* type */
1147 0, /* size (0 = byte, 1 = short, 2 = long) */
1149 false, /* pc_relative */
1151 complain_overflow_dont
, /* complain_on_overflow */
1152 bfd_elf_generic_reloc
, /* special_function */
1153 "R_MIPS_REL16", /* name */
1154 false, /* partial_inplace */
1157 false), /* pcrel_offset */
1159 HOWTO (R_MIPS_ADD_IMMEDIATE
, /* type */
1161 0, /* size (0 = byte, 1 = short, 2 = long) */
1163 false, /* pc_relative */
1165 complain_overflow_dont
, /* complain_on_overflow */
1166 bfd_elf_generic_reloc
, /* special_function */
1167 "R_MIPS_ADD_IMMEDIATE", /* name */
1168 false, /* partial_inplace */
1171 false), /* pcrel_offset */
1173 HOWTO (R_MIPS_PJUMP
, /* type */
1175 0, /* size (0 = byte, 1 = short, 2 = long) */
1177 false, /* pc_relative */
1179 complain_overflow_dont
, /* complain_on_overflow */
1180 bfd_elf_generic_reloc
, /* special_function */
1181 "R_MIPS_PJUMP", /* name */
1182 false, /* partial_inplace */
1185 false), /* pcrel_offset */
1187 HOWTO (R_MIPS_RELGOT
, /* type */
1189 0, /* size (0 = byte, 1 = short, 2 = long) */
1191 false, /* pc_relative */
1193 complain_overflow_dont
, /* complain_on_overflow */
1194 bfd_elf_generic_reloc
, /* special_function */
1195 "R_MIPS_RELGOT", /* name */
1196 false, /* partial_inplace */
1199 false) /* pcrel_offset */
1202 /* Swap in a MIPS 64-bit Rel reloc. */
1205 mips_elf64_swap_reloc_in (abfd
, src
, dst
)
1207 const Elf64_Mips_External_Rel
*src
;
1208 Elf64_Mips_Internal_Rel
*dst
;
1210 dst
->r_offset
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_offset
);
1211 dst
->r_sym
= bfd_h_get_32 (abfd
, (bfd_byte
*) src
->r_sym
);
1212 dst
->r_ssym
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_ssym
);
1213 dst
->r_type3
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type3
);
1214 dst
->r_type2
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type2
);
1215 dst
->r_type
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type
);
1218 /* Swap in a MIPS 64-bit Rela reloc. */
1221 mips_elf64_swap_reloca_in (abfd
, src
, dst
)
1223 const Elf64_Mips_External_Rela
*src
;
1224 Elf64_Mips_Internal_Rela
*dst
;
1226 dst
->r_offset
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_offset
);
1227 dst
->r_sym
= bfd_h_get_32 (abfd
, (bfd_byte
*) src
->r_sym
);
1228 dst
->r_ssym
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_ssym
);
1229 dst
->r_type3
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type3
);
1230 dst
->r_type2
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type2
);
1231 dst
->r_type
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type
);
1232 dst
->r_addend
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_addend
);
1237 /* This is not currently used. */
1239 /* Swap out a MIPS 64-bit Rel reloc. */
1242 mips_elf64_swap_reloc_out (abfd
, src
, dst
)
1244 const Elf64_Mips_Internal_Rel
*src
;
1245 Elf64_Mips_External_Rel
*dst
;
1247 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1248 bfd_h_put_32 (abfd
, src
->r_sym
, (bfd_byte
*) dst
->r_sym
);
1249 bfd_h_put_8 (abfd
, src
->r_ssym
, (bfd_byte
*) dst
->r_ssym
);
1250 bfd_h_put_8 (abfd
, src
->r_type3
, (bfd_byte
*) dst
->r_type3
);
1251 bfd_h_put_8 (abfd
, src
->r_type2
, (bfd_byte
*) dst
->r_type2
);
1252 bfd_h_put_8 (abfd
, src
->r_type
, (bfd_byte
*) dst
->r_type
);
1257 /* Swap out a MIPS 64-bit Rela reloc. */
1260 mips_elf64_swap_reloca_out (abfd
, src
, dst
)
1262 const Elf64_Mips_Internal_Rela
*src
;
1263 Elf64_Mips_External_Rela
*dst
;
1265 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1266 bfd_h_put_32 (abfd
, src
->r_sym
, (bfd_byte
*) dst
->r_sym
);
1267 bfd_h_put_8 (abfd
, src
->r_ssym
, (bfd_byte
*) dst
->r_ssym
);
1268 bfd_h_put_8 (abfd
, src
->r_type3
, (bfd_byte
*) dst
->r_type3
);
1269 bfd_h_put_8 (abfd
, src
->r_type2
, (bfd_byte
*) dst
->r_type2
);
1270 bfd_h_put_8 (abfd
, src
->r_type
, (bfd_byte
*) dst
->r_type
);
1271 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1274 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1276 struct elf_reloc_map
1278 bfd_reloc_code_real_type bfd_reloc_val
;
1279 enum mips_elf64_reloc_type elf_reloc_val
;
1282 static CONST
struct elf_reloc_map mips_reloc_map
[] =
1284 { BFD_RELOC_NONE
, R_MIPS_NONE
, },
1285 { BFD_RELOC_16
, R_MIPS_16
},
1286 { BFD_RELOC_32
, R_MIPS_32
},
1287 { BFD_RELOC_64
, R_MIPS_64
},
1288 { BFD_RELOC_CTOR
, R_MIPS_64
},
1289 { BFD_RELOC_32_PCREL
, R_MIPS_REL32
},
1290 { BFD_RELOC_MIPS_JMP
, R_MIPS_26
},
1291 { BFD_RELOC_HI16_S
, R_MIPS_HI16
},
1292 { BFD_RELOC_LO16
, R_MIPS_LO16
},
1293 { BFD_RELOC_MIPS_GPREL
, R_MIPS_GPREL16
},
1294 { BFD_RELOC_MIPS_LITERAL
, R_MIPS_LITERAL
},
1295 { BFD_RELOC_MIPS_GOT16
, R_MIPS_GOT16
},
1296 { BFD_RELOC_16_PCREL
, R_MIPS_PC16
},
1297 { BFD_RELOC_MIPS_CALL16
, R_MIPS_CALL16
},
1298 { BFD_RELOC_MIPS_GPREL32
, R_MIPS_GPREL32
},
1299 { BFD_RELOC_MIPS_GOT_HI16
, R_MIPS_GOT_HI16
},
1300 { BFD_RELOC_MIPS_GOT_LO16
, R_MIPS_GOT_LO16
},
1301 { BFD_RELOC_MIPS_CALL_HI16
, R_MIPS_CALL_HI16
},
1302 { BFD_RELOC_MIPS_CALL_LO16
, R_MIPS_CALL_LO16
}
1305 /* Given a BFD reloc type, return a howto structure. */
1307 static reloc_howto_type
*
1308 mips_elf64_reloc_type_lookup (abfd
, code
)
1310 bfd_reloc_code_real_type code
;
1314 for (i
= 0; i
< sizeof (mips_reloc_map
) / sizeof (struct elf_reloc_map
); i
++)
1316 if (mips_reloc_map
[i
].bfd_reloc_val
== code
)
1320 v
= (int) mips_reloc_map
[i
].elf_reloc_val
;
1321 return &mips_elf64_howto_table_rel
[v
];
1328 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1329 to three relocs, we must tell the user to allocate more space. */
1332 mips_elf64_get_reloc_upper_bound (abfd
, sec
)
1336 return (sec
->reloc_count
* 3 + 1) * sizeof (arelent
*);
1339 /* Read the relocations from one reloc section. */
1342 mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
, rel_hdr
)
1346 const Elf_Internal_Shdr
*rel_hdr
;
1348 PTR allocated
= NULL
;
1349 bfd_byte
*native_relocs
;
1355 reloc_howto_type
*howto_table
;
1357 allocated
= (PTR
) bfd_malloc (rel_hdr
->sh_size
);
1358 if (allocated
== NULL
)
1361 if (bfd_seek (abfd
, rel_hdr
->sh_offset
, SEEK_SET
) != 0
1362 || (bfd_read (allocated
, 1, rel_hdr
->sh_size
, abfd
) != rel_hdr
->sh_size
))
1365 native_relocs
= (bfd_byte
*) allocated
;
1367 relents
= asect
->relocation
+ asect
->reloc_count
;
1369 entsize
= rel_hdr
->sh_entsize
;
1370 BFD_ASSERT (entsize
== sizeof (Elf64_Mips_External_Rel
)
1371 || entsize
== sizeof (Elf64_Mips_External_Rela
));
1373 count
= rel_hdr
->sh_size
/ entsize
;
1375 if (entsize
== sizeof (Elf64_Mips_External_Rel
))
1376 howto_table
= mips_elf64_howto_table_rel
;
1378 howto_table
= mips_elf64_howto_table_rela
;
1381 for (i
= 0; i
< count
; i
++, native_relocs
+= entsize
)
1383 Elf64_Mips_Internal_Rela rela
;
1384 boolean used_sym
, used_ssym
;
1387 if (entsize
== sizeof (Elf64_Mips_External_Rela
))
1388 mips_elf64_swap_reloca_in (abfd
,
1389 (Elf64_Mips_External_Rela
*) native_relocs
,
1393 Elf64_Mips_Internal_Rel rel
;
1395 mips_elf64_swap_reloc_in (abfd
,
1396 (Elf64_Mips_External_Rel
*) native_relocs
,
1398 rela
.r_offset
= rel
.r_offset
;
1399 rela
.r_sym
= rel
.r_sym
;
1400 rela
.r_ssym
= rel
.r_ssym
;
1401 rela
.r_type3
= rel
.r_type3
;
1402 rela
.r_type2
= rel
.r_type2
;
1403 rela
.r_type
= rel
.r_type
;
1407 /* Each entry represents up to three actual relocations. */
1411 for (ir
= 0; ir
< 3; ir
++)
1413 enum mips_elf64_reloc_type type
;
1420 type
= (enum mips_elf64_reloc_type
) rela
.r_type
;
1423 type
= (enum mips_elf64_reloc_type
) rela
.r_type2
;
1426 type
= (enum mips_elf64_reloc_type
) rela
.r_type3
;
1430 if (type
== R_MIPS_NONE
)
1432 /* There are no more relocations in this entry. If this
1433 is the first entry, we need to generate a dummy
1434 relocation so that the generic linker knows that
1435 there has been a break in the sequence of relocations
1436 applying to a particular address. */
1439 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1440 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1441 relent
->address
= rela
.r_offset
;
1443 relent
->address
= rela
.r_offset
- asect
->vma
;
1445 relent
->howto
= &howto_table
[(int) R_MIPS_NONE
];
1451 /* Some types require symbols, whereas some do not. */
1455 case R_MIPS_LITERAL
:
1456 case R_MIPS_INSERT_A
:
1457 case R_MIPS_INSERT_B
:
1459 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1465 if (rela
.r_sym
== 0)
1466 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1471 ps
= symbols
+ rela
.r_sym
- 1;
1473 if ((s
->flags
& BSF_SECTION_SYM
) == 0)
1474 relent
->sym_ptr_ptr
= ps
;
1476 relent
->sym_ptr_ptr
= s
->section
->symbol_ptr_ptr
;
1481 else if (! used_ssym
)
1483 switch (rela
.r_ssym
)
1486 relent
->sym_ptr_ptr
=
1487 bfd_abs_section_ptr
->symbol_ptr_ptr
;
1493 /* FIXME: I think these need to be handled using
1494 special howto structures. */
1506 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1511 /* The address of an ELF reloc is section relative for an
1512 object file, and absolute for an executable file or
1513 shared library. The address of a BFD reloc is always
1514 section relative. */
1515 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1516 relent
->address
= rela
.r_offset
;
1518 relent
->address
= rela
.r_offset
- asect
->vma
;
1520 relent
->addend
= rela
.r_addend
;
1522 relent
->howto
= &howto_table
[(int) type
];
1528 asect
->reloc_count
+= relent
- relents
;
1530 if (allocated
!= NULL
)
1536 if (allocated
!= NULL
)
1541 /* Read the relocations. On Irix 6, there can be two reloc sections
1542 associated with a single data section. */
1545 mips_elf64_slurp_reloc_table (abfd
, asect
, symbols
)
1550 struct bfd_elf_section_data
* const d
= elf_section_data (asect
);
1552 if (asect
->relocation
!= NULL
1553 || (asect
->flags
& SEC_RELOC
) == 0
1554 || asect
->reloc_count
== 0)
1557 /* Allocate space for 3 arelent structures for each Rel structure. */
1558 asect
->relocation
= ((arelent
*)
1560 asect
->reloc_count
* 3 * sizeof (arelent
)));
1561 if (asect
->relocation
== NULL
)
1564 /* The slurp_one_reloc_table routine increments reloc_count. */
1565 asect
->reloc_count
= 0;
1567 if (! mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
, &d
->rel_hdr
))
1569 if (d
->rel_hdr2
!= NULL
)
1571 if (! mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
,
1579 /* Write out the relocations. */
1582 mips_elf64_write_relocs (abfd
, sec
, data
)
1587 boolean
*failedp
= (boolean
*) data
;
1589 Elf_Internal_Shdr
*rela_hdr
;
1590 Elf64_Mips_External_Rela
*ext_rela
;
1592 asymbol
*last_sym
= 0;
1593 int last_sym_idx
= 0;
1595 /* If we have already failed, don't do anything. */
1599 if ((sec
->flags
& SEC_RELOC
) == 0)
1602 /* The linker backend writes the relocs out itself, and sets the
1603 reloc_count field to zero to inhibit writing them here. Also,
1604 sometimes the SEC_RELOC flag gets set even when there aren't any
1606 if (sec
->reloc_count
== 0)
1609 /* We can combine up to three relocs that refer to the same address
1610 if the latter relocs have no associated symbol. */
1612 for (idx
= 0; idx
< sec
->reloc_count
; idx
++)
1619 addr
= sec
->orelocation
[idx
]->address
;
1620 for (i
= 0; i
< 2; i
++)
1624 if (idx
+ 1 >= sec
->reloc_count
)
1626 r
= sec
->orelocation
[idx
+ 1];
1627 if (r
->address
!= addr
1628 || ! bfd_is_abs_section ((*r
->sym_ptr_ptr
)->section
)
1629 || (*r
->sym_ptr_ptr
)->value
!= 0)
1632 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1638 rela_hdr
= &elf_section_data (sec
)->rel_hdr
;
1640 rela_hdr
->sh_size
= rela_hdr
->sh_entsize
* count
;
1641 rela_hdr
->contents
= (PTR
) bfd_alloc (abfd
, rela_hdr
->sh_size
);
1642 if (rela_hdr
->contents
== NULL
)
1648 ext_rela
= (Elf64_Mips_External_Rela
*) rela_hdr
->contents
;
1649 for (idx
= 0; idx
< sec
->reloc_count
; idx
++, ext_rela
++)
1652 Elf64_Mips_Internal_Rela int_rela
;
1657 ptr
= sec
->orelocation
[idx
];
1659 /* The address of an ELF reloc is section relative for an object
1660 file, and absolute for an executable file or shared library.
1661 The address of a BFD reloc is always section relative. */
1662 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1663 int_rela
.r_offset
= ptr
->address
;
1665 int_rela
.r_offset
= ptr
->address
+ sec
->vma
;
1667 sym
= *ptr
->sym_ptr_ptr
;
1668 if (sym
== last_sym
)
1673 n
= _bfd_elf_symbol_from_bfd_symbol (abfd
, &sym
);
1684 int_rela
.r_addend
= ptr
->addend
;
1686 int_rela
.r_ssym
= RSS_UNDEF
;
1688 if ((*ptr
->sym_ptr_ptr
)->the_bfd
->xvec
!= abfd
->xvec
1689 && ! _bfd_elf_validate_reloc (abfd
, ptr
))
1695 int_rela
.r_type
= ptr
->howto
->type
;
1696 int_rela
.r_type2
= (int) R_MIPS_NONE
;
1697 int_rela
.r_type3
= (int) R_MIPS_NONE
;
1699 for (i
= 0; i
< 2; i
++)
1703 if (idx
+ 1 >= sec
->reloc_count
)
1705 r
= sec
->orelocation
[idx
+ 1];
1706 if (r
->address
!= ptr
->address
1707 || ! bfd_is_abs_section ((*r
->sym_ptr_ptr
)->section
)
1708 || (*r
->sym_ptr_ptr
)->value
!= 0)
1711 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1714 int_rela
.r_type2
= r
->howto
->type
;
1716 int_rela
.r_type3
= r
->howto
->type
;
1721 mips_elf64_swap_reloca_out (abfd
, &int_rela
, ext_rela
);
1724 BFD_ASSERT (ext_rela
- (Elf64_Mips_External_Rela
*) rela_hdr
->contents
1728 /* Handle a 64-bit MIPS ELF specific section. */
1731 mips_elf64_section_from_shdr (abfd
, hdr
, name
)
1733 Elf_Internal_Shdr
*hdr
;
1736 if (! _bfd_mips_elf_section_from_shdr (abfd
, hdr
, name
))
1742 /* ECOFF swapping routines. These are used when dealing with the
1743 .mdebug section, which is in the ECOFF debugging format. */
1744 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap
=
1746 /* Symbol table magic number. */
1748 /* Alignment of debugging information. E.g., 4. */
1750 /* Sizes of external symbolic information. */
1751 sizeof (struct hdr_ext
),
1752 sizeof (struct dnr_ext
),
1753 sizeof (struct pdr_ext
),
1754 sizeof (struct sym_ext
),
1755 sizeof (struct opt_ext
),
1756 sizeof (struct fdr_ext
),
1757 sizeof (struct rfd_ext
),
1758 sizeof (struct ext_ext
),
1759 /* Functions to swap in external symbolic data. */
1768 _bfd_ecoff_swap_tir_in
,
1769 _bfd_ecoff_swap_rndx_in
,
1770 /* Functions to swap out external symbolic data. */
1779 _bfd_ecoff_swap_tir_out
,
1780 _bfd_ecoff_swap_rndx_out
,
1781 /* Function to read in symbolic data. */
1782 _bfd_mips_elf_read_ecoff_info
1785 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
1786 standard ELF. This structure is used to redirect the relocation
1787 handling routines. */
1789 const struct elf_size_info mips_elf64_size_info
=
1791 sizeof (Elf64_External_Ehdr
),
1792 sizeof (Elf64_External_Phdr
),
1793 sizeof (Elf64_External_Shdr
),
1794 sizeof (Elf64_Mips_External_Rel
),
1795 sizeof (Elf64_Mips_External_Rela
),
1796 sizeof (Elf64_External_Sym
),
1797 sizeof (Elf64_External_Dyn
),
1798 sizeof (Elf_External_Note
),
1803 bfd_elf64_write_out_phdrs
,
1804 bfd_elf64_write_shdrs_and_ehdr
,
1805 mips_elf64_write_relocs
,
1806 bfd_elf64_swap_symbol_out
,
1807 mips_elf64_slurp_reloc_table
,
1808 bfd_elf64_slurp_symbol_table
,
1809 bfd_elf64_swap_dyn_in
1812 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
1813 #define TARGET_LITTLE_NAME "elf64-littlemips"
1814 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
1815 #define TARGET_BIG_NAME "elf64-bigmips"
1816 #define ELF_ARCH bfd_arch_mips
1817 #define ELF_MACHINE_CODE EM_MIPS
1818 #define ELF_MAXPAGESIZE 0x1000
1819 #define elf_backend_size_info mips_elf64_size_info
1820 #define elf_backend_object_p _bfd_mips_elf_object_p
1821 #define elf_backend_section_from_shdr mips_elf64_section_from_shdr
1822 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
1823 #define elf_backend_section_from_bfd_section \
1824 _bfd_mips_elf_section_from_bfd_section
1825 #define elf_backend_section_processing _bfd_mips_elf_section_processing
1826 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
1827 #define elf_backend_final_write_processing \
1828 _bfd_mips_elf_final_write_processing
1829 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
1831 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
1832 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
1834 #include "elf64-target.h"