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.
27 The MIPS 64-bit ELF ABI also uses an unusual archive map format. */
38 /* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
39 use ECOFF. However, we support it anyhow for an easier changeover. */
41 #include "coff/symconst.h"
42 #include "coff/internal.h"
43 #include "coff/ecoff.h"
44 /* The 64 bit versions of the mdebug data structures are in alpha.h. */
45 #include "coff/alpha.h"
47 #include "ecoffswap.h"
49 static void mips_elf64_swap_reloc_in
50 PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
51 Elf64_Mips_Internal_Rel *));
52 static void mips_elf64_swap_reloca_in
53 PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
54 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 *));
60 static void mips_elf64_swap_reloca_out
61 PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
62 Elf64_Mips_External_Rela *));
63 static reloc_howto_type *mips_elf64_reloc_type_lookup
64 PARAMS ((bfd *, bfd_reloc_code_real_type));
65 static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
66 static boolean mips_elf64_slurp_one_reloc_table
67 PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
68 static boolean mips_elf64_slurp_reloc_table
69 PARAMS ((bfd *, asection *, asymbol **));
70 static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
71 static boolean mips_elf64_section_from_shdr
72 PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
73 static boolean mips_elf64_section_processing
74 PARAMS ((bfd *, Elf_Internal_Shdr *));
75 static boolean mips_elf64_slurp_armap PARAMS ((bfd *));
76 static boolean mips_elf64_write_armap
77 PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
79 /* The relocation types. */
81 enum mips_elf64_reloc_type
104 R_MIPS_GOT_DISP = 19,
105 R_MIPS_GOT_PAGE = 20,
106 R_MIPS_GOT_OFST = 21,
107 R_MIPS_GOT_HI16 = 22,
108 R_MIPS_GOT_LO16 = 23,
110 R_MIPS_INSERT_A = 25,
111 R_MIPS_INSERT_B = 26,
115 R_MIPS_CALL_HI16 = 30,
116 R_MIPS_CALL_LO16 = 31,
117 R_MIPS_SCN_DISP = 32,
119 R_MIPS_ADD_IMMEDIATE = 34,
124 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
125 from smaller values. Start with zero, widen, *then* decrement. */
126 #define MINUS_ONE (((bfd_vma)0) - 1)
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 _bfd_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 _bfd_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 _bfd_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 _bfd_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 _bfd_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 _bfd_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 _bfd_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 _bfd_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 /* FIXME: This is not handled correctly. */
809 HOWTO (R_MIPS_GOT16, /* type */
811 2, /* size (0 = byte, 1 = short, 2 = long) */
813 false, /* pc_relative */
815 complain_overflow_signed, /* complain_on_overflow */
816 bfd_elf_generic_reloc, /* special_function */
817 "R_MIPS_GOT16", /* name */
818 false, /* partial_inplace */
820 0xffff, /* dst_mask */
821 false), /* pcrel_offset */
823 /* 16 bit PC relative reference. */
824 HOWTO (R_MIPS_PC16, /* type */
826 2, /* size (0 = byte, 1 = short, 2 = long) */
828 true, /* pc_relative */
830 complain_overflow_signed, /* complain_on_overflow */
831 bfd_elf_generic_reloc, /* special_function */
832 "R_MIPS_PC16", /* name */
833 true, /* partial_inplace */
835 0xffff, /* dst_mask */
836 false), /* pcrel_offset */
838 /* 16 bit call through global offset table. */
839 /* FIXME: This is not handled correctly. */
840 HOWTO (R_MIPS_CALL16, /* type */
842 2, /* size (0 = byte, 1 = short, 2 = long) */
844 false, /* pc_relative */
846 complain_overflow_signed, /* complain_on_overflow */
847 bfd_elf_generic_reloc, /* special_function */
848 "R_MIPS_CALL16", /* name */
849 false, /* partial_inplace */
851 0xffff, /* dst_mask */
852 false), /* pcrel_offset */
854 /* 32 bit GP relative reference. */
855 HOWTO (R_MIPS_GPREL32, /* type */
857 2, /* size (0 = byte, 1 = short, 2 = long) */
859 false, /* pc_relative */
861 complain_overflow_bitfield, /* complain_on_overflow */
862 _bfd_mips_elf_gprel32_reloc, /* special_function */
863 "R_MIPS_GPREL32", /* name */
864 true, /* partial_inplace */
866 0xffffffff, /* dst_mask */
867 false), /* pcrel_offset */
873 /* A 5 bit shift field. */
874 HOWTO (R_MIPS_SHIFT5, /* type */
876 2, /* size (0 = byte, 1 = short, 2 = long) */
878 false, /* pc_relative */
880 complain_overflow_bitfield, /* complain_on_overflow */
881 bfd_elf_generic_reloc, /* special_function */
882 "R_MIPS_SHIFT5", /* name */
883 true, /* partial_inplace */
885 0x000007c0, /* dst_mask */
886 false), /* pcrel_offset */
888 /* A 6 bit shift field. */
889 /* FIXME: This is not handled correctly; a special function is
890 needed to put the most significant bit in the right place. */
891 HOWTO (R_MIPS_SHIFT6, /* type */
893 2, /* size (0 = byte, 1 = short, 2 = long) */
895 false, /* pc_relative */
897 complain_overflow_bitfield, /* complain_on_overflow */
898 bfd_elf_generic_reloc, /* special_function */
899 "R_MIPS_SHIFT6", /* name */
900 true, /* partial_inplace */
902 0x000007c4, /* dst_mask */
903 false), /* pcrel_offset */
905 /* 64 bit relocation. */
906 HOWTO (R_MIPS_64, /* type */
908 4, /* size (0 = byte, 1 = short, 2 = long) */
910 false, /* pc_relative */
912 complain_overflow_bitfield, /* complain_on_overflow */
913 bfd_elf_generic_reloc, /* special_function */
914 "R_MIPS_64", /* name */
915 true, /* partial_inplace */
917 MINUS_ONE, /* dst_mask */
918 false), /* pcrel_offset */
920 /* Displacement in the global offset table. */
921 /* FIXME: Not handled correctly. */
922 HOWTO (R_MIPS_GOT_DISP, /* type */
924 2, /* size (0 = byte, 1 = short, 2 = long) */
926 false, /* pc_relative */
928 complain_overflow_bitfield, /* complain_on_overflow */
929 bfd_elf_generic_reloc, /* special_function */
930 "R_MIPS_GOT_DISP", /* name */
931 true, /* partial_inplace */
933 0x0000ffff, /* dst_mask */
934 false), /* pcrel_offset */
936 /* Displacement to page pointer in the global offset table. */
937 /* FIXME: Not handled correctly. */
938 HOWTO (R_MIPS_GOT_PAGE, /* type */
940 2, /* size (0 = byte, 1 = short, 2 = long) */
942 false, /* pc_relative */
944 complain_overflow_bitfield, /* complain_on_overflow */
945 bfd_elf_generic_reloc, /* special_function */
946 "R_MIPS_GOT_PAGE", /* name */
947 true, /* partial_inplace */
949 0x0000ffff, /* dst_mask */
950 false), /* pcrel_offset */
952 /* Offset from page pointer in the global offset table. */
953 /* FIXME: Not handled correctly. */
954 HOWTO (R_MIPS_GOT_OFST, /* type */
956 2, /* size (0 = byte, 1 = short, 2 = long) */
958 false, /* pc_relative */
960 complain_overflow_bitfield, /* complain_on_overflow */
961 bfd_elf_generic_reloc, /* special_function */
962 "R_MIPS_GOT_OFST", /* name */
963 true, /* partial_inplace */
965 0x0000ffff, /* dst_mask */
966 false), /* pcrel_offset */
968 /* High 16 bits of displacement in global offset table. */
969 /* FIXME: Not handled correctly. */
970 HOWTO (R_MIPS_GOT_HI16, /* type */
972 2, /* size (0 = byte, 1 = short, 2 = long) */
974 false, /* pc_relative */
976 complain_overflow_dont, /* complain_on_overflow */
977 bfd_elf_generic_reloc, /* special_function */
978 "R_MIPS_GOT_HI16", /* name */
979 true, /* partial_inplace */
981 0x0000ffff, /* dst_mask */
982 false), /* pcrel_offset */
984 /* Low 16 bits of displacement in global offset table. */
985 /* FIXME: Not handled correctly. */
986 HOWTO (R_MIPS_GOT_LO16, /* 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_GOT_LO16", /* name */
995 true, /* partial_inplace */
997 0x0000ffff, /* dst_mask */
998 false), /* pcrel_offset */
1000 /* 64 bit substraction. */
1001 /* FIXME: Not handled correctly. */
1002 HOWTO (R_MIPS_SUB, /* type */
1004 4, /* size (0 = byte, 1 = short, 2 = long) */
1006 false, /* pc_relative */
1008 complain_overflow_bitfield, /* complain_on_overflow */
1009 bfd_elf_generic_reloc, /* special_function */
1010 "R_MIPS_SUB", /* name */
1011 true, /* partial_inplace */
1013 MINUS_ONE, /* dst_mask */
1014 false), /* pcrel_offset */
1016 /* Insert the addend as an instruction. */
1017 /* FIXME: Not handled correctly. */
1018 HOWTO (R_MIPS_INSERT_A, /* type */
1020 0, /* size (0 = byte, 1 = short, 2 = long) */
1022 false, /* pc_relative */
1024 complain_overflow_dont, /* complain_on_overflow */
1025 bfd_elf_generic_reloc, /* special_function */
1026 "R_MIPS_INSERT_A", /* name */
1027 false, /* partial_inplace */
1030 false), /* pcrel_offset */
1032 /* Insert the addend as an instruction, and change all relocations
1033 to refer to the old instruction at the address. */
1034 /* FIXME: Not handled correctly. */
1035 HOWTO (R_MIPS_INSERT_B, /* type */
1037 0, /* size (0 = byte, 1 = short, 2 = long) */
1039 false, /* pc_relative */
1041 complain_overflow_dont, /* complain_on_overflow */
1042 bfd_elf_generic_reloc, /* special_function */
1043 "R_MIPS_INSERT_B", /* name */
1044 false, /* partial_inplace */
1047 false), /* pcrel_offset */
1049 /* Delete a 32 bit instruction. */
1050 /* FIXME: Not handled correctly. */
1051 HOWTO (R_MIPS_DELETE, /* type */
1053 0, /* size (0 = byte, 1 = short, 2 = long) */
1055 false, /* pc_relative */
1057 complain_overflow_dont, /* complain_on_overflow */
1058 bfd_elf_generic_reloc, /* special_function */
1059 "R_MIPS_DELETE", /* name */
1060 false, /* partial_inplace */
1063 false), /* pcrel_offset */
1065 /* Get the higher value of a 64 bit addend. */
1066 /* FIXME: Not handled correctly. */
1067 HOWTO (R_MIPS_HIGHER, /* type */
1069 2, /* size (0 = byte, 1 = short, 2 = long) */
1071 false, /* pc_relative */
1073 complain_overflow_dont, /* complain_on_overflow */
1074 bfd_elf_generic_reloc, /* special_function */
1075 "R_MIPS_HIGHER", /* name */
1076 true, /* partial_inplace */
1078 0xffff, /* dst_mask */
1079 false), /* pcrel_offset */
1081 /* Get the highest value of a 64 bit addend. */
1082 /* FIXME: Not handled correctly. */
1083 HOWTO (R_MIPS_HIGHEST, /* type */
1085 2, /* size (0 = byte, 1 = short, 2 = long) */
1087 false, /* pc_relative */
1089 complain_overflow_dont, /* complain_on_overflow */
1090 bfd_elf_generic_reloc, /* special_function */
1091 "R_MIPS_HIGHEST", /* name */
1092 true, /* partial_inplace */
1094 0xffff, /* dst_mask */
1095 false), /* pcrel_offset */
1097 /* High 16 bits of displacement in global offset table. */
1098 /* FIXME: Not handled correctly. */
1099 HOWTO (R_MIPS_CALL_HI16, /* type */
1101 2, /* size (0 = byte, 1 = short, 2 = long) */
1103 false, /* pc_relative */
1105 complain_overflow_dont, /* complain_on_overflow */
1106 bfd_elf_generic_reloc, /* special_function */
1107 "R_MIPS_CALL_HI16", /* name */
1108 true, /* partial_inplace */
1110 0x0000ffff, /* dst_mask */
1111 false), /* pcrel_offset */
1113 /* Low 16 bits of displacement in global offset table. */
1114 /* FIXME: Not handled correctly. */
1115 HOWTO (R_MIPS_CALL_LO16, /* type */
1117 2, /* size (0 = byte, 1 = short, 2 = long) */
1119 false, /* pc_relative */
1121 complain_overflow_dont, /* complain_on_overflow */
1122 bfd_elf_generic_reloc, /* special_function */
1123 "R_MIPS_CALL_LO16", /* name */
1124 true, /* partial_inplace */
1126 0x0000ffff, /* dst_mask */
1127 false), /* pcrel_offset */
1129 /* I'm not sure what the remaining relocs are, but they are defined
1132 HOWTO (R_MIPS_SCN_DISP, /* type */
1134 0, /* size (0 = byte, 1 = short, 2 = long) */
1136 false, /* pc_relative */
1138 complain_overflow_dont, /* complain_on_overflow */
1139 bfd_elf_generic_reloc, /* special_function */
1140 "R_MIPS_SCN_DISP", /* name */
1141 false, /* partial_inplace */
1144 false), /* pcrel_offset */
1146 HOWTO (R_MIPS_REL16, /* type */
1148 0, /* size (0 = byte, 1 = short, 2 = long) */
1150 false, /* pc_relative */
1152 complain_overflow_dont, /* complain_on_overflow */
1153 bfd_elf_generic_reloc, /* special_function */
1154 "R_MIPS_REL16", /* name */
1155 false, /* partial_inplace */
1158 false), /* pcrel_offset */
1160 HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
1162 0, /* size (0 = byte, 1 = short, 2 = long) */
1164 false, /* pc_relative */
1166 complain_overflow_dont, /* complain_on_overflow */
1167 bfd_elf_generic_reloc, /* special_function */
1168 "R_MIPS_ADD_IMMEDIATE", /* name */
1169 false, /* partial_inplace */
1172 false), /* pcrel_offset */
1174 HOWTO (R_MIPS_PJUMP, /* type */
1176 0, /* size (0 = byte, 1 = short, 2 = long) */
1178 false, /* pc_relative */
1180 complain_overflow_dont, /* complain_on_overflow */
1181 bfd_elf_generic_reloc, /* special_function */
1182 "R_MIPS_PJUMP", /* name */
1183 false, /* partial_inplace */
1186 false), /* pcrel_offset */
1188 HOWTO (R_MIPS_RELGOT, /* type */
1190 0, /* size (0 = byte, 1 = short, 2 = long) */
1192 false, /* pc_relative */
1194 complain_overflow_dont, /* complain_on_overflow */
1195 bfd_elf_generic_reloc, /* special_function */
1196 "R_MIPS_RELGOT", /* name */
1197 false, /* partial_inplace */
1200 false) /* pcrel_offset */
1203 /* Swap in a MIPS 64-bit Rel reloc. */
1206 mips_elf64_swap_reloc_in (abfd, src, dst)
1208 const Elf64_Mips_External_Rel *src;
1209 Elf64_Mips_Internal_Rel *dst;
1211 dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
1212 dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
1213 dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
1214 dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
1215 dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
1216 dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
1219 /* Swap in a MIPS 64-bit Rela reloc. */
1222 mips_elf64_swap_reloca_in (abfd, src, dst)
1224 const Elf64_Mips_External_Rela *src;
1225 Elf64_Mips_Internal_Rela *dst;
1227 dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
1228 dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
1229 dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
1230 dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
1231 dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
1232 dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
1233 dst->r_addend = bfd_h_get_64 (abfd, (bfd_byte *) src->r_addend);
1238 /* This is not currently used. */
1240 /* Swap out a MIPS 64-bit Rel reloc. */
1243 mips_elf64_swap_reloc_out (abfd, src, dst)
1245 const Elf64_Mips_Internal_Rel *src;
1246 Elf64_Mips_External_Rel *dst;
1248 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1249 bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
1250 bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
1251 bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
1252 bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
1253 bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
1258 /* Swap out a MIPS 64-bit Rela reloc. */
1261 mips_elf64_swap_reloca_out (abfd, src, dst)
1263 const Elf64_Mips_Internal_Rela *src;
1264 Elf64_Mips_External_Rela *dst;
1266 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1267 bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
1268 bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
1269 bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
1270 bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
1271 bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
1272 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1275 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1277 struct elf_reloc_map
1279 bfd_reloc_code_real_type bfd_reloc_val;
1280 enum mips_elf64_reloc_type elf_reloc_val;
1283 static CONST struct elf_reloc_map mips_reloc_map[] =
1285 { BFD_RELOC_NONE, R_MIPS_NONE, },
1286 { BFD_RELOC_16, R_MIPS_16 },
1287 { BFD_RELOC_32, R_MIPS_32 },
1288 { BFD_RELOC_64, R_MIPS_64 },
1289 { BFD_RELOC_CTOR, R_MIPS_64 },
1290 { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
1291 { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
1292 { BFD_RELOC_HI16_S, R_MIPS_HI16 },
1293 { BFD_RELOC_LO16, R_MIPS_LO16 },
1294 { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 },
1295 { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
1296 { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
1297 { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
1298 { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
1299 { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 },
1300 { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
1301 { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
1302 { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
1303 { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }
1306 /* Given a BFD reloc type, return a howto structure. */
1308 static reloc_howto_type *
1309 mips_elf64_reloc_type_lookup (abfd, code)
1311 bfd_reloc_code_real_type code;
1315 for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
1317 if (mips_reloc_map[i].bfd_reloc_val == code)
1321 v = (int) mips_reloc_map[i].elf_reloc_val;
1322 return &mips_elf64_howto_table_rel[v];
1329 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1330 to three relocs, we must tell the user to allocate more space. */
1333 mips_elf64_get_reloc_upper_bound (abfd, sec)
1337 return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
1340 /* Read the relocations from one reloc section. */
1343 mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
1347 const Elf_Internal_Shdr *rel_hdr;
1349 PTR allocated = NULL;
1350 bfd_byte *native_relocs;
1356 reloc_howto_type *howto_table;
1358 allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
1359 if (allocated == NULL)
1362 if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
1363 || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
1366 native_relocs = (bfd_byte *) allocated;
1368 relents = asect->relocation + asect->reloc_count;
1370 entsize = rel_hdr->sh_entsize;
1371 BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
1372 || entsize == sizeof (Elf64_Mips_External_Rela));
1374 count = rel_hdr->sh_size / entsize;
1376 if (entsize == sizeof (Elf64_Mips_External_Rel))
1377 howto_table = mips_elf64_howto_table_rel;
1379 howto_table = mips_elf64_howto_table_rela;
1382 for (i = 0; i < count; i++, native_relocs += entsize)
1384 Elf64_Mips_Internal_Rela rela;
1385 boolean used_sym, used_ssym;
1388 if (entsize == sizeof (Elf64_Mips_External_Rela))
1389 mips_elf64_swap_reloca_in (abfd,
1390 (Elf64_Mips_External_Rela *) native_relocs,
1394 Elf64_Mips_Internal_Rel rel;
1396 mips_elf64_swap_reloc_in (abfd,
1397 (Elf64_Mips_External_Rel *) native_relocs,
1399 rela.r_offset = rel.r_offset;
1400 rela.r_sym = rel.r_sym;
1401 rela.r_ssym = rel.r_ssym;
1402 rela.r_type3 = rel.r_type3;
1403 rela.r_type2 = rel.r_type2;
1404 rela.r_type = rel.r_type;
1408 /* Each entry represents up to three actual relocations. */
1412 for (ir = 0; ir < 3; ir++)
1414 enum mips_elf64_reloc_type type;
1421 type = (enum mips_elf64_reloc_type) rela.r_type;
1424 type = (enum mips_elf64_reloc_type) rela.r_type2;
1427 type = (enum mips_elf64_reloc_type) rela.r_type3;
1431 if (type == R_MIPS_NONE)
1433 /* There are no more relocations in this entry. If this
1434 is the first entry, we need to generate a dummy
1435 relocation so that the generic linker knows that
1436 there has been a break in the sequence of relocations
1437 applying to a particular address. */
1440 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1441 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1442 relent->address = rela.r_offset;
1444 relent->address = rela.r_offset - asect->vma;
1446 relent->howto = &howto_table[(int) R_MIPS_NONE];
1452 /* Some types require symbols, whereas some do not. */
1456 case R_MIPS_LITERAL:
1457 case R_MIPS_INSERT_A:
1458 case R_MIPS_INSERT_B:
1460 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1466 if (rela.r_sym == 0)
1467 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1472 ps = symbols + rela.r_sym - 1;
1474 if ((s->flags & BSF_SECTION_SYM) == 0)
1475 relent->sym_ptr_ptr = ps;
1477 relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
1482 else if (! used_ssym)
1484 switch (rela.r_ssym)
1487 relent->sym_ptr_ptr =
1488 bfd_abs_section_ptr->symbol_ptr_ptr;
1494 /* FIXME: I think these need to be handled using
1495 special howto structures. */
1507 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1512 /* The address of an ELF reloc is section relative for an
1513 object file, and absolute for an executable file or
1514 shared library. The address of a BFD reloc is always
1515 section relative. */
1516 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1517 relent->address = rela.r_offset;
1519 relent->address = rela.r_offset - asect->vma;
1521 relent->addend = rela.r_addend;
1523 relent->howto = &howto_table[(int) type];
1529 asect->reloc_count += relent - relents;
1531 if (allocated != NULL)
1537 if (allocated != NULL)
1542 /* Read the relocations. On Irix 6, there can be two reloc sections
1543 associated with a single data section. */
1546 mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
1552 struct bfd_elf_section_data * const d = elf_section_data (asect);
1556 bfd_set_error (bfd_error_invalid_operation);
1560 if (asect->relocation != NULL
1561 || (asect->flags & SEC_RELOC) == 0
1562 || asect->reloc_count == 0)
1565 /* Allocate space for 3 arelent structures for each Rel structure. */
1566 asect->relocation = ((arelent *)
1568 asect->reloc_count * 3 * sizeof (arelent)));
1569 if (asect->relocation == NULL)
1572 /* The slurp_one_reloc_table routine increments reloc_count. */
1573 asect->reloc_count = 0;
1575 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
1577 if (d->rel_hdr2 != NULL)
1579 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
1587 /* Write out the relocations. */
1590 mips_elf64_write_relocs (abfd, sec, data)
1595 boolean *failedp = (boolean *) data;
1597 Elf_Internal_Shdr *rela_hdr;
1598 Elf64_Mips_External_Rela *ext_rela;
1600 asymbol *last_sym = 0;
1601 int last_sym_idx = 0;
1603 /* If we have already failed, don't do anything. */
1607 if ((sec->flags & SEC_RELOC) == 0)
1610 /* The linker backend writes the relocs out itself, and sets the
1611 reloc_count field to zero to inhibit writing them here. Also,
1612 sometimes the SEC_RELOC flag gets set even when there aren't any
1614 if (sec->reloc_count == 0)
1617 /* We can combine up to three relocs that refer to the same address
1618 if the latter relocs have no associated symbol. */
1620 for (idx = 0; idx < sec->reloc_count; idx++)
1627 addr = sec->orelocation[idx]->address;
1628 for (i = 0; i < 2; i++)
1632 if (idx + 1 >= sec->reloc_count)
1634 r = sec->orelocation[idx + 1];
1635 if (r->address != addr
1636 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
1637 || (*r->sym_ptr_ptr)->value != 0)
1640 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1646 rela_hdr = &elf_section_data (sec)->rel_hdr;
1648 rela_hdr->sh_size = rela_hdr->sh_entsize * count;
1649 rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
1650 if (rela_hdr->contents == NULL)
1656 ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
1657 for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
1660 Elf64_Mips_Internal_Rela int_rela;
1665 ptr = sec->orelocation[idx];
1667 /* The address of an ELF reloc is section relative for an object
1668 file, and absolute for an executable file or shared library.
1669 The address of a BFD reloc is always section relative. */
1670 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1671 int_rela.r_offset = ptr->address;
1673 int_rela.r_offset = ptr->address + sec->vma;
1675 sym = *ptr->sym_ptr_ptr;
1676 if (sym == last_sym)
1681 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
1692 int_rela.r_addend = ptr->addend;
1694 int_rela.r_ssym = RSS_UNDEF;
1696 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
1697 && ! _bfd_elf_validate_reloc (abfd, ptr))
1703 int_rela.r_type = ptr->howto->type;
1704 int_rela.r_type2 = (int) R_MIPS_NONE;
1705 int_rela.r_type3 = (int) R_MIPS_NONE;
1707 for (i = 0; i < 2; i++)
1711 if (idx + 1 >= sec->reloc_count)
1713 r = sec->orelocation[idx + 1];
1714 if (r->address != ptr->address
1715 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
1716 || (*r->sym_ptr_ptr)->value != 0)
1719 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1722 int_rela.r_type2 = r->howto->type;
1724 int_rela.r_type3 = r->howto->type;
1729 mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
1732 BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
1736 /* Handle a 64-bit MIPS ELF specific section. */
1739 mips_elf64_section_from_shdr (abfd, hdr, name)
1741 Elf_Internal_Shdr *hdr;
1744 if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
1747 /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
1748 set the gp value based on what we find. We may see both
1749 SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
1750 they should agree. */
1751 if (hdr->sh_type == SHT_MIPS_OPTIONS)
1753 bfd_byte *contents, *l, *lend;
1755 contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
1756 if (contents == NULL)
1758 if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
1759 (file_ptr) 0, hdr->sh_size))
1765 lend = contents + hdr->sh_size;
1766 while (l + sizeof (Elf_External_Options) <= lend)
1768 Elf_Internal_Options intopt;
1770 bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
1772 if (intopt.kind == ODK_REGINFO)
1774 Elf64_Internal_RegInfo intreg;
1776 bfd_mips_elf64_swap_reginfo_in
1778 ((Elf64_External_RegInfo *)
1779 (l + sizeof (Elf_External_Options))),
1781 elf_gp (abfd) = intreg.ri_gp_value;
1791 /* Work over a section just before writing it out. We update the GP
1792 value in the SHT_MIPS_OPTIONS section based on the value we are
1796 mips_elf64_section_processing (abfd, hdr)
1798 Elf_Internal_Shdr *hdr;
1800 if (hdr->sh_type == SHT_MIPS_OPTIONS
1801 && hdr->bfd_section != NULL
1802 && elf_section_data (hdr->bfd_section) != NULL
1803 && elf_section_data (hdr->bfd_section)->tdata != NULL)
1805 bfd_byte *contents, *l, *lend;
1807 /* We stored the section contents in the elf_section_data tdata
1808 field in the set_section_contents routine. We save the
1809 section contents so that we don't have to read them again.
1810 At this point we know that elf_gp is set, so we can look
1811 through the section contents to see if there is an
1812 ODK_REGINFO structure. */
1814 contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
1816 lend = contents + hdr->sh_size;
1817 while (l + sizeof (Elf_External_Options) <= lend)
1819 Elf_Internal_Options intopt;
1821 bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
1823 if (intopt.kind == ODK_REGINFO)
1830 + sizeof (Elf_External_Options)
1831 + (sizeof (Elf64_External_RegInfo) - 8)),
1834 bfd_h_put_64 (abfd, elf_gp (abfd), buf);
1835 if (bfd_write (buf, 1, 8, abfd) != 8)
1842 return _bfd_mips_elf_section_processing (abfd, hdr);
1845 /* Irix 6 defines a brand new archive map format, so that they can
1846 have archives more than 4 GB in size. */
1848 /* Read an Irix 6 armap. */
1851 mips_elf64_slurp_armap (abfd)
1854 struct artdata *ardata = bfd_ardata (abfd);
1857 bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
1858 struct areltdata *mapdata;
1859 bfd_byte int_buf[8];
1861 bfd_byte *raw_armap = NULL;
1864 ardata->symdefs = NULL;
1866 /* Get the name of the first element. */
1867 arhdrpos = bfd_tell (abfd);
1868 i = bfd_read ((PTR) nextname, 1, 16, abfd);
1874 if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
1877 /* Archives with traditional armaps are still permitted. */
1878 if (strncmp (nextname, "/ ", 16) == 0)
1879 return bfd_slurp_armap (abfd);
1881 if (strncmp (nextname, "/SYM64/ ", 16) != 0)
1883 bfd_has_map (abfd) = false;
1887 mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
1888 if (mapdata == NULL)
1890 parsed_size = mapdata->parsed_size;
1891 bfd_release (abfd, (PTR) mapdata);
1893 if (bfd_read (int_buf, 1, 8, abfd) != 8)
1895 if (bfd_get_error () != bfd_error_system_call)
1896 bfd_set_error (bfd_error_malformed_archive);
1900 nsymz = bfd_getb64 (int_buf);
1901 stringsize = parsed_size - 8 * nsymz - 8;
1903 carsym_size = nsymz * sizeof (carsym);
1904 ptrsize = 8 * nsymz;
1906 ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1);
1907 if (ardata->symdefs == NULL)
1909 carsyms = ardata->symdefs;
1910 stringbase = ((char *) ardata->symdefs) + carsym_size;
1912 raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
1913 if (raw_armap == NULL)
1916 if (bfd_read (raw_armap, 1, ptrsize, abfd) != ptrsize
1917 || bfd_read (stringbase, 1, stringsize, abfd) != stringsize)
1919 if (bfd_get_error () != bfd_error_system_call)
1920 bfd_set_error (bfd_error_malformed_archive);
1924 for (i = 0; i < nsymz; i++)
1926 carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
1927 carsyms->name = stringbase;
1928 stringbase += strlen (stringbase) + 1;
1933 ardata->symdef_count = nsymz;
1934 ardata->first_file_filepos = arhdrpos + sizeof (struct ar_hdr) + parsed_size;
1936 bfd_has_map (abfd) = true;
1937 bfd_release (abfd, raw_armap);
1942 if (raw_armap != NULL)
1943 bfd_release (abfd, raw_armap);
1944 if (ardata->symdefs != NULL)
1945 bfd_release (abfd, ardata->symdefs);
1949 /* Write out an Irix 6 armap. The Irix 6 tools are supposed to be
1950 able to handle ordinary ELF armaps, but at least on Irix 6.2 the
1954 mips_elf64_write_armap (arch, elength, map, symbol_count, stridx)
1956 unsigned int elength;
1958 unsigned int symbol_count;
1961 unsigned int ranlibsize = (symbol_count * 8) + 8;
1962 unsigned int stringsize = stridx;
1963 unsigned int mapsize = stringsize + ranlibsize;
1964 file_ptr archive_member_file_ptr;
1965 bfd *current = arch->archive_head;
1972 padding = BFD_ALIGN (mapsize, 8) - mapsize;
1975 /* work out where the first object file will go in the archive */
1976 archive_member_file_ptr = (mapsize
1978 + sizeof (struct ar_hdr)
1981 memset ((char *) (&hdr), 0, sizeof (struct ar_hdr));
1982 strcpy (hdr.ar_name, "/SYM64/");
1983 sprintf (hdr.ar_size, "%-10d", (int) mapsize);
1984 sprintf (hdr.ar_date, "%ld", (long) time (NULL));
1985 /* This, at least, is what Intel coff sets the values to.: */
1986 sprintf ((hdr.ar_uid), "%d", 0);
1987 sprintf ((hdr.ar_gid), "%d", 0);
1988 sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0);
1989 strncpy (hdr.ar_fmag, ARFMAG, 2);
1991 for (i = 0; i < sizeof (struct ar_hdr); i++)
1992 if (((char *) (&hdr))[i] == '\0')
1993 (((char *) (&hdr))[i]) = ' ';
1995 /* Write the ar header for this item and the number of symbols */
1997 if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), arch)
1998 != sizeof (struct ar_hdr))
2001 bfd_putb64 (symbol_count, buf);
2002 if (bfd_write (buf, 1, 8, arch) != 8)
2005 /* Two passes, first write the file offsets for each symbol -
2006 remembering that each offset is on a two byte boundary. */
2008 /* Write out the file offset for the file associated with each
2009 symbol, and remember to keep the offsets padded out. */
2011 current = arch->archive_head;
2013 while (current != (bfd *) NULL && count < symbol_count)
2015 /* For each symbol which is used defined in this object, write out
2016 the object file's address in the archive */
2018 while (((bfd *) (map[count]).pos) == current)
2020 bfd_putb64 (archive_member_file_ptr, buf);
2021 if (bfd_write (buf, 1, 8, arch) != 8)
2025 /* Add size of this archive entry */
2026 archive_member_file_ptr += (arelt_size (current)
2027 + sizeof (struct ar_hdr));
2028 /* remember about the even alignment */
2029 archive_member_file_ptr += archive_member_file_ptr % 2;
2030 current = current->next;
2033 /* now write the strings themselves */
2034 for (count = 0; count < symbol_count; count++)
2036 size_t len = strlen (*map[count].name) + 1;
2038 if (bfd_write (*map[count].name, 1, len, arch) != len)
2042 /* The spec says that this should be padded to an 8 byte boundary.
2043 However, the Irix 6.2 tools do not appear to do this. */
2044 while (padding != 0)
2046 if (bfd_write ("", 1, 1, arch) != 1)
2054 /* ECOFF swapping routines. These are used when dealing with the
2055 .mdebug section, which is in the ECOFF debugging format. */
2056 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
2058 /* Symbol table magic number. */
2060 /* Alignment of debugging information. E.g., 4. */
2062 /* Sizes of external symbolic information. */
2063 sizeof (struct hdr_ext),
2064 sizeof (struct dnr_ext),
2065 sizeof (struct pdr_ext),
2066 sizeof (struct sym_ext),
2067 sizeof (struct opt_ext),
2068 sizeof (struct fdr_ext),
2069 sizeof (struct rfd_ext),
2070 sizeof (struct ext_ext),
2071 /* Functions to swap in external symbolic data. */
2080 _bfd_ecoff_swap_tir_in,
2081 _bfd_ecoff_swap_rndx_in,
2082 /* Functions to swap out external symbolic data. */
2091 _bfd_ecoff_swap_tir_out,
2092 _bfd_ecoff_swap_rndx_out,
2093 /* Function to read in symbolic data. */
2094 _bfd_mips_elf_read_ecoff_info
2097 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
2098 standard ELF. This structure is used to redirect the relocation
2099 handling routines. */
2101 const struct elf_size_info mips_elf64_size_info =
2103 sizeof (Elf64_External_Ehdr),
2104 sizeof (Elf64_External_Phdr),
2105 sizeof (Elf64_External_Shdr),
2106 sizeof (Elf64_Mips_External_Rel),
2107 sizeof (Elf64_Mips_External_Rela),
2108 sizeof (Elf64_External_Sym),
2109 sizeof (Elf64_External_Dyn),
2110 sizeof (Elf_External_Note),
2115 bfd_elf64_write_out_phdrs,
2116 bfd_elf64_write_shdrs_and_ehdr,
2117 mips_elf64_write_relocs,
2118 bfd_elf64_swap_symbol_out,
2119 mips_elf64_slurp_reloc_table,
2120 bfd_elf64_slurp_symbol_table,
2121 bfd_elf64_swap_dyn_in
2124 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
2125 #define TARGET_LITTLE_NAME "elf64-littlemips"
2126 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
2127 #define TARGET_BIG_NAME "elf64-bigmips"
2128 #define ELF_ARCH bfd_arch_mips
2129 #define ELF_MACHINE_CODE EM_MIPS
2130 #define ELF_MAXPAGESIZE 0x1000
2131 #define elf_backend_size_info mips_elf64_size_info
2132 #define elf_backend_object_p _bfd_mips_elf_object_p
2133 #define elf_backend_section_from_shdr mips_elf64_section_from_shdr
2134 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
2135 #define elf_backend_section_from_bfd_section \
2136 _bfd_mips_elf_section_from_bfd_section
2137 #define elf_backend_section_processing mips_elf64_section_processing
2138 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
2139 #define elf_backend_final_write_processing \
2140 _bfd_mips_elf_final_write_processing
2141 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
2143 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
2144 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
2145 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
2146 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
2147 #define bfd_elf64_bfd_copy_private_bfd_data \
2148 _bfd_mips_elf_copy_private_bfd_data
2149 #define bfd_elf64_bfd_merge_private_bfd_data \
2150 _bfd_mips_elf_merge_private_bfd_data
2151 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
2153 #define bfd_elf64_archive_functions
2154 #define bfd_elf64_archive_slurp_armap mips_elf64_slurp_armap
2155 #define bfd_elf64_archive_slurp_extended_name_table \
2156 _bfd_archive_coff_slurp_extended_name_table
2157 #define bfd_elf64_archive_construct_extended_name_table \
2158 _bfd_archive_coff_construct_extended_name_table
2159 #define bfd_elf64_archive_truncate_arname \
2160 _bfd_archive_coff_truncate_arname
2161 #define bfd_elf64_archive_write_armap mips_elf64_write_armap
2162 #define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
2163 #define bfd_elf64_archive_openr_next_archived_file \
2164 _bfd_archive_coff_openr_next_archived_file
2165 #define bfd_elf64_archive_get_elt_at_index \
2166 _bfd_archive_coff_get_elt_at_index
2167 #define bfd_elf64_archive_generic_stat_arch_elt \
2168 _bfd_archive_coff_generic_stat_arch_elt
2169 #define bfd_elf64_archive_update_armap_timestamp \
2170 _bfd_archive_coff_update_armap_timestamp
2172 #include "elf64-target.h"