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