1 /* MIPS-specific support for 64-bit ELF
2 Copyright 1996, 1997, 1998 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
**, boolean
));
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 /* 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 relocation table used for SHT_REL sections. */
85 static reloc_howto_type mips_elf64_howto_table_rel
[] =
88 HOWTO (R_MIPS_NONE
, /* type */
90 0, /* size (0 = byte, 1 = short, 2 = long) */
92 false, /* pc_relative */
94 complain_overflow_dont
, /* complain_on_overflow */
95 bfd_elf_generic_reloc
, /* special_function */
96 "R_MIPS_NONE", /* name */
97 false, /* partial_inplace */
100 false), /* pcrel_offset */
102 /* 16 bit relocation. */
103 HOWTO (R_MIPS_16
, /* type */
105 1, /* size (0 = byte, 1 = short, 2 = long) */
107 false, /* pc_relative */
109 complain_overflow_bitfield
, /* complain_on_overflow */
110 bfd_elf_generic_reloc
, /* special_function */
111 "R_MIPS_16", /* name */
112 true, /* partial_inplace */
113 0xffff, /* src_mask */
114 0xffff, /* dst_mask */
115 false), /* pcrel_offset */
117 /* 32 bit relocation. */
118 HOWTO (R_MIPS_32
, /* type */
120 2, /* size (0 = byte, 1 = short, 2 = long) */
122 false, /* pc_relative */
124 complain_overflow_bitfield
, /* complain_on_overflow */
125 bfd_elf_generic_reloc
, /* special_function */
126 "R_MIPS_32", /* name */
127 true, /* partial_inplace */
128 0xffffffff, /* src_mask */
129 0xffffffff, /* dst_mask */
130 false), /* pcrel_offset */
132 /* 32 bit symbol relative relocation. */
133 HOWTO (R_MIPS_REL32
, /* type */
135 2, /* size (0 = byte, 1 = short, 2 = long) */
137 false, /* pc_relative */
139 complain_overflow_bitfield
, /* complain_on_overflow */
140 bfd_elf_generic_reloc
, /* special_function */
141 "R_MIPS_REL32", /* name */
142 true, /* partial_inplace */
143 0xffffffff, /* src_mask */
144 0xffffffff, /* dst_mask */
145 false), /* pcrel_offset */
147 /* 26 bit branch address. */
148 HOWTO (R_MIPS_26
, /* type */
150 2, /* size (0 = byte, 1 = short, 2 = long) */
152 false, /* pc_relative */
154 complain_overflow_dont
, /* complain_on_overflow */
155 /* This needs complex overflow
156 detection, because the upper four
157 bits must match the PC. */
158 bfd_elf_generic_reloc
, /* special_function */
159 "R_MIPS_26", /* name */
160 true, /* partial_inplace */
161 0x3ffffff, /* src_mask */
162 0x3ffffff, /* dst_mask */
163 false), /* pcrel_offset */
165 /* High 16 bits of symbol value. */
166 HOWTO (R_MIPS_HI16
, /* type */
168 2, /* size (0 = byte, 1 = short, 2 = long) */
170 false, /* pc_relative */
172 complain_overflow_dont
, /* complain_on_overflow */
173 _bfd_mips_elf_hi16_reloc
, /* special_function */
174 "R_MIPS_HI16", /* name */
175 true, /* partial_inplace */
176 0xffff, /* src_mask */
177 0xffff, /* dst_mask */
178 false), /* pcrel_offset */
180 /* Low 16 bits of symbol value. */
181 HOWTO (R_MIPS_LO16
, /* type */
183 2, /* size (0 = byte, 1 = short, 2 = long) */
185 false, /* pc_relative */
187 complain_overflow_dont
, /* complain_on_overflow */
188 _bfd_mips_elf_lo16_reloc
, /* special_function */
189 "R_MIPS_LO16", /* name */
190 true, /* partial_inplace */
191 0xffff, /* src_mask */
192 0xffff, /* dst_mask */
193 false), /* pcrel_offset */
195 /* GP relative reference. */
196 HOWTO (R_MIPS_GPREL16
, /* type */
198 2, /* size (0 = byte, 1 = short, 2 = long) */
200 false, /* pc_relative */
202 complain_overflow_signed
, /* complain_on_overflow */
203 _bfd_mips_elf_gprel16_reloc
, /* special_function */
204 "R_MIPS_GPREL16", /* name */
205 true, /* partial_inplace */
206 0xffff, /* src_mask */
207 0xffff, /* dst_mask */
208 false), /* pcrel_offset */
210 /* Reference to literal section. */
211 HOWTO (R_MIPS_LITERAL
, /* type */
213 2, /* size (0 = byte, 1 = short, 2 = long) */
215 false, /* pc_relative */
217 complain_overflow_signed
, /* complain_on_overflow */
218 _bfd_mips_elf_gprel16_reloc
, /* special_function */
219 "R_MIPS_LITERAL", /* name */
220 true, /* partial_inplace */
221 0xffff, /* src_mask */
222 0xffff, /* dst_mask */
223 false), /* pcrel_offset */
225 /* Reference to global offset table. */
226 HOWTO (R_MIPS_GOT16
, /* type */
228 2, /* size (0 = byte, 1 = short, 2 = long) */
230 false, /* pc_relative */
232 complain_overflow_signed
, /* complain_on_overflow */
233 _bfd_mips_elf_got16_reloc
, /* special_function */
234 "R_MIPS_GOT16", /* name */
235 false, /* partial_inplace */
237 0xffff, /* dst_mask */
238 false), /* pcrel_offset */
240 /* 16 bit PC relative reference. */
241 HOWTO (R_MIPS_PC16
, /* type */
243 2, /* size (0 = byte, 1 = short, 2 = long) */
245 true, /* pc_relative */
247 complain_overflow_signed
, /* complain_on_overflow */
248 bfd_elf_generic_reloc
, /* special_function */
249 "R_MIPS_PC16", /* name */
250 true, /* partial_inplace */
251 0xffff, /* src_mask */
252 0xffff, /* dst_mask */
253 false), /* pcrel_offset */
255 /* 16 bit call through global offset table. */
256 /* FIXME: This is not handled correctly. */
257 HOWTO (R_MIPS_CALL16
, /* type */
259 2, /* size (0 = byte, 1 = short, 2 = long) */
261 false, /* pc_relative */
263 complain_overflow_signed
, /* complain_on_overflow */
264 bfd_elf_generic_reloc
, /* special_function */
265 "R_MIPS_CALL16", /* name */
266 false, /* partial_inplace */
268 0xffff, /* dst_mask */
269 false), /* pcrel_offset */
271 /* 32 bit GP relative reference. */
272 HOWTO (R_MIPS_GPREL32
, /* type */
274 2, /* size (0 = byte, 1 = short, 2 = long) */
276 false, /* pc_relative */
278 complain_overflow_bitfield
, /* complain_on_overflow */
279 _bfd_mips_elf_gprel32_reloc
, /* special_function */
280 "R_MIPS_GPREL32", /* name */
281 true, /* partial_inplace */
282 0xffffffff, /* src_mask */
283 0xffffffff, /* dst_mask */
284 false), /* pcrel_offset */
290 /* A 5 bit shift field. */
291 HOWTO (R_MIPS_SHIFT5
, /* type */
293 2, /* size (0 = byte, 1 = short, 2 = long) */
295 false, /* pc_relative */
297 complain_overflow_bitfield
, /* complain_on_overflow */
298 bfd_elf_generic_reloc
, /* special_function */
299 "R_MIPS_SHIFT5", /* name */
300 true, /* partial_inplace */
301 0x000007c0, /* src_mask */
302 0x000007c0, /* dst_mask */
303 false), /* pcrel_offset */
305 /* A 6 bit shift field. */
306 /* FIXME: This is not handled correctly; a special function is
307 needed to put the most significant bit in the right place. */
308 HOWTO (R_MIPS_SHIFT6
, /* type */
310 2, /* size (0 = byte, 1 = short, 2 = long) */
312 false, /* pc_relative */
314 complain_overflow_bitfield
, /* complain_on_overflow */
315 bfd_elf_generic_reloc
, /* special_function */
316 "R_MIPS_SHIFT6", /* name */
317 true, /* partial_inplace */
318 0x000007c4, /* src_mask */
319 0x000007c4, /* dst_mask */
320 false), /* pcrel_offset */
322 /* 64 bit relocation. */
323 HOWTO (R_MIPS_64
, /* type */
325 4, /* size (0 = byte, 1 = short, 2 = long) */
327 false, /* pc_relative */
329 complain_overflow_bitfield
, /* complain_on_overflow */
330 bfd_elf_generic_reloc
, /* special_function */
331 "R_MIPS_64", /* name */
332 true, /* partial_inplace */
333 MINUS_ONE
, /* src_mask */
334 MINUS_ONE
, /* dst_mask */
335 false), /* pcrel_offset */
337 /* Displacement in the global offset table. */
338 /* FIXME: Not handled correctly. */
339 HOWTO (R_MIPS_GOT_DISP
, /* type */
341 2, /* size (0 = byte, 1 = short, 2 = long) */
343 false, /* pc_relative */
345 complain_overflow_bitfield
, /* complain_on_overflow */
346 bfd_elf_generic_reloc
, /* special_function */
347 "R_MIPS_GOT_DISP", /* name */
348 true, /* partial_inplace */
349 0x0000ffff, /* src_mask */
350 0x0000ffff, /* dst_mask */
351 false), /* pcrel_offset */
353 /* Displacement to page pointer in the global offset table. */
354 /* FIXME: Not handled correctly. */
355 HOWTO (R_MIPS_GOT_PAGE
, /* type */
357 2, /* size (0 = byte, 1 = short, 2 = long) */
359 false, /* pc_relative */
361 complain_overflow_bitfield
, /* complain_on_overflow */
362 bfd_elf_generic_reloc
, /* special_function */
363 "R_MIPS_GOT_PAGE", /* name */
364 true, /* partial_inplace */
365 0x0000ffff, /* src_mask */
366 0x0000ffff, /* dst_mask */
367 false), /* pcrel_offset */
369 /* Offset from page pointer in the global offset table. */
370 /* FIXME: Not handled correctly. */
371 HOWTO (R_MIPS_GOT_OFST
, /* type */
373 2, /* size (0 = byte, 1 = short, 2 = long) */
375 false, /* pc_relative */
377 complain_overflow_bitfield
, /* complain_on_overflow */
378 bfd_elf_generic_reloc
, /* special_function */
379 "R_MIPS_GOT_OFST", /* name */
380 true, /* partial_inplace */
381 0x0000ffff, /* src_mask */
382 0x0000ffff, /* dst_mask */
383 false), /* pcrel_offset */
385 /* High 16 bits of displacement in global offset table. */
386 /* FIXME: Not handled correctly. */
387 HOWTO (R_MIPS_GOT_HI16
, /* type */
389 2, /* size (0 = byte, 1 = short, 2 = long) */
391 false, /* pc_relative */
393 complain_overflow_dont
, /* complain_on_overflow */
394 bfd_elf_generic_reloc
, /* special_function */
395 "R_MIPS_GOT_HI16", /* name */
396 true, /* partial_inplace */
397 0x0000ffff, /* src_mask */
398 0x0000ffff, /* dst_mask */
399 false), /* pcrel_offset */
401 /* Low 16 bits of displacement in global offset table. */
402 /* FIXME: Not handled correctly. */
403 HOWTO (R_MIPS_GOT_LO16
, /* type */
405 2, /* size (0 = byte, 1 = short, 2 = long) */
407 false, /* pc_relative */
409 complain_overflow_dont
, /* complain_on_overflow */
410 bfd_elf_generic_reloc
, /* special_function */
411 "R_MIPS_GOT_LO16", /* name */
412 true, /* partial_inplace */
413 0x0000ffff, /* src_mask */
414 0x0000ffff, /* dst_mask */
415 false), /* pcrel_offset */
417 /* 64 bit substraction. */
418 /* FIXME: Not handled correctly. */
419 HOWTO (R_MIPS_SUB
, /* type */
421 4, /* size (0 = byte, 1 = short, 2 = long) */
423 false, /* pc_relative */
425 complain_overflow_bitfield
, /* complain_on_overflow */
426 bfd_elf_generic_reloc
, /* special_function */
427 "R_MIPS_SUB", /* name */
428 true, /* partial_inplace */
429 MINUS_ONE
, /* src_mask */
430 MINUS_ONE
, /* dst_mask */
431 false), /* pcrel_offset */
433 /* Insert the addend as an instruction. */
434 /* FIXME: Not handled correctly. */
435 HOWTO (R_MIPS_INSERT_A
, /* type */
437 0, /* size (0 = byte, 1 = short, 2 = long) */
439 false, /* pc_relative */
441 complain_overflow_dont
, /* complain_on_overflow */
442 bfd_elf_generic_reloc
, /* special_function */
443 "R_MIPS_INSERT_A", /* name */
444 false, /* partial_inplace */
447 false), /* pcrel_offset */
449 /* Insert the addend as an instruction, and change all relocations
450 to refer to the old instruction at the address. */
451 /* FIXME: Not handled correctly. */
452 HOWTO (R_MIPS_INSERT_B
, /* type */
454 0, /* size (0 = byte, 1 = short, 2 = long) */
456 false, /* pc_relative */
458 complain_overflow_dont
, /* complain_on_overflow */
459 bfd_elf_generic_reloc
, /* special_function */
460 "R_MIPS_INSERT_B", /* name */
461 false, /* partial_inplace */
464 false), /* pcrel_offset */
466 /* Delete a 32 bit instruction. */
467 /* FIXME: Not handled correctly. */
468 HOWTO (R_MIPS_DELETE
, /* type */
470 0, /* size (0 = byte, 1 = short, 2 = long) */
472 false, /* pc_relative */
474 complain_overflow_dont
, /* complain_on_overflow */
475 bfd_elf_generic_reloc
, /* special_function */
476 "R_MIPS_DELETE", /* name */
477 false, /* partial_inplace */
480 false), /* pcrel_offset */
482 /* Get the higher value of a 64 bit addend. */
483 /* FIXME: Not handled correctly. */
484 HOWTO (R_MIPS_HIGHER
, /* type */
486 2, /* size (0 = byte, 1 = short, 2 = long) */
488 false, /* pc_relative */
490 complain_overflow_dont
, /* complain_on_overflow */
491 bfd_elf_generic_reloc
, /* special_function */
492 "R_MIPS_HIGHER", /* name */
493 true, /* partial_inplace */
494 0xffff, /* src_mask */
495 0xffff, /* dst_mask */
496 false), /* pcrel_offset */
498 /* Get the highest value of a 64 bit addend. */
499 /* FIXME: Not handled correctly. */
500 HOWTO (R_MIPS_HIGHEST
, /* type */
502 2, /* size (0 = byte, 1 = short, 2 = long) */
504 false, /* pc_relative */
506 complain_overflow_dont
, /* complain_on_overflow */
507 bfd_elf_generic_reloc
, /* special_function */
508 "R_MIPS_HIGHEST", /* name */
509 true, /* partial_inplace */
510 0xffff, /* src_mask */
511 0xffff, /* dst_mask */
512 false), /* pcrel_offset */
514 /* High 16 bits of displacement in global offset table. */
515 /* FIXME: Not handled correctly. */
516 HOWTO (R_MIPS_CALL_HI16
, /* type */
518 2, /* size (0 = byte, 1 = short, 2 = long) */
520 false, /* pc_relative */
522 complain_overflow_dont
, /* complain_on_overflow */
523 bfd_elf_generic_reloc
, /* special_function */
524 "R_MIPS_CALL_HI16", /* name */
525 true, /* partial_inplace */
526 0x0000ffff, /* src_mask */
527 0x0000ffff, /* dst_mask */
528 false), /* pcrel_offset */
530 /* Low 16 bits of displacement in global offset table. */
531 /* FIXME: Not handled correctly. */
532 HOWTO (R_MIPS_CALL_LO16
, /* type */
534 2, /* size (0 = byte, 1 = short, 2 = long) */
536 false, /* pc_relative */
538 complain_overflow_dont
, /* complain_on_overflow */
539 bfd_elf_generic_reloc
, /* special_function */
540 "R_MIPS_CALL_LO16", /* name */
541 true, /* partial_inplace */
542 0x0000ffff, /* src_mask */
543 0x0000ffff, /* dst_mask */
544 false), /* pcrel_offset */
546 /* I'm not sure what the remaining relocs are, but they are defined
549 HOWTO (R_MIPS_SCN_DISP
, /* type */
551 0, /* size (0 = byte, 1 = short, 2 = long) */
553 false, /* pc_relative */
555 complain_overflow_dont
, /* complain_on_overflow */
556 bfd_elf_generic_reloc
, /* special_function */
557 "R_MIPS_SCN_DISP", /* name */
558 false, /* partial_inplace */
561 false), /* pcrel_offset */
563 HOWTO (R_MIPS_REL16
, /* type */
565 0, /* size (0 = byte, 1 = short, 2 = long) */
567 false, /* pc_relative */
569 complain_overflow_dont
, /* complain_on_overflow */
570 bfd_elf_generic_reloc
, /* special_function */
571 "R_MIPS_REL16", /* name */
572 false, /* partial_inplace */
575 false), /* pcrel_offset */
577 HOWTO (R_MIPS_ADD_IMMEDIATE
, /* type */
579 0, /* 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_ADD_IMMEDIATE", /* name */
586 false, /* partial_inplace */
589 false), /* pcrel_offset */
591 HOWTO (R_MIPS_PJUMP
, /* type */
593 0, /* size (0 = byte, 1 = short, 2 = long) */
595 false, /* pc_relative */
597 complain_overflow_dont
, /* complain_on_overflow */
598 bfd_elf_generic_reloc
, /* special_function */
599 "R_MIPS_PJUMP", /* name */
600 false, /* partial_inplace */
603 false), /* pcrel_offset */
605 HOWTO (R_MIPS_RELGOT
, /* type */
607 0, /* size (0 = byte, 1 = short, 2 = long) */
609 false, /* pc_relative */
611 complain_overflow_dont
, /* complain_on_overflow */
612 bfd_elf_generic_reloc
, /* special_function */
613 "R_MIPS_RELGOT", /* name */
614 false, /* partial_inplace */
617 false) /* pcrel_offset */
620 /* The relocation table used for SHT_RELA sections. */
622 static reloc_howto_type mips_elf64_howto_table_rela
[] =
625 HOWTO (R_MIPS_NONE
, /* type */
627 0, /* size (0 = byte, 1 = short, 2 = long) */
629 false, /* pc_relative */
631 complain_overflow_dont
, /* complain_on_overflow */
632 bfd_elf_generic_reloc
, /* special_function */
633 "R_MIPS_NONE", /* name */
634 false, /* partial_inplace */
637 false), /* pcrel_offset */
639 /* 16 bit relocation. */
640 HOWTO (R_MIPS_16
, /* type */
642 1, /* size (0 = byte, 1 = short, 2 = long) */
644 false, /* pc_relative */
646 complain_overflow_bitfield
, /* complain_on_overflow */
647 bfd_elf_generic_reloc
, /* special_function */
648 "R_MIPS_16", /* name */
649 true, /* partial_inplace */
651 0xffff, /* dst_mask */
652 false), /* pcrel_offset */
654 /* 32 bit relocation. */
655 HOWTO (R_MIPS_32
, /* type */
657 2, /* size (0 = byte, 1 = short, 2 = long) */
659 false, /* pc_relative */
661 complain_overflow_bitfield
, /* complain_on_overflow */
662 bfd_elf_generic_reloc
, /* special_function */
663 "R_MIPS_32", /* name */
664 true, /* partial_inplace */
666 0xffffffff, /* dst_mask */
667 false), /* pcrel_offset */
669 /* 32 bit symbol relative relocation. */
670 HOWTO (R_MIPS_REL32
, /* type */
672 2, /* size (0 = byte, 1 = short, 2 = long) */
674 false, /* pc_relative */
676 complain_overflow_bitfield
, /* complain_on_overflow */
677 bfd_elf_generic_reloc
, /* special_function */
678 "R_MIPS_REL32", /* name */
679 true, /* partial_inplace */
681 0xffffffff, /* dst_mask */
682 false), /* pcrel_offset */
684 /* 26 bit branch address. */
685 HOWTO (R_MIPS_26
, /* type */
687 2, /* size (0 = byte, 1 = short, 2 = long) */
689 false, /* pc_relative */
691 complain_overflow_dont
, /* complain_on_overflow */
692 /* This needs complex overflow
693 detection, because the upper four
694 bits must match the PC. */
695 bfd_elf_generic_reloc
, /* special_function */
696 "R_MIPS_26", /* name */
697 true, /* partial_inplace */
699 0x3ffffff, /* dst_mask */
700 false), /* pcrel_offset */
702 /* High 16 bits of symbol value. */
703 HOWTO (R_MIPS_HI16
, /* type */
705 2, /* size (0 = byte, 1 = short, 2 = long) */
707 false, /* pc_relative */
709 complain_overflow_dont
, /* complain_on_overflow */
710 bfd_elf_generic_reloc
, /* special_function */
711 "R_MIPS_HI16", /* name */
712 true, /* partial_inplace */
714 0xffff, /* dst_mask */
715 false), /* pcrel_offset */
717 /* Low 16 bits of symbol value. */
718 HOWTO (R_MIPS_LO16
, /* type */
720 2, /* size (0 = byte, 1 = short, 2 = long) */
722 false, /* pc_relative */
724 complain_overflow_dont
, /* complain_on_overflow */
725 bfd_elf_generic_reloc
, /* special_function */
726 "R_MIPS_LO16", /* name */
727 true, /* partial_inplace */
729 0xffff, /* dst_mask */
730 false), /* pcrel_offset */
732 /* GP relative reference. */
733 HOWTO (R_MIPS_GPREL16
, /* type */
735 2, /* size (0 = byte, 1 = short, 2 = long) */
737 false, /* pc_relative */
739 complain_overflow_signed
, /* complain_on_overflow */
740 _bfd_mips_elf_gprel16_reloc
, /* special_function */
741 "R_MIPS_GPREL16", /* name */
742 true, /* partial_inplace */
744 0xffff, /* dst_mask */
745 false), /* pcrel_offset */
747 /* Reference to literal section. */
748 HOWTO (R_MIPS_LITERAL
, /* type */
750 2, /* size (0 = byte, 1 = short, 2 = long) */
752 false, /* pc_relative */
754 complain_overflow_signed
, /* complain_on_overflow */
755 _bfd_mips_elf_gprel16_reloc
, /* special_function */
756 "R_MIPS_LITERAL", /* name */
757 true, /* partial_inplace */
759 0xffff, /* dst_mask */
760 false), /* pcrel_offset */
762 /* Reference to global offset table. */
763 /* FIXME: This is not handled correctly. */
764 HOWTO (R_MIPS_GOT16
, /* type */
766 2, /* size (0 = byte, 1 = short, 2 = long) */
768 false, /* pc_relative */
770 complain_overflow_signed
, /* complain_on_overflow */
771 bfd_elf_generic_reloc
, /* special_function */
772 "R_MIPS_GOT16", /* name */
773 false, /* partial_inplace */
775 0xffff, /* dst_mask */
776 false), /* pcrel_offset */
778 /* 16 bit PC relative reference. */
779 HOWTO (R_MIPS_PC16
, /* type */
781 2, /* size (0 = byte, 1 = short, 2 = long) */
783 true, /* pc_relative */
785 complain_overflow_signed
, /* complain_on_overflow */
786 bfd_elf_generic_reloc
, /* special_function */
787 "R_MIPS_PC16", /* name */
788 true, /* partial_inplace */
790 0xffff, /* dst_mask */
791 false), /* pcrel_offset */
793 /* 16 bit call through global offset table. */
794 /* FIXME: This is not handled correctly. */
795 HOWTO (R_MIPS_CALL16
, /* type */
797 2, /* size (0 = byte, 1 = short, 2 = long) */
799 false, /* pc_relative */
801 complain_overflow_signed
, /* complain_on_overflow */
802 bfd_elf_generic_reloc
, /* special_function */
803 "R_MIPS_CALL16", /* name */
804 false, /* partial_inplace */
806 0xffff, /* dst_mask */
807 false), /* pcrel_offset */
809 /* 32 bit GP relative reference. */
810 HOWTO (R_MIPS_GPREL32
, /* type */
812 2, /* size (0 = byte, 1 = short, 2 = long) */
814 false, /* pc_relative */
816 complain_overflow_bitfield
, /* complain_on_overflow */
817 _bfd_mips_elf_gprel32_reloc
, /* special_function */
818 "R_MIPS_GPREL32", /* name */
819 true, /* partial_inplace */
821 0xffffffff, /* dst_mask */
822 false), /* pcrel_offset */
828 /* A 5 bit shift field. */
829 HOWTO (R_MIPS_SHIFT5
, /* type */
831 2, /* size (0 = byte, 1 = short, 2 = long) */
833 false, /* pc_relative */
835 complain_overflow_bitfield
, /* complain_on_overflow */
836 bfd_elf_generic_reloc
, /* special_function */
837 "R_MIPS_SHIFT5", /* name */
838 true, /* partial_inplace */
840 0x000007c0, /* dst_mask */
841 false), /* pcrel_offset */
843 /* A 6 bit shift field. */
844 /* FIXME: This is not handled correctly; a special function is
845 needed to put the most significant bit in the right place. */
846 HOWTO (R_MIPS_SHIFT6
, /* type */
848 2, /* size (0 = byte, 1 = short, 2 = long) */
850 false, /* pc_relative */
852 complain_overflow_bitfield
, /* complain_on_overflow */
853 bfd_elf_generic_reloc
, /* special_function */
854 "R_MIPS_SHIFT6", /* name */
855 true, /* partial_inplace */
857 0x000007c4, /* dst_mask */
858 false), /* pcrel_offset */
860 /* 64 bit relocation. */
861 HOWTO (R_MIPS_64
, /* type */
863 4, /* size (0 = byte, 1 = short, 2 = long) */
865 false, /* pc_relative */
867 complain_overflow_bitfield
, /* complain_on_overflow */
868 bfd_elf_generic_reloc
, /* special_function */
869 "R_MIPS_64", /* name */
870 true, /* partial_inplace */
872 MINUS_ONE
, /* dst_mask */
873 false), /* pcrel_offset */
875 /* Displacement in the global offset table. */
876 /* FIXME: Not handled correctly. */
877 HOWTO (R_MIPS_GOT_DISP
, /* type */
879 2, /* size (0 = byte, 1 = short, 2 = long) */
881 false, /* pc_relative */
883 complain_overflow_bitfield
, /* complain_on_overflow */
884 bfd_elf_generic_reloc
, /* special_function */
885 "R_MIPS_GOT_DISP", /* name */
886 true, /* partial_inplace */
888 0x0000ffff, /* dst_mask */
889 false), /* pcrel_offset */
891 /* Displacement to page pointer in the global offset table. */
892 /* FIXME: Not handled correctly. */
893 HOWTO (R_MIPS_GOT_PAGE
, /* type */
895 2, /* size (0 = byte, 1 = short, 2 = long) */
897 false, /* pc_relative */
899 complain_overflow_bitfield
, /* complain_on_overflow */
900 bfd_elf_generic_reloc
, /* special_function */
901 "R_MIPS_GOT_PAGE", /* name */
902 true, /* partial_inplace */
904 0x0000ffff, /* dst_mask */
905 false), /* pcrel_offset */
907 /* Offset from page pointer in the global offset table. */
908 /* FIXME: Not handled correctly. */
909 HOWTO (R_MIPS_GOT_OFST
, /* type */
911 2, /* size (0 = byte, 1 = short, 2 = long) */
913 false, /* pc_relative */
915 complain_overflow_bitfield
, /* complain_on_overflow */
916 bfd_elf_generic_reloc
, /* special_function */
917 "R_MIPS_GOT_OFST", /* name */
918 true, /* partial_inplace */
920 0x0000ffff, /* dst_mask */
921 false), /* pcrel_offset */
923 /* High 16 bits of displacement in global offset table. */
924 /* FIXME: Not handled correctly. */
925 HOWTO (R_MIPS_GOT_HI16
, /* type */
927 2, /* size (0 = byte, 1 = short, 2 = long) */
929 false, /* pc_relative */
931 complain_overflow_dont
, /* complain_on_overflow */
932 bfd_elf_generic_reloc
, /* special_function */
933 "R_MIPS_GOT_HI16", /* name */
934 true, /* partial_inplace */
936 0x0000ffff, /* dst_mask */
937 false), /* pcrel_offset */
939 /* Low 16 bits of displacement in global offset table. */
940 /* FIXME: Not handled correctly. */
941 HOWTO (R_MIPS_GOT_LO16
, /* type */
943 2, /* size (0 = byte, 1 = short, 2 = long) */
945 false, /* pc_relative */
947 complain_overflow_dont
, /* complain_on_overflow */
948 bfd_elf_generic_reloc
, /* special_function */
949 "R_MIPS_GOT_LO16", /* name */
950 true, /* partial_inplace */
952 0x0000ffff, /* dst_mask */
953 false), /* pcrel_offset */
955 /* 64 bit substraction. */
956 /* FIXME: Not handled correctly. */
957 HOWTO (R_MIPS_SUB
, /* type */
959 4, /* size (0 = byte, 1 = short, 2 = long) */
961 false, /* pc_relative */
963 complain_overflow_bitfield
, /* complain_on_overflow */
964 bfd_elf_generic_reloc
, /* special_function */
965 "R_MIPS_SUB", /* name */
966 true, /* partial_inplace */
968 MINUS_ONE
, /* dst_mask */
969 false), /* pcrel_offset */
971 /* Insert the addend as an instruction. */
972 /* FIXME: Not handled correctly. */
973 HOWTO (R_MIPS_INSERT_A
, /* type */
975 0, /* size (0 = byte, 1 = short, 2 = long) */
977 false, /* pc_relative */
979 complain_overflow_dont
, /* complain_on_overflow */
980 bfd_elf_generic_reloc
, /* special_function */
981 "R_MIPS_INSERT_A", /* name */
982 false, /* partial_inplace */
985 false), /* pcrel_offset */
987 /* Insert the addend as an instruction, and change all relocations
988 to refer to the old instruction at the address. */
989 /* FIXME: Not handled correctly. */
990 HOWTO (R_MIPS_INSERT_B
, /* type */
992 0, /* size (0 = byte, 1 = short, 2 = long) */
994 false, /* pc_relative */
996 complain_overflow_dont
, /* complain_on_overflow */
997 bfd_elf_generic_reloc
, /* special_function */
998 "R_MIPS_INSERT_B", /* name */
999 false, /* partial_inplace */
1002 false), /* pcrel_offset */
1004 /* Delete a 32 bit instruction. */
1005 /* FIXME: Not handled correctly. */
1006 HOWTO (R_MIPS_DELETE
, /* type */
1008 0, /* size (0 = byte, 1 = short, 2 = long) */
1010 false, /* pc_relative */
1012 complain_overflow_dont
, /* complain_on_overflow */
1013 bfd_elf_generic_reloc
, /* special_function */
1014 "R_MIPS_DELETE", /* name */
1015 false, /* partial_inplace */
1018 false), /* pcrel_offset */
1020 /* Get the higher value of a 64 bit addend. */
1021 /* FIXME: Not handled correctly. */
1022 HOWTO (R_MIPS_HIGHER
, /* type */
1024 2, /* size (0 = byte, 1 = short, 2 = long) */
1026 false, /* pc_relative */
1028 complain_overflow_dont
, /* complain_on_overflow */
1029 bfd_elf_generic_reloc
, /* special_function */
1030 "R_MIPS_HIGHER", /* name */
1031 true, /* partial_inplace */
1033 0xffff, /* dst_mask */
1034 false), /* pcrel_offset */
1036 /* Get the highest value of a 64 bit addend. */
1037 /* FIXME: Not handled correctly. */
1038 HOWTO (R_MIPS_HIGHEST
, /* type */
1040 2, /* size (0 = byte, 1 = short, 2 = long) */
1042 false, /* pc_relative */
1044 complain_overflow_dont
, /* complain_on_overflow */
1045 bfd_elf_generic_reloc
, /* special_function */
1046 "R_MIPS_HIGHEST", /* name */
1047 true, /* partial_inplace */
1049 0xffff, /* dst_mask */
1050 false), /* pcrel_offset */
1052 /* High 16 bits of displacement in global offset table. */
1053 /* FIXME: Not handled correctly. */
1054 HOWTO (R_MIPS_CALL_HI16
, /* type */
1056 2, /* size (0 = byte, 1 = short, 2 = long) */
1058 false, /* pc_relative */
1060 complain_overflow_dont
, /* complain_on_overflow */
1061 bfd_elf_generic_reloc
, /* special_function */
1062 "R_MIPS_CALL_HI16", /* name */
1063 true, /* partial_inplace */
1065 0x0000ffff, /* dst_mask */
1066 false), /* pcrel_offset */
1068 /* Low 16 bits of displacement in global offset table. */
1069 /* FIXME: Not handled correctly. */
1070 HOWTO (R_MIPS_CALL_LO16
, /* type */
1072 2, /* size (0 = byte, 1 = short, 2 = long) */
1074 false, /* pc_relative */
1076 complain_overflow_dont
, /* complain_on_overflow */
1077 bfd_elf_generic_reloc
, /* special_function */
1078 "R_MIPS_CALL_LO16", /* name */
1079 true, /* partial_inplace */
1081 0x0000ffff, /* dst_mask */
1082 false), /* pcrel_offset */
1084 /* I'm not sure what the remaining relocs are, but they are defined
1087 HOWTO (R_MIPS_SCN_DISP
, /* type */
1089 0, /* size (0 = byte, 1 = short, 2 = long) */
1091 false, /* pc_relative */
1093 complain_overflow_dont
, /* complain_on_overflow */
1094 bfd_elf_generic_reloc
, /* special_function */
1095 "R_MIPS_SCN_DISP", /* name */
1096 false, /* partial_inplace */
1099 false), /* pcrel_offset */
1101 HOWTO (R_MIPS_REL16
, /* type */
1103 0, /* size (0 = byte, 1 = short, 2 = long) */
1105 false, /* pc_relative */
1107 complain_overflow_dont
, /* complain_on_overflow */
1108 bfd_elf_generic_reloc
, /* special_function */
1109 "R_MIPS_REL16", /* name */
1110 false, /* partial_inplace */
1113 false), /* pcrel_offset */
1115 HOWTO (R_MIPS_ADD_IMMEDIATE
, /* type */
1117 0, /* 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_ADD_IMMEDIATE", /* name */
1124 false, /* partial_inplace */
1127 false), /* pcrel_offset */
1129 HOWTO (R_MIPS_PJUMP
, /* type */
1131 0, /* 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_PJUMP", /* name */
1138 false, /* partial_inplace */
1141 false), /* pcrel_offset */
1143 HOWTO (R_MIPS_RELGOT
, /* type */
1145 0, /* size (0 = byte, 1 = short, 2 = long) */
1147 false, /* pc_relative */
1149 complain_overflow_dont
, /* complain_on_overflow */
1150 bfd_elf_generic_reloc
, /* special_function */
1151 "R_MIPS_RELGOT", /* name */
1152 false, /* partial_inplace */
1155 false) /* pcrel_offset */
1158 /* Swap in a MIPS 64-bit Rel reloc. */
1161 mips_elf64_swap_reloc_in (abfd
, src
, dst
)
1163 const Elf64_Mips_External_Rel
*src
;
1164 Elf64_Mips_Internal_Rel
*dst
;
1166 dst
->r_offset
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_offset
);
1167 dst
->r_sym
= bfd_h_get_32 (abfd
, (bfd_byte
*) src
->r_sym
);
1168 dst
->r_ssym
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_ssym
);
1169 dst
->r_type3
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type3
);
1170 dst
->r_type2
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type2
);
1171 dst
->r_type
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type
);
1174 /* Swap in a MIPS 64-bit Rela reloc. */
1177 mips_elf64_swap_reloca_in (abfd
, src
, dst
)
1179 const Elf64_Mips_External_Rela
*src
;
1180 Elf64_Mips_Internal_Rela
*dst
;
1182 dst
->r_offset
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_offset
);
1183 dst
->r_sym
= bfd_h_get_32 (abfd
, (bfd_byte
*) src
->r_sym
);
1184 dst
->r_ssym
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_ssym
);
1185 dst
->r_type3
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type3
);
1186 dst
->r_type2
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type2
);
1187 dst
->r_type
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type
);
1188 dst
->r_addend
= bfd_h_get_signed_64 (abfd
, (bfd_byte
*) src
->r_addend
);
1193 /* This is not currently used. */
1195 /* Swap out a MIPS 64-bit Rel reloc. */
1198 mips_elf64_swap_reloc_out (abfd
, src
, dst
)
1200 const Elf64_Mips_Internal_Rel
*src
;
1201 Elf64_Mips_External_Rel
*dst
;
1203 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1204 bfd_h_put_32 (abfd
, src
->r_sym
, (bfd_byte
*) dst
->r_sym
);
1205 bfd_h_put_8 (abfd
, src
->r_ssym
, (bfd_byte
*) dst
->r_ssym
);
1206 bfd_h_put_8 (abfd
, src
->r_type3
, (bfd_byte
*) dst
->r_type3
);
1207 bfd_h_put_8 (abfd
, src
->r_type2
, (bfd_byte
*) dst
->r_type2
);
1208 bfd_h_put_8 (abfd
, src
->r_type
, (bfd_byte
*) dst
->r_type
);
1213 /* Swap out a MIPS 64-bit Rela reloc. */
1216 mips_elf64_swap_reloca_out (abfd
, src
, dst
)
1218 const Elf64_Mips_Internal_Rela
*src
;
1219 Elf64_Mips_External_Rela
*dst
;
1221 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1222 bfd_h_put_32 (abfd
, src
->r_sym
, (bfd_byte
*) dst
->r_sym
);
1223 bfd_h_put_8 (abfd
, src
->r_ssym
, (bfd_byte
*) dst
->r_ssym
);
1224 bfd_h_put_8 (abfd
, src
->r_type3
, (bfd_byte
*) dst
->r_type3
);
1225 bfd_h_put_8 (abfd
, src
->r_type2
, (bfd_byte
*) dst
->r_type2
);
1226 bfd_h_put_8 (abfd
, src
->r_type
, (bfd_byte
*) dst
->r_type
);
1227 bfd_h_put_64 (abfd
, src
->r_addend
, (bfd_byte
*) dst
->r_addend
);
1230 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1232 struct elf_reloc_map
1234 bfd_reloc_code_real_type bfd_reloc_val
;
1235 enum elf_mips_reloc_type elf_reloc_val
;
1238 static CONST
struct elf_reloc_map mips_reloc_map
[] =
1240 { BFD_RELOC_NONE
, R_MIPS_NONE
, },
1241 { BFD_RELOC_16
, R_MIPS_16
},
1242 { BFD_RELOC_32
, R_MIPS_32
},
1243 { BFD_RELOC_64
, R_MIPS_64
},
1244 { BFD_RELOC_CTOR
, R_MIPS_64
},
1245 { BFD_RELOC_32_PCREL
, R_MIPS_REL32
},
1246 { BFD_RELOC_MIPS_JMP
, R_MIPS_26
},
1247 { BFD_RELOC_HI16_S
, R_MIPS_HI16
},
1248 { BFD_RELOC_LO16
, R_MIPS_LO16
},
1249 { BFD_RELOC_MIPS_GPREL
, R_MIPS_GPREL16
},
1250 { BFD_RELOC_MIPS_LITERAL
, R_MIPS_LITERAL
},
1251 { BFD_RELOC_MIPS_GOT16
, R_MIPS_GOT16
},
1252 { BFD_RELOC_16_PCREL
, R_MIPS_PC16
},
1253 { BFD_RELOC_MIPS_CALL16
, R_MIPS_CALL16
},
1254 { BFD_RELOC_MIPS_GPREL32
, R_MIPS_GPREL32
},
1255 { BFD_RELOC_MIPS_GOT_HI16
, R_MIPS_GOT_HI16
},
1256 { BFD_RELOC_MIPS_GOT_LO16
, R_MIPS_GOT_LO16
},
1257 { BFD_RELOC_MIPS_CALL_HI16
, R_MIPS_CALL_HI16
},
1258 { BFD_RELOC_MIPS_CALL_LO16
, R_MIPS_CALL_LO16
},
1259 { BFD_RELOC_MIPS_SUB
, R_MIPS_SUB
},
1260 { BFD_RELOC_MIPS_GOT_PAGE
, R_MIPS_GOT_PAGE
},
1261 { BFD_RELOC_MIPS_GOT_OFST
, R_MIPS_GOT_OFST
},
1262 { BFD_RELOC_MIPS_GOT_DISP
, R_MIPS_GOT_DISP
}
1265 /* Given a BFD reloc type, return a howto structure. */
1267 static reloc_howto_type
*
1268 mips_elf64_reloc_type_lookup (abfd
, code
)
1270 bfd_reloc_code_real_type code
;
1274 for (i
= 0; i
< sizeof (mips_reloc_map
) / sizeof (struct elf_reloc_map
); i
++)
1276 if (mips_reloc_map
[i
].bfd_reloc_val
== code
)
1280 v
= (int) mips_reloc_map
[i
].elf_reloc_val
;
1281 return &mips_elf64_howto_table_rel
[v
];
1288 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1289 to three relocs, we must tell the user to allocate more space. */
1292 mips_elf64_get_reloc_upper_bound (abfd
, sec
)
1296 return (sec
->reloc_count
* 3 + 1) * sizeof (arelent
*);
1299 /* Read the relocations from one reloc section. */
1302 mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
, rel_hdr
)
1306 const Elf_Internal_Shdr
*rel_hdr
;
1308 PTR allocated
= NULL
;
1309 bfd_byte
*native_relocs
;
1315 reloc_howto_type
*howto_table
;
1317 allocated
= (PTR
) bfd_malloc (rel_hdr
->sh_size
);
1318 if (allocated
== NULL
)
1321 if (bfd_seek (abfd
, rel_hdr
->sh_offset
, SEEK_SET
) != 0
1322 || (bfd_read (allocated
, 1, rel_hdr
->sh_size
, abfd
) != rel_hdr
->sh_size
))
1325 native_relocs
= (bfd_byte
*) allocated
;
1327 relents
= asect
->relocation
+ asect
->reloc_count
;
1329 entsize
= rel_hdr
->sh_entsize
;
1330 BFD_ASSERT (entsize
== sizeof (Elf64_Mips_External_Rel
)
1331 || entsize
== sizeof (Elf64_Mips_External_Rela
));
1333 count
= rel_hdr
->sh_size
/ entsize
;
1335 if (entsize
== sizeof (Elf64_Mips_External_Rel
))
1336 howto_table
= mips_elf64_howto_table_rel
;
1338 howto_table
= mips_elf64_howto_table_rela
;
1341 for (i
= 0; i
< count
; i
++, native_relocs
+= entsize
)
1343 Elf64_Mips_Internal_Rela rela
;
1344 boolean used_sym
, used_ssym
;
1347 if (entsize
== sizeof (Elf64_Mips_External_Rela
))
1348 mips_elf64_swap_reloca_in (abfd
,
1349 (Elf64_Mips_External_Rela
*) native_relocs
,
1353 Elf64_Mips_Internal_Rel rel
;
1355 mips_elf64_swap_reloc_in (abfd
,
1356 (Elf64_Mips_External_Rel
*) native_relocs
,
1358 rela
.r_offset
= rel
.r_offset
;
1359 rela
.r_sym
= rel
.r_sym
;
1360 rela
.r_ssym
= rel
.r_ssym
;
1361 rela
.r_type3
= rel
.r_type3
;
1362 rela
.r_type2
= rel
.r_type2
;
1363 rela
.r_type
= rel
.r_type
;
1367 /* Each entry represents up to three actual relocations. */
1371 for (ir
= 0; ir
< 3; ir
++)
1373 enum elf_mips_reloc_type type
;
1380 type
= (enum elf_mips_reloc_type
) rela
.r_type
;
1383 type
= (enum elf_mips_reloc_type
) rela
.r_type2
;
1386 type
= (enum elf_mips_reloc_type
) rela
.r_type3
;
1390 if (type
== R_MIPS_NONE
)
1392 /* There are no more relocations in this entry. If this
1393 is the first entry, we need to generate a dummy
1394 relocation so that the generic linker knows that
1395 there has been a break in the sequence of relocations
1396 applying to a particular address. */
1399 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1400 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1401 relent
->address
= rela
.r_offset
;
1403 relent
->address
= rela
.r_offset
- asect
->vma
;
1405 relent
->howto
= &howto_table
[(int) R_MIPS_NONE
];
1411 /* Some types require symbols, whereas some do not. */
1415 case R_MIPS_LITERAL
:
1416 case R_MIPS_INSERT_A
:
1417 case R_MIPS_INSERT_B
:
1419 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1425 if (rela
.r_sym
== 0)
1426 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1431 ps
= symbols
+ rela
.r_sym
- 1;
1433 if ((s
->flags
& BSF_SECTION_SYM
) == 0)
1434 relent
->sym_ptr_ptr
= ps
;
1436 relent
->sym_ptr_ptr
= s
->section
->symbol_ptr_ptr
;
1441 else if (! used_ssym
)
1443 switch (rela
.r_ssym
)
1446 relent
->sym_ptr_ptr
=
1447 bfd_abs_section_ptr
->symbol_ptr_ptr
;
1453 /* FIXME: I think these need to be handled using
1454 special howto structures. */
1466 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1471 /* The address of an ELF reloc is section relative for an
1472 object file, and absolute for an executable file or
1473 shared library. The address of a BFD reloc is always
1474 section relative. */
1475 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1476 relent
->address
= rela
.r_offset
;
1478 relent
->address
= rela
.r_offset
- asect
->vma
;
1480 relent
->addend
= rela
.r_addend
;
1482 relent
->howto
= &howto_table
[(int) type
];
1488 asect
->reloc_count
+= relent
- relents
;
1490 if (allocated
!= NULL
)
1496 if (allocated
!= NULL
)
1501 /* Read the relocations. On Irix 6, there can be two reloc sections
1502 associated with a single data section. */
1505 mips_elf64_slurp_reloc_table (abfd
, asect
, symbols
, dynamic
)
1511 struct bfd_elf_section_data
* const d
= elf_section_data (asect
);
1515 bfd_set_error (bfd_error_invalid_operation
);
1519 if (asect
->relocation
!= NULL
1520 || (asect
->flags
& SEC_RELOC
) == 0
1521 || asect
->reloc_count
== 0)
1524 /* Allocate space for 3 arelent structures for each Rel structure. */
1525 asect
->relocation
= ((arelent
*)
1527 asect
->reloc_count
* 3 * sizeof (arelent
)));
1528 if (asect
->relocation
== NULL
)
1531 /* The slurp_one_reloc_table routine increments reloc_count. */
1532 asect
->reloc_count
= 0;
1534 if (! mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
, &d
->rel_hdr
))
1536 if (d
->rel_hdr2
!= NULL
)
1538 if (! mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
,
1546 /* Write out the relocations. */
1549 mips_elf64_write_relocs (abfd
, sec
, data
)
1554 boolean
*failedp
= (boolean
*) data
;
1556 Elf_Internal_Shdr
*rela_hdr
;
1557 Elf64_Mips_External_Rela
*ext_rela
;
1559 asymbol
*last_sym
= 0;
1560 int last_sym_idx
= 0;
1562 /* If we have already failed, don't do anything. */
1566 if ((sec
->flags
& SEC_RELOC
) == 0)
1569 /* The linker backend writes the relocs out itself, and sets the
1570 reloc_count field to zero to inhibit writing them here. Also,
1571 sometimes the SEC_RELOC flag gets set even when there aren't any
1573 if (sec
->reloc_count
== 0)
1576 /* We can combine up to three relocs that refer to the same address
1577 if the latter relocs have no associated symbol. */
1579 for (idx
= 0; idx
< sec
->reloc_count
; idx
++)
1586 addr
= sec
->orelocation
[idx
]->address
;
1587 for (i
= 0; i
< 2; i
++)
1591 if (idx
+ 1 >= sec
->reloc_count
)
1593 r
= sec
->orelocation
[idx
+ 1];
1594 if (r
->address
!= addr
1595 || ! bfd_is_abs_section ((*r
->sym_ptr_ptr
)->section
)
1596 || (*r
->sym_ptr_ptr
)->value
!= 0)
1599 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1605 rela_hdr
= &elf_section_data (sec
)->rel_hdr
;
1607 rela_hdr
->sh_size
= rela_hdr
->sh_entsize
* count
;
1608 rela_hdr
->contents
= (PTR
) bfd_alloc (abfd
, rela_hdr
->sh_size
);
1609 if (rela_hdr
->contents
== NULL
)
1615 ext_rela
= (Elf64_Mips_External_Rela
*) rela_hdr
->contents
;
1616 for (idx
= 0; idx
< sec
->reloc_count
; idx
++, ext_rela
++)
1619 Elf64_Mips_Internal_Rela int_rela
;
1624 ptr
= sec
->orelocation
[idx
];
1626 /* The address of an ELF reloc is section relative for an object
1627 file, and absolute for an executable file or shared library.
1628 The address of a BFD reloc is always section relative. */
1629 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1630 int_rela
.r_offset
= ptr
->address
;
1632 int_rela
.r_offset
= ptr
->address
+ sec
->vma
;
1634 sym
= *ptr
->sym_ptr_ptr
;
1635 if (sym
== last_sym
)
1640 n
= _bfd_elf_symbol_from_bfd_symbol (abfd
, &sym
);
1651 int_rela
.r_addend
= ptr
->addend
;
1653 int_rela
.r_ssym
= RSS_UNDEF
;
1655 if ((*ptr
->sym_ptr_ptr
)->the_bfd
->xvec
!= abfd
->xvec
1656 && ! _bfd_elf_validate_reloc (abfd
, ptr
))
1662 int_rela
.r_type
= ptr
->howto
->type
;
1663 int_rela
.r_type2
= (int) R_MIPS_NONE
;
1664 int_rela
.r_type3
= (int) R_MIPS_NONE
;
1666 for (i
= 0; i
< 2; i
++)
1670 if (idx
+ 1 >= sec
->reloc_count
)
1672 r
= sec
->orelocation
[idx
+ 1];
1673 if (r
->address
!= ptr
->address
1674 || ! bfd_is_abs_section ((*r
->sym_ptr_ptr
)->section
)
1675 || (*r
->sym_ptr_ptr
)->value
!= 0)
1678 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1681 int_rela
.r_type2
= r
->howto
->type
;
1683 int_rela
.r_type3
= r
->howto
->type
;
1688 mips_elf64_swap_reloca_out (abfd
, &int_rela
, ext_rela
);
1691 BFD_ASSERT (ext_rela
- (Elf64_Mips_External_Rela
*) rela_hdr
->contents
1695 /* Handle a 64-bit MIPS ELF specific section. */
1698 mips_elf64_section_from_shdr (abfd
, hdr
, name
)
1700 Elf_Internal_Shdr
*hdr
;
1703 if (! _bfd_mips_elf_section_from_shdr (abfd
, hdr
, name
))
1706 /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
1707 set the gp value based on what we find. We may see both
1708 SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
1709 they should agree. */
1710 if (hdr
->sh_type
== SHT_MIPS_OPTIONS
)
1712 bfd_byte
*contents
, *l
, *lend
;
1714 contents
= (bfd_byte
*) bfd_malloc (hdr
->sh_size
);
1715 if (contents
== NULL
)
1717 if (! bfd_get_section_contents (abfd
, hdr
->bfd_section
, contents
,
1718 (file_ptr
) 0, hdr
->sh_size
))
1724 lend
= contents
+ hdr
->sh_size
;
1725 while (l
+ sizeof (Elf_External_Options
) <= lend
)
1727 Elf_Internal_Options intopt
;
1729 bfd_mips_elf_swap_options_in (abfd
, (Elf_External_Options
*) l
,
1731 if (intopt
.kind
== ODK_REGINFO
)
1733 Elf64_Internal_RegInfo intreg
;
1735 bfd_mips_elf64_swap_reginfo_in
1737 ((Elf64_External_RegInfo
*)
1738 (l
+ sizeof (Elf_External_Options
))),
1740 elf_gp (abfd
) = intreg
.ri_gp_value
;
1750 /* Work over a section just before writing it out. We update the GP
1751 value in the SHT_MIPS_OPTIONS section based on the value we are
1755 mips_elf64_section_processing (abfd
, hdr
)
1757 Elf_Internal_Shdr
*hdr
;
1759 if (hdr
->sh_type
== SHT_MIPS_OPTIONS
1760 && hdr
->bfd_section
!= NULL
1761 && elf_section_data (hdr
->bfd_section
) != NULL
1762 && elf_section_data (hdr
->bfd_section
)->tdata
!= NULL
)
1764 bfd_byte
*contents
, *l
, *lend
;
1766 /* We stored the section contents in the elf_section_data tdata
1767 field in the set_section_contents routine. We save the
1768 section contents so that we don't have to read them again.
1769 At this point we know that elf_gp is set, so we can look
1770 through the section contents to see if there is an
1771 ODK_REGINFO structure. */
1773 contents
= (bfd_byte
*) elf_section_data (hdr
->bfd_section
)->tdata
;
1775 lend
= contents
+ hdr
->sh_size
;
1776 while (l
+ sizeof (Elf_External_Options
) <= lend
)
1778 Elf_Internal_Options intopt
;
1780 bfd_mips_elf_swap_options_in (abfd
, (Elf_External_Options
*) l
,
1782 if (intopt
.kind
== ODK_REGINFO
)
1789 + sizeof (Elf_External_Options
)
1790 + (sizeof (Elf64_External_RegInfo
) - 8)),
1793 bfd_h_put_64 (abfd
, elf_gp (abfd
), buf
);
1794 if (bfd_write (buf
, 1, 8, abfd
) != 8)
1801 return _bfd_mips_elf_section_processing (abfd
, hdr
);
1804 /* Irix 6 defines a brand new archive map format, so that they can
1805 have archives more than 4 GB in size. */
1807 /* Read an Irix 6 armap. */
1810 mips_elf64_slurp_armap (abfd
)
1813 struct artdata
*ardata
= bfd_ardata (abfd
);
1816 bfd_size_type i
, parsed_size
, nsymz
, stringsize
, carsym_size
, ptrsize
;
1817 struct areltdata
*mapdata
;
1818 bfd_byte int_buf
[8];
1820 bfd_byte
*raw_armap
= NULL
;
1823 ardata
->symdefs
= NULL
;
1825 /* Get the name of the first element. */
1826 arhdrpos
= bfd_tell (abfd
);
1827 i
= bfd_read ((PTR
) nextname
, 1, 16, abfd
);
1833 if (bfd_seek (abfd
, (file_ptr
) - 16, SEEK_CUR
) != 0)
1836 /* Archives with traditional armaps are still permitted. */
1837 if (strncmp (nextname
, "/ ", 16) == 0)
1838 return bfd_slurp_armap (abfd
);
1840 if (strncmp (nextname
, "/SYM64/ ", 16) != 0)
1842 bfd_has_map (abfd
) = false;
1846 mapdata
= (struct areltdata
*) _bfd_read_ar_hdr (abfd
);
1847 if (mapdata
== NULL
)
1849 parsed_size
= mapdata
->parsed_size
;
1850 bfd_release (abfd
, (PTR
) mapdata
);
1852 if (bfd_read (int_buf
, 1, 8, abfd
) != 8)
1854 if (bfd_get_error () != bfd_error_system_call
)
1855 bfd_set_error (bfd_error_malformed_archive
);
1859 nsymz
= bfd_getb64 (int_buf
);
1860 stringsize
= parsed_size
- 8 * nsymz
- 8;
1862 carsym_size
= nsymz
* sizeof (carsym
);
1863 ptrsize
= 8 * nsymz
;
1865 ardata
->symdefs
= (carsym
*) bfd_zalloc (abfd
, carsym_size
+ stringsize
+ 1);
1866 if (ardata
->symdefs
== NULL
)
1868 carsyms
= ardata
->symdefs
;
1869 stringbase
= ((char *) ardata
->symdefs
) + carsym_size
;
1871 raw_armap
= (bfd_byte
*) bfd_alloc (abfd
, ptrsize
);
1872 if (raw_armap
== NULL
)
1875 if (bfd_read (raw_armap
, 1, ptrsize
, abfd
) != ptrsize
1876 || bfd_read (stringbase
, 1, stringsize
, abfd
) != stringsize
)
1878 if (bfd_get_error () != bfd_error_system_call
)
1879 bfd_set_error (bfd_error_malformed_archive
);
1883 for (i
= 0; i
< nsymz
; i
++)
1885 carsyms
->file_offset
= bfd_getb64 (raw_armap
+ i
* 8);
1886 carsyms
->name
= stringbase
;
1887 stringbase
+= strlen (stringbase
) + 1;
1892 ardata
->symdef_count
= nsymz
;
1893 ardata
->first_file_filepos
= arhdrpos
+ sizeof (struct ar_hdr
) + parsed_size
;
1895 bfd_has_map (abfd
) = true;
1896 bfd_release (abfd
, raw_armap
);
1901 if (raw_armap
!= NULL
)
1902 bfd_release (abfd
, raw_armap
);
1903 if (ardata
->symdefs
!= NULL
)
1904 bfd_release (abfd
, ardata
->symdefs
);
1908 /* Write out an Irix 6 armap. The Irix 6 tools are supposed to be
1909 able to handle ordinary ELF armaps, but at least on Irix 6.2 the
1913 mips_elf64_write_armap (arch
, elength
, map
, symbol_count
, stridx
)
1915 unsigned int elength
;
1917 unsigned int symbol_count
;
1920 unsigned int ranlibsize
= (symbol_count
* 8) + 8;
1921 unsigned int stringsize
= stridx
;
1922 unsigned int mapsize
= stringsize
+ ranlibsize
;
1923 file_ptr archive_member_file_ptr
;
1924 bfd
*current
= arch
->archive_head
;
1931 padding
= BFD_ALIGN (mapsize
, 8) - mapsize
;
1934 /* work out where the first object file will go in the archive */
1935 archive_member_file_ptr
= (mapsize
1937 + sizeof (struct ar_hdr
)
1940 memset ((char *) (&hdr
), 0, sizeof (struct ar_hdr
));
1941 strcpy (hdr
.ar_name
, "/SYM64/");
1942 sprintf (hdr
.ar_size
, "%-10d", (int) mapsize
);
1943 sprintf (hdr
.ar_date
, "%ld", (long) time (NULL
));
1944 /* This, at least, is what Intel coff sets the values to.: */
1945 sprintf ((hdr
.ar_uid
), "%d", 0);
1946 sprintf ((hdr
.ar_gid
), "%d", 0);
1947 sprintf ((hdr
.ar_mode
), "%-7o", (unsigned) 0);
1948 strncpy (hdr
.ar_fmag
, ARFMAG
, 2);
1950 for (i
= 0; i
< sizeof (struct ar_hdr
); i
++)
1951 if (((char *) (&hdr
))[i
] == '\0')
1952 (((char *) (&hdr
))[i
]) = ' ';
1954 /* Write the ar header for this item and the number of symbols */
1956 if (bfd_write ((PTR
) &hdr
, 1, sizeof (struct ar_hdr
), arch
)
1957 != sizeof (struct ar_hdr
))
1960 bfd_putb64 (symbol_count
, buf
);
1961 if (bfd_write (buf
, 1, 8, arch
) != 8)
1964 /* Two passes, first write the file offsets for each symbol -
1965 remembering that each offset is on a two byte boundary. */
1967 /* Write out the file offset for the file associated with each
1968 symbol, and remember to keep the offsets padded out. */
1970 current
= arch
->archive_head
;
1972 while (current
!= (bfd
*) NULL
&& count
< symbol_count
)
1974 /* For each symbol which is used defined in this object, write out
1975 the object file's address in the archive */
1977 while (((bfd
*) (map
[count
]).pos
) == current
)
1979 bfd_putb64 (archive_member_file_ptr
, buf
);
1980 if (bfd_write (buf
, 1, 8, arch
) != 8)
1984 /* Add size of this archive entry */
1985 archive_member_file_ptr
+= (arelt_size (current
)
1986 + sizeof (struct ar_hdr
));
1987 /* remember about the even alignment */
1988 archive_member_file_ptr
+= archive_member_file_ptr
% 2;
1989 current
= current
->next
;
1992 /* now write the strings themselves */
1993 for (count
= 0; count
< symbol_count
; count
++)
1995 size_t len
= strlen (*map
[count
].name
) + 1;
1997 if (bfd_write (*map
[count
].name
, 1, len
, arch
) != len
)
2001 /* The spec says that this should be padded to an 8 byte boundary.
2002 However, the Irix 6.2 tools do not appear to do this. */
2003 while (padding
!= 0)
2005 if (bfd_write ("", 1, 1, arch
) != 1)
2013 /* ECOFF swapping routines. These are used when dealing with the
2014 .mdebug section, which is in the ECOFF debugging format. */
2015 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap
=
2017 /* Symbol table magic number. */
2019 /* Alignment of debugging information. E.g., 4. */
2021 /* Sizes of external symbolic information. */
2022 sizeof (struct hdr_ext
),
2023 sizeof (struct dnr_ext
),
2024 sizeof (struct pdr_ext
),
2025 sizeof (struct sym_ext
),
2026 sizeof (struct opt_ext
),
2027 sizeof (struct fdr_ext
),
2028 sizeof (struct rfd_ext
),
2029 sizeof (struct ext_ext
),
2030 /* Functions to swap in external symbolic data. */
2039 _bfd_ecoff_swap_tir_in
,
2040 _bfd_ecoff_swap_rndx_in
,
2041 /* Functions to swap out external symbolic data. */
2050 _bfd_ecoff_swap_tir_out
,
2051 _bfd_ecoff_swap_rndx_out
,
2052 /* Function to read in symbolic data. */
2053 _bfd_mips_elf_read_ecoff_info
2056 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
2057 standard ELF. This structure is used to redirect the relocation
2058 handling routines. */
2060 const struct elf_size_info mips_elf64_size_info
=
2062 sizeof (Elf64_External_Ehdr
),
2063 sizeof (Elf64_External_Phdr
),
2064 sizeof (Elf64_External_Shdr
),
2065 sizeof (Elf64_Mips_External_Rel
),
2066 sizeof (Elf64_Mips_External_Rela
),
2067 sizeof (Elf64_External_Sym
),
2068 sizeof (Elf64_External_Dyn
),
2069 sizeof (Elf_External_Note
),
2074 bfd_elf64_write_out_phdrs
,
2075 bfd_elf64_write_shdrs_and_ehdr
,
2076 mips_elf64_write_relocs
,
2077 bfd_elf64_swap_symbol_out
,
2078 mips_elf64_slurp_reloc_table
,
2079 bfd_elf64_slurp_symbol_table
,
2080 bfd_elf64_swap_dyn_in
2083 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
2084 #define TARGET_LITTLE_NAME "elf64-littlemips"
2085 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
2086 #define TARGET_BIG_NAME "elf64-bigmips"
2087 #define ELF_ARCH bfd_arch_mips
2088 #define ELF_MACHINE_CODE EM_MIPS
2089 #define ELF_MAXPAGESIZE 0x1000
2090 #define elf_backend_size_info mips_elf64_size_info
2091 #define elf_backend_object_p _bfd_mips_elf_object_p
2092 #define elf_backend_section_from_shdr mips_elf64_section_from_shdr
2093 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
2094 #define elf_backend_section_from_bfd_section \
2095 _bfd_mips_elf_section_from_bfd_section
2096 #define elf_backend_section_processing mips_elf64_section_processing
2097 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
2098 #define elf_backend_final_write_processing \
2099 _bfd_mips_elf_final_write_processing
2100 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
2102 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
2103 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
2104 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
2105 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
2106 #define bfd_elf64_bfd_copy_private_bfd_data \
2107 _bfd_mips_elf_copy_private_bfd_data
2108 #define bfd_elf64_bfd_merge_private_bfd_data \
2109 _bfd_mips_elf_merge_private_bfd_data
2110 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
2112 #define bfd_elf64_archive_functions
2113 #define bfd_elf64_archive_slurp_armap mips_elf64_slurp_armap
2114 #define bfd_elf64_archive_slurp_extended_name_table \
2115 _bfd_archive_coff_slurp_extended_name_table
2116 #define bfd_elf64_archive_construct_extended_name_table \
2117 _bfd_archive_coff_construct_extended_name_table
2118 #define bfd_elf64_archive_truncate_arname \
2119 _bfd_archive_coff_truncate_arname
2120 #define bfd_elf64_archive_write_armap mips_elf64_write_armap
2121 #define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
2122 #define bfd_elf64_archive_openr_next_archived_file \
2123 _bfd_archive_coff_openr_next_archived_file
2124 #define bfd_elf64_archive_get_elt_at_index \
2125 _bfd_archive_coff_get_elt_at_index
2126 #define bfd_elf64_archive_generic_stat_arch_elt \
2127 _bfd_archive_coff_generic_stat_arch_elt
2128 #define bfd_elf64_archive_update_armap_timestamp \
2129 _bfd_archive_coff_update_armap_timestamp
2131 #include "elf64-target.h"