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));
80 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
81 from smaller values. Start with zero, widen, *then* decrement. */
82 #define MINUS_ONE (((bfd_vma)0) - 1)
84 /* The relocation table used for SHT_REL sections. */
86 static reloc_howto_type mips_elf64_howto_table_rel
[] =
89 HOWTO (R_MIPS_NONE
, /* type */
91 0, /* size (0 = byte, 1 = short, 2 = long) */
93 false, /* pc_relative */
95 complain_overflow_dont
, /* complain_on_overflow */
96 bfd_elf_generic_reloc
, /* special_function */
97 "R_MIPS_NONE", /* name */
98 false, /* partial_inplace */
101 false), /* pcrel_offset */
103 /* 16 bit relocation. */
104 HOWTO (R_MIPS_16
, /* type */
106 1, /* size (0 = byte, 1 = short, 2 = long) */
108 false, /* pc_relative */
110 complain_overflow_bitfield
, /* complain_on_overflow */
111 bfd_elf_generic_reloc
, /* special_function */
112 "R_MIPS_16", /* name */
113 true, /* partial_inplace */
114 0xffff, /* src_mask */
115 0xffff, /* dst_mask */
116 false), /* pcrel_offset */
118 /* 32 bit relocation. */
119 HOWTO (R_MIPS_32
, /* type */
121 2, /* size (0 = byte, 1 = short, 2 = long) */
123 false, /* pc_relative */
125 complain_overflow_bitfield
, /* complain_on_overflow */
126 bfd_elf_generic_reloc
, /* special_function */
127 "R_MIPS_32", /* name */
128 true, /* partial_inplace */
129 0xffffffff, /* src_mask */
130 0xffffffff, /* dst_mask */
131 false), /* pcrel_offset */
133 /* 32 bit symbol relative relocation. */
134 HOWTO (R_MIPS_REL32
, /* type */
136 2, /* size (0 = byte, 1 = short, 2 = long) */
138 false, /* pc_relative */
140 complain_overflow_bitfield
, /* complain_on_overflow */
141 bfd_elf_generic_reloc
, /* special_function */
142 "R_MIPS_REL32", /* name */
143 true, /* partial_inplace */
144 0xffffffff, /* src_mask */
145 0xffffffff, /* dst_mask */
146 false), /* pcrel_offset */
148 /* 26 bit branch address. */
149 HOWTO (R_MIPS_26
, /* type */
151 2, /* size (0 = byte, 1 = short, 2 = long) */
153 false, /* pc_relative */
155 complain_overflow_dont
, /* complain_on_overflow */
156 /* This needs complex overflow
157 detection, because the upper four
158 bits must match the PC. */
159 bfd_elf_generic_reloc
, /* special_function */
160 "R_MIPS_26", /* name */
161 true, /* partial_inplace */
162 0x3ffffff, /* src_mask */
163 0x3ffffff, /* dst_mask */
164 false), /* pcrel_offset */
166 /* High 16 bits of symbol value. */
167 HOWTO (R_MIPS_HI16
, /* type */
169 2, /* size (0 = byte, 1 = short, 2 = long) */
171 false, /* pc_relative */
173 complain_overflow_dont
, /* complain_on_overflow */
174 _bfd_mips_elf_hi16_reloc
, /* special_function */
175 "R_MIPS_HI16", /* name */
176 true, /* partial_inplace */
177 0xffff, /* src_mask */
178 0xffff, /* dst_mask */
179 false), /* pcrel_offset */
181 /* Low 16 bits of symbol value. */
182 HOWTO (R_MIPS_LO16
, /* type */
184 2, /* size (0 = byte, 1 = short, 2 = long) */
186 false, /* pc_relative */
188 complain_overflow_dont
, /* complain_on_overflow */
189 _bfd_mips_elf_lo16_reloc
, /* special_function */
190 "R_MIPS_LO16", /* name */
191 true, /* partial_inplace */
192 0xffff, /* src_mask */
193 0xffff, /* dst_mask */
194 false), /* pcrel_offset */
196 /* GP relative reference. */
197 HOWTO (R_MIPS_GPREL16
, /* type */
199 2, /* size (0 = byte, 1 = short, 2 = long) */
201 false, /* pc_relative */
203 complain_overflow_signed
, /* complain_on_overflow */
204 _bfd_mips_elf_gprel16_reloc
, /* special_function */
205 "R_MIPS_GPREL16", /* name */
206 true, /* partial_inplace */
207 0xffff, /* src_mask */
208 0xffff, /* dst_mask */
209 false), /* pcrel_offset */
211 /* Reference to literal section. */
212 HOWTO (R_MIPS_LITERAL
, /* type */
214 2, /* size (0 = byte, 1 = short, 2 = long) */
216 false, /* pc_relative */
218 complain_overflow_signed
, /* complain_on_overflow */
219 _bfd_mips_elf_gprel16_reloc
, /* special_function */
220 "R_MIPS_LITERAL", /* name */
221 true, /* partial_inplace */
222 0xffff, /* src_mask */
223 0xffff, /* dst_mask */
224 false), /* pcrel_offset */
226 /* Reference to global offset table. */
227 HOWTO (R_MIPS_GOT16
, /* type */
229 2, /* size (0 = byte, 1 = short, 2 = long) */
231 false, /* pc_relative */
233 complain_overflow_signed
, /* complain_on_overflow */
234 _bfd_mips_elf_got16_reloc
, /* special_function */
235 "R_MIPS_GOT16", /* name */
236 false, /* partial_inplace */
238 0xffff, /* dst_mask */
239 false), /* pcrel_offset */
241 /* 16 bit PC relative reference. */
242 HOWTO (R_MIPS_PC16
, /* type */
244 2, /* size (0 = byte, 1 = short, 2 = long) */
246 true, /* pc_relative */
248 complain_overflow_signed
, /* complain_on_overflow */
249 bfd_elf_generic_reloc
, /* special_function */
250 "R_MIPS_PC16", /* name */
251 true, /* partial_inplace */
252 0xffff, /* src_mask */
253 0xffff, /* dst_mask */
254 false), /* pcrel_offset */
256 /* 16 bit call through global offset table. */
257 /* FIXME: This is not handled correctly. */
258 HOWTO (R_MIPS_CALL16
, /* type */
260 2, /* size (0 = byte, 1 = short, 2 = long) */
262 false, /* pc_relative */
264 complain_overflow_signed
, /* complain_on_overflow */
265 bfd_elf_generic_reloc
, /* special_function */
266 "R_MIPS_CALL16", /* name */
267 false, /* partial_inplace */
269 0xffff, /* dst_mask */
270 false), /* pcrel_offset */
272 /* 32 bit GP relative reference. */
273 HOWTO (R_MIPS_GPREL32
, /* type */
275 2, /* size (0 = byte, 1 = short, 2 = long) */
277 false, /* pc_relative */
279 complain_overflow_bitfield
, /* complain_on_overflow */
280 _bfd_mips_elf_gprel32_reloc
, /* special_function */
281 "R_MIPS_GPREL32", /* name */
282 true, /* partial_inplace */
283 0xffffffff, /* src_mask */
284 0xffffffff, /* dst_mask */
285 false), /* pcrel_offset */
291 /* A 5 bit shift field. */
292 HOWTO (R_MIPS_SHIFT5
, /* type */
294 2, /* size (0 = byte, 1 = short, 2 = long) */
296 false, /* pc_relative */
298 complain_overflow_bitfield
, /* complain_on_overflow */
299 bfd_elf_generic_reloc
, /* special_function */
300 "R_MIPS_SHIFT5", /* name */
301 true, /* partial_inplace */
302 0x000007c0, /* src_mask */
303 0x000007c0, /* dst_mask */
304 false), /* pcrel_offset */
306 /* A 6 bit shift field. */
307 /* FIXME: This is not handled correctly; a special function is
308 needed to put the most significant bit in the right place. */
309 HOWTO (R_MIPS_SHIFT6
, /* type */
311 2, /* size (0 = byte, 1 = short, 2 = long) */
313 false, /* pc_relative */
315 complain_overflow_bitfield
, /* complain_on_overflow */
316 bfd_elf_generic_reloc
, /* special_function */
317 "R_MIPS_SHIFT6", /* name */
318 true, /* partial_inplace */
319 0x000007c4, /* src_mask */
320 0x000007c4, /* dst_mask */
321 false), /* pcrel_offset */
323 /* 64 bit relocation. */
324 HOWTO (R_MIPS_64
, /* type */
326 4, /* size (0 = byte, 1 = short, 2 = long) */
328 false, /* pc_relative */
330 complain_overflow_bitfield
, /* complain_on_overflow */
331 bfd_elf_generic_reloc
, /* special_function */
332 "R_MIPS_64", /* name */
333 true, /* partial_inplace */
334 MINUS_ONE
, /* src_mask */
335 MINUS_ONE
, /* dst_mask */
336 false), /* pcrel_offset */
338 /* Displacement in the global offset table. */
339 /* FIXME: Not handled correctly. */
340 HOWTO (R_MIPS_GOT_DISP
, /* type */
342 2, /* size (0 = byte, 1 = short, 2 = long) */
344 false, /* pc_relative */
346 complain_overflow_bitfield
, /* complain_on_overflow */
347 bfd_elf_generic_reloc
, /* special_function */
348 "R_MIPS_GOT_DISP", /* name */
349 true, /* partial_inplace */
350 0x0000ffff, /* src_mask */
351 0x0000ffff, /* dst_mask */
352 false), /* pcrel_offset */
354 /* Displacement to page pointer in the global offset table. */
355 /* FIXME: Not handled correctly. */
356 HOWTO (R_MIPS_GOT_PAGE
, /* type */
358 2, /* size (0 = byte, 1 = short, 2 = long) */
360 false, /* pc_relative */
362 complain_overflow_bitfield
, /* complain_on_overflow */
363 bfd_elf_generic_reloc
, /* special_function */
364 "R_MIPS_GOT_PAGE", /* name */
365 true, /* partial_inplace */
366 0x0000ffff, /* src_mask */
367 0x0000ffff, /* dst_mask */
368 false), /* pcrel_offset */
370 /* Offset from page pointer in the global offset table. */
371 /* FIXME: Not handled correctly. */
372 HOWTO (R_MIPS_GOT_OFST
, /* type */
374 2, /* size (0 = byte, 1 = short, 2 = long) */
376 false, /* pc_relative */
378 complain_overflow_bitfield
, /* complain_on_overflow */
379 bfd_elf_generic_reloc
, /* special_function */
380 "R_MIPS_GOT_OFST", /* name */
381 true, /* partial_inplace */
382 0x0000ffff, /* src_mask */
383 0x0000ffff, /* dst_mask */
384 false), /* pcrel_offset */
386 /* High 16 bits of displacement in global offset table. */
387 /* FIXME: Not handled correctly. */
388 HOWTO (R_MIPS_GOT_HI16
, /* type */
390 2, /* size (0 = byte, 1 = short, 2 = long) */
392 false, /* pc_relative */
394 complain_overflow_dont
, /* complain_on_overflow */
395 bfd_elf_generic_reloc
, /* special_function */
396 "R_MIPS_GOT_HI16", /* name */
397 true, /* partial_inplace */
398 0x0000ffff, /* src_mask */
399 0x0000ffff, /* dst_mask */
400 false), /* pcrel_offset */
402 /* Low 16 bits of displacement in global offset table. */
403 /* FIXME: Not handled correctly. */
404 HOWTO (R_MIPS_GOT_LO16
, /* type */
406 2, /* size (0 = byte, 1 = short, 2 = long) */
408 false, /* pc_relative */
410 complain_overflow_dont
, /* complain_on_overflow */
411 bfd_elf_generic_reloc
, /* special_function */
412 "R_MIPS_GOT_LO16", /* name */
413 true, /* partial_inplace */
414 0x0000ffff, /* src_mask */
415 0x0000ffff, /* dst_mask */
416 false), /* pcrel_offset */
418 /* 64 bit substraction. */
419 /* FIXME: Not handled correctly. */
420 HOWTO (R_MIPS_SUB
, /* type */
422 4, /* size (0 = byte, 1 = short, 2 = long) */
424 false, /* pc_relative */
426 complain_overflow_bitfield
, /* complain_on_overflow */
427 bfd_elf_generic_reloc
, /* special_function */
428 "R_MIPS_SUB", /* name */
429 true, /* partial_inplace */
430 MINUS_ONE
, /* src_mask */
431 MINUS_ONE
, /* dst_mask */
432 false), /* pcrel_offset */
434 /* Insert the addend as an instruction. */
435 /* FIXME: Not handled correctly. */
436 HOWTO (R_MIPS_INSERT_A
, /* type */
438 0, /* size (0 = byte, 1 = short, 2 = long) */
440 false, /* pc_relative */
442 complain_overflow_dont
, /* complain_on_overflow */
443 bfd_elf_generic_reloc
, /* special_function */
444 "R_MIPS_INSERT_A", /* name */
445 false, /* partial_inplace */
448 false), /* pcrel_offset */
450 /* Insert the addend as an instruction, and change all relocations
451 to refer to the old instruction at the address. */
452 /* FIXME: Not handled correctly. */
453 HOWTO (R_MIPS_INSERT_B
, /* type */
455 0, /* size (0 = byte, 1 = short, 2 = long) */
457 false, /* pc_relative */
459 complain_overflow_dont
, /* complain_on_overflow */
460 bfd_elf_generic_reloc
, /* special_function */
461 "R_MIPS_INSERT_B", /* name */
462 false, /* partial_inplace */
465 false), /* pcrel_offset */
467 /* Delete a 32 bit instruction. */
468 /* FIXME: Not handled correctly. */
469 HOWTO (R_MIPS_DELETE
, /* type */
471 0, /* size (0 = byte, 1 = short, 2 = long) */
473 false, /* pc_relative */
475 complain_overflow_dont
, /* complain_on_overflow */
476 bfd_elf_generic_reloc
, /* special_function */
477 "R_MIPS_DELETE", /* name */
478 false, /* partial_inplace */
481 false), /* pcrel_offset */
483 /* Get the higher value of a 64 bit addend. */
484 /* FIXME: Not handled correctly. */
485 HOWTO (R_MIPS_HIGHER
, /* type */
487 2, /* size (0 = byte, 1 = short, 2 = long) */
489 false, /* pc_relative */
491 complain_overflow_dont
, /* complain_on_overflow */
492 bfd_elf_generic_reloc
, /* special_function */
493 "R_MIPS_HIGHER", /* name */
494 true, /* partial_inplace */
495 0xffff, /* src_mask */
496 0xffff, /* dst_mask */
497 false), /* pcrel_offset */
499 /* Get the highest value of a 64 bit addend. */
500 /* FIXME: Not handled correctly. */
501 HOWTO (R_MIPS_HIGHEST
, /* type */
503 2, /* size (0 = byte, 1 = short, 2 = long) */
505 false, /* pc_relative */
507 complain_overflow_dont
, /* complain_on_overflow */
508 bfd_elf_generic_reloc
, /* special_function */
509 "R_MIPS_HIGHEST", /* name */
510 true, /* partial_inplace */
511 0xffff, /* src_mask */
512 0xffff, /* dst_mask */
513 false), /* pcrel_offset */
515 /* High 16 bits of displacement in global offset table. */
516 /* FIXME: Not handled correctly. */
517 HOWTO (R_MIPS_CALL_HI16
, /* type */
519 2, /* size (0 = byte, 1 = short, 2 = long) */
521 false, /* pc_relative */
523 complain_overflow_dont
, /* complain_on_overflow */
524 bfd_elf_generic_reloc
, /* special_function */
525 "R_MIPS_CALL_HI16", /* name */
526 true, /* partial_inplace */
527 0x0000ffff, /* src_mask */
528 0x0000ffff, /* dst_mask */
529 false), /* pcrel_offset */
531 /* Low 16 bits of displacement in global offset table. */
532 /* FIXME: Not handled correctly. */
533 HOWTO (R_MIPS_CALL_LO16
, /* type */
535 2, /* size (0 = byte, 1 = short, 2 = long) */
537 false, /* pc_relative */
539 complain_overflow_dont
, /* complain_on_overflow */
540 bfd_elf_generic_reloc
, /* special_function */
541 "R_MIPS_CALL_LO16", /* name */
542 true, /* partial_inplace */
543 0x0000ffff, /* src_mask */
544 0x0000ffff, /* dst_mask */
545 false), /* pcrel_offset */
547 /* I'm not sure what the remaining relocs are, but they are defined
550 HOWTO (R_MIPS_SCN_DISP
, /* type */
552 0, /* size (0 = byte, 1 = short, 2 = long) */
554 false, /* pc_relative */
556 complain_overflow_dont
, /* complain_on_overflow */
557 bfd_elf_generic_reloc
, /* special_function */
558 "R_MIPS_SCN_DISP", /* name */
559 false, /* partial_inplace */
562 false), /* pcrel_offset */
564 HOWTO (R_MIPS_REL16
, /* type */
566 0, /* size (0 = byte, 1 = short, 2 = long) */
568 false, /* pc_relative */
570 complain_overflow_dont
, /* complain_on_overflow */
571 bfd_elf_generic_reloc
, /* special_function */
572 "R_MIPS_REL16", /* name */
573 false, /* partial_inplace */
576 false), /* pcrel_offset */
578 HOWTO (R_MIPS_ADD_IMMEDIATE
, /* type */
580 0, /* size (0 = byte, 1 = short, 2 = long) */
582 false, /* pc_relative */
584 complain_overflow_dont
, /* complain_on_overflow */
585 bfd_elf_generic_reloc
, /* special_function */
586 "R_MIPS_ADD_IMMEDIATE", /* name */
587 false, /* partial_inplace */
590 false), /* pcrel_offset */
592 HOWTO (R_MIPS_PJUMP
, /* type */
594 0, /* size (0 = byte, 1 = short, 2 = long) */
596 false, /* pc_relative */
598 complain_overflow_dont
, /* complain_on_overflow */
599 bfd_elf_generic_reloc
, /* special_function */
600 "R_MIPS_PJUMP", /* name */
601 false, /* partial_inplace */
604 false), /* pcrel_offset */
606 HOWTO (R_MIPS_RELGOT
, /* type */
608 0, /* size (0 = byte, 1 = short, 2 = long) */
610 false, /* pc_relative */
612 complain_overflow_dont
, /* complain_on_overflow */
613 bfd_elf_generic_reloc
, /* special_function */
614 "R_MIPS_RELGOT", /* name */
615 false, /* partial_inplace */
618 false) /* pcrel_offset */
621 /* The relocation table used for SHT_RELA sections. */
623 static reloc_howto_type mips_elf64_howto_table_rela
[] =
626 HOWTO (R_MIPS_NONE
, /* type */
628 0, /* size (0 = byte, 1 = short, 2 = long) */
630 false, /* pc_relative */
632 complain_overflow_dont
, /* complain_on_overflow */
633 bfd_elf_generic_reloc
, /* special_function */
634 "R_MIPS_NONE", /* name */
635 false, /* partial_inplace */
638 false), /* pcrel_offset */
640 /* 16 bit relocation. */
641 HOWTO (R_MIPS_16
, /* type */
643 1, /* size (0 = byte, 1 = short, 2 = long) */
645 false, /* pc_relative */
647 complain_overflow_bitfield
, /* complain_on_overflow */
648 bfd_elf_generic_reloc
, /* special_function */
649 "R_MIPS_16", /* name */
650 true, /* partial_inplace */
652 0xffff, /* dst_mask */
653 false), /* pcrel_offset */
655 /* 32 bit relocation. */
656 HOWTO (R_MIPS_32
, /* type */
658 2, /* size (0 = byte, 1 = short, 2 = long) */
660 false, /* pc_relative */
662 complain_overflow_bitfield
, /* complain_on_overflow */
663 bfd_elf_generic_reloc
, /* special_function */
664 "R_MIPS_32", /* name */
665 true, /* partial_inplace */
667 0xffffffff, /* dst_mask */
668 false), /* pcrel_offset */
670 /* 32 bit symbol relative relocation. */
671 HOWTO (R_MIPS_REL32
, /* type */
673 2, /* size (0 = byte, 1 = short, 2 = long) */
675 false, /* pc_relative */
677 complain_overflow_bitfield
, /* complain_on_overflow */
678 bfd_elf_generic_reloc
, /* special_function */
679 "R_MIPS_REL32", /* name */
680 true, /* partial_inplace */
682 0xffffffff, /* dst_mask */
683 false), /* pcrel_offset */
685 /* 26 bit branch address. */
686 HOWTO (R_MIPS_26
, /* type */
688 2, /* size (0 = byte, 1 = short, 2 = long) */
690 false, /* pc_relative */
692 complain_overflow_dont
, /* complain_on_overflow */
693 /* This needs complex overflow
694 detection, because the upper four
695 bits must match the PC. */
696 bfd_elf_generic_reloc
, /* special_function */
697 "R_MIPS_26", /* name */
698 true, /* partial_inplace */
700 0x3ffffff, /* dst_mask */
701 false), /* pcrel_offset */
703 /* High 16 bits of symbol value. */
704 HOWTO (R_MIPS_HI16
, /* type */
706 2, /* size (0 = byte, 1 = short, 2 = long) */
708 false, /* pc_relative */
710 complain_overflow_dont
, /* complain_on_overflow */
711 bfd_elf_generic_reloc
, /* special_function */
712 "R_MIPS_HI16", /* name */
713 true, /* partial_inplace */
715 0xffff, /* dst_mask */
716 false), /* pcrel_offset */
718 /* Low 16 bits of symbol value. */
719 HOWTO (R_MIPS_LO16
, /* type */
721 2, /* size (0 = byte, 1 = short, 2 = long) */
723 false, /* pc_relative */
725 complain_overflow_dont
, /* complain_on_overflow */
726 bfd_elf_generic_reloc
, /* special_function */
727 "R_MIPS_LO16", /* name */
728 true, /* partial_inplace */
730 0xffff, /* dst_mask */
731 false), /* pcrel_offset */
733 /* GP relative reference. */
734 HOWTO (R_MIPS_GPREL16
, /* type */
736 2, /* size (0 = byte, 1 = short, 2 = long) */
738 false, /* pc_relative */
740 complain_overflow_signed
, /* complain_on_overflow */
741 _bfd_mips_elf_gprel16_reloc
, /* special_function */
742 "R_MIPS_GPREL16", /* name */
743 true, /* partial_inplace */
745 0xffff, /* dst_mask */
746 false), /* pcrel_offset */
748 /* Reference to literal section. */
749 HOWTO (R_MIPS_LITERAL
, /* type */
751 2, /* size (0 = byte, 1 = short, 2 = long) */
753 false, /* pc_relative */
755 complain_overflow_signed
, /* complain_on_overflow */
756 _bfd_mips_elf_gprel16_reloc
, /* special_function */
757 "R_MIPS_LITERAL", /* name */
758 true, /* partial_inplace */
760 0xffff, /* dst_mask */
761 false), /* pcrel_offset */
763 /* Reference to global offset table. */
764 /* FIXME: This is not handled correctly. */
765 HOWTO (R_MIPS_GOT16
, /* type */
767 2, /* size (0 = byte, 1 = short, 2 = long) */
769 false, /* pc_relative */
771 complain_overflow_signed
, /* complain_on_overflow */
772 bfd_elf_generic_reloc
, /* special_function */
773 "R_MIPS_GOT16", /* name */
774 false, /* partial_inplace */
776 0xffff, /* dst_mask */
777 false), /* pcrel_offset */
779 /* 16 bit PC relative reference. */
780 HOWTO (R_MIPS_PC16
, /* type */
782 2, /* size (0 = byte, 1 = short, 2 = long) */
784 true, /* pc_relative */
786 complain_overflow_signed
, /* complain_on_overflow */
787 bfd_elf_generic_reloc
, /* special_function */
788 "R_MIPS_PC16", /* name */
789 true, /* partial_inplace */
791 0xffff, /* dst_mask */
792 false), /* pcrel_offset */
794 /* 16 bit call through global offset table. */
795 /* FIXME: This is not handled correctly. */
796 HOWTO (R_MIPS_CALL16
, /* type */
798 2, /* size (0 = byte, 1 = short, 2 = long) */
800 false, /* pc_relative */
802 complain_overflow_signed
, /* complain_on_overflow */
803 bfd_elf_generic_reloc
, /* special_function */
804 "R_MIPS_CALL16", /* name */
805 false, /* partial_inplace */
807 0xffff, /* dst_mask */
808 false), /* pcrel_offset */
810 /* 32 bit GP relative reference. */
811 HOWTO (R_MIPS_GPREL32
, /* type */
813 2, /* size (0 = byte, 1 = short, 2 = long) */
815 false, /* pc_relative */
817 complain_overflow_bitfield
, /* complain_on_overflow */
818 _bfd_mips_elf_gprel32_reloc
, /* special_function */
819 "R_MIPS_GPREL32", /* name */
820 true, /* partial_inplace */
822 0xffffffff, /* dst_mask */
823 false), /* pcrel_offset */
829 /* A 5 bit shift field. */
830 HOWTO (R_MIPS_SHIFT5
, /* type */
832 2, /* size (0 = byte, 1 = short, 2 = long) */
834 false, /* pc_relative */
836 complain_overflow_bitfield
, /* complain_on_overflow */
837 bfd_elf_generic_reloc
, /* special_function */
838 "R_MIPS_SHIFT5", /* name */
839 true, /* partial_inplace */
841 0x000007c0, /* dst_mask */
842 false), /* pcrel_offset */
844 /* A 6 bit shift field. */
845 /* FIXME: This is not handled correctly; a special function is
846 needed to put the most significant bit in the right place. */
847 HOWTO (R_MIPS_SHIFT6
, /* type */
849 2, /* size (0 = byte, 1 = short, 2 = long) */
851 false, /* pc_relative */
853 complain_overflow_bitfield
, /* complain_on_overflow */
854 bfd_elf_generic_reloc
, /* special_function */
855 "R_MIPS_SHIFT6", /* name */
856 true, /* partial_inplace */
858 0x000007c4, /* dst_mask */
859 false), /* pcrel_offset */
861 /* 64 bit relocation. */
862 HOWTO (R_MIPS_64
, /* type */
864 4, /* size (0 = byte, 1 = short, 2 = long) */
866 false, /* pc_relative */
868 complain_overflow_bitfield
, /* complain_on_overflow */
869 bfd_elf_generic_reloc
, /* special_function */
870 "R_MIPS_64", /* name */
871 true, /* partial_inplace */
873 MINUS_ONE
, /* dst_mask */
874 false), /* pcrel_offset */
876 /* Displacement in the global offset table. */
877 /* FIXME: Not handled correctly. */
878 HOWTO (R_MIPS_GOT_DISP
, /* type */
880 2, /* size (0 = byte, 1 = short, 2 = long) */
882 false, /* pc_relative */
884 complain_overflow_bitfield
, /* complain_on_overflow */
885 bfd_elf_generic_reloc
, /* special_function */
886 "R_MIPS_GOT_DISP", /* name */
887 true, /* partial_inplace */
889 0x0000ffff, /* dst_mask */
890 false), /* pcrel_offset */
892 /* Displacement to page pointer in the global offset table. */
893 /* FIXME: Not handled correctly. */
894 HOWTO (R_MIPS_GOT_PAGE
, /* type */
896 2, /* size (0 = byte, 1 = short, 2 = long) */
898 false, /* pc_relative */
900 complain_overflow_bitfield
, /* complain_on_overflow */
901 bfd_elf_generic_reloc
, /* special_function */
902 "R_MIPS_GOT_PAGE", /* name */
903 true, /* partial_inplace */
905 0x0000ffff, /* dst_mask */
906 false), /* pcrel_offset */
908 /* Offset from page pointer in the global offset table. */
909 /* FIXME: Not handled correctly. */
910 HOWTO (R_MIPS_GOT_OFST
, /* type */
912 2, /* size (0 = byte, 1 = short, 2 = long) */
914 false, /* pc_relative */
916 complain_overflow_bitfield
, /* complain_on_overflow */
917 bfd_elf_generic_reloc
, /* special_function */
918 "R_MIPS_GOT_OFST", /* name */
919 true, /* partial_inplace */
921 0x0000ffff, /* dst_mask */
922 false), /* pcrel_offset */
924 /* High 16 bits of displacement in global offset table. */
925 /* FIXME: Not handled correctly. */
926 HOWTO (R_MIPS_GOT_HI16
, /* type */
928 2, /* size (0 = byte, 1 = short, 2 = long) */
930 false, /* pc_relative */
932 complain_overflow_dont
, /* complain_on_overflow */
933 bfd_elf_generic_reloc
, /* special_function */
934 "R_MIPS_GOT_HI16", /* name */
935 true, /* partial_inplace */
937 0x0000ffff, /* dst_mask */
938 false), /* pcrel_offset */
940 /* Low 16 bits of displacement in global offset table. */
941 /* FIXME: Not handled correctly. */
942 HOWTO (R_MIPS_GOT_LO16
, /* type */
944 2, /* size (0 = byte, 1 = short, 2 = long) */
946 false, /* pc_relative */
948 complain_overflow_dont
, /* complain_on_overflow */
949 bfd_elf_generic_reloc
, /* special_function */
950 "R_MIPS_GOT_LO16", /* name */
951 true, /* partial_inplace */
953 0x0000ffff, /* dst_mask */
954 false), /* pcrel_offset */
956 /* 64 bit substraction. */
957 /* FIXME: Not handled correctly. */
958 HOWTO (R_MIPS_SUB
, /* type */
960 4, /* size (0 = byte, 1 = short, 2 = long) */
962 false, /* pc_relative */
964 complain_overflow_bitfield
, /* complain_on_overflow */
965 bfd_elf_generic_reloc
, /* special_function */
966 "R_MIPS_SUB", /* name */
967 true, /* partial_inplace */
969 MINUS_ONE
, /* dst_mask */
970 false), /* pcrel_offset */
972 /* Insert the addend as an instruction. */
973 /* FIXME: Not handled correctly. */
974 HOWTO (R_MIPS_INSERT_A
, /* type */
976 0, /* size (0 = byte, 1 = short, 2 = long) */
978 false, /* pc_relative */
980 complain_overflow_dont
, /* complain_on_overflow */
981 bfd_elf_generic_reloc
, /* special_function */
982 "R_MIPS_INSERT_A", /* name */
983 false, /* partial_inplace */
986 false), /* pcrel_offset */
988 /* Insert the addend as an instruction, and change all relocations
989 to refer to the old instruction at the address. */
990 /* FIXME: Not handled correctly. */
991 HOWTO (R_MIPS_INSERT_B
, /* type */
993 0, /* size (0 = byte, 1 = short, 2 = long) */
995 false, /* pc_relative */
997 complain_overflow_dont
, /* complain_on_overflow */
998 bfd_elf_generic_reloc
, /* special_function */
999 "R_MIPS_INSERT_B", /* name */
1000 false, /* partial_inplace */
1003 false), /* pcrel_offset */
1005 /* Delete a 32 bit instruction. */
1006 /* FIXME: Not handled correctly. */
1007 HOWTO (R_MIPS_DELETE
, /* type */
1009 0, /* size (0 = byte, 1 = short, 2 = long) */
1011 false, /* pc_relative */
1013 complain_overflow_dont
, /* complain_on_overflow */
1014 bfd_elf_generic_reloc
, /* special_function */
1015 "R_MIPS_DELETE", /* name */
1016 false, /* partial_inplace */
1019 false), /* pcrel_offset */
1021 /* Get the higher value of a 64 bit addend. */
1022 /* FIXME: Not handled correctly. */
1023 HOWTO (R_MIPS_HIGHER
, /* type */
1025 2, /* size (0 = byte, 1 = short, 2 = long) */
1027 false, /* pc_relative */
1029 complain_overflow_dont
, /* complain_on_overflow */
1030 bfd_elf_generic_reloc
, /* special_function */
1031 "R_MIPS_HIGHER", /* name */
1032 true, /* partial_inplace */
1034 0xffff, /* dst_mask */
1035 false), /* pcrel_offset */
1037 /* Get the highest value of a 64 bit addend. */
1038 /* FIXME: Not handled correctly. */
1039 HOWTO (R_MIPS_HIGHEST
, /* type */
1041 2, /* size (0 = byte, 1 = short, 2 = long) */
1043 false, /* pc_relative */
1045 complain_overflow_dont
, /* complain_on_overflow */
1046 bfd_elf_generic_reloc
, /* special_function */
1047 "R_MIPS_HIGHEST", /* name */
1048 true, /* partial_inplace */
1050 0xffff, /* dst_mask */
1051 false), /* pcrel_offset */
1053 /* High 16 bits of displacement in global offset table. */
1054 /* FIXME: Not handled correctly. */
1055 HOWTO (R_MIPS_CALL_HI16
, /* type */
1057 2, /* size (0 = byte, 1 = short, 2 = long) */
1059 false, /* pc_relative */
1061 complain_overflow_dont
, /* complain_on_overflow */
1062 bfd_elf_generic_reloc
, /* special_function */
1063 "R_MIPS_CALL_HI16", /* name */
1064 true, /* partial_inplace */
1066 0x0000ffff, /* dst_mask */
1067 false), /* pcrel_offset */
1069 /* Low 16 bits of displacement in global offset table. */
1070 /* FIXME: Not handled correctly. */
1071 HOWTO (R_MIPS_CALL_LO16
, /* type */
1073 2, /* size (0 = byte, 1 = short, 2 = long) */
1075 false, /* pc_relative */
1077 complain_overflow_dont
, /* complain_on_overflow */
1078 bfd_elf_generic_reloc
, /* special_function */
1079 "R_MIPS_CALL_LO16", /* name */
1080 true, /* partial_inplace */
1082 0x0000ffff, /* dst_mask */
1083 false), /* pcrel_offset */
1085 /* I'm not sure what the remaining relocs are, but they are defined
1088 HOWTO (R_MIPS_SCN_DISP
, /* type */
1090 0, /* size (0 = byte, 1 = short, 2 = long) */
1092 false, /* pc_relative */
1094 complain_overflow_dont
, /* complain_on_overflow */
1095 bfd_elf_generic_reloc
, /* special_function */
1096 "R_MIPS_SCN_DISP", /* name */
1097 false, /* partial_inplace */
1100 false), /* pcrel_offset */
1102 HOWTO (R_MIPS_REL16
, /* type */
1104 0, /* size (0 = byte, 1 = short, 2 = long) */
1106 false, /* pc_relative */
1108 complain_overflow_dont
, /* complain_on_overflow */
1109 bfd_elf_generic_reloc
, /* special_function */
1110 "R_MIPS_REL16", /* name */
1111 false, /* partial_inplace */
1114 false), /* pcrel_offset */
1116 HOWTO (R_MIPS_ADD_IMMEDIATE
, /* type */
1118 0, /* size (0 = byte, 1 = short, 2 = long) */
1120 false, /* pc_relative */
1122 complain_overflow_dont
, /* complain_on_overflow */
1123 bfd_elf_generic_reloc
, /* special_function */
1124 "R_MIPS_ADD_IMMEDIATE", /* name */
1125 false, /* partial_inplace */
1128 false), /* pcrel_offset */
1130 HOWTO (R_MIPS_PJUMP
, /* type */
1132 0, /* size (0 = byte, 1 = short, 2 = long) */
1134 false, /* pc_relative */
1136 complain_overflow_dont
, /* complain_on_overflow */
1137 bfd_elf_generic_reloc
, /* special_function */
1138 "R_MIPS_PJUMP", /* name */
1139 false, /* partial_inplace */
1142 false), /* pcrel_offset */
1144 HOWTO (R_MIPS_RELGOT
, /* type */
1146 0, /* size (0 = byte, 1 = short, 2 = long) */
1148 false, /* pc_relative */
1150 complain_overflow_dont
, /* complain_on_overflow */
1151 bfd_elf_generic_reloc
, /* special_function */
1152 "R_MIPS_RELGOT", /* name */
1153 false, /* partial_inplace */
1156 false) /* pcrel_offset */
1159 /* Swap in a MIPS 64-bit Rel reloc. */
1162 mips_elf64_swap_reloc_in (abfd
, src
, dst
)
1164 const Elf64_Mips_External_Rel
*src
;
1165 Elf64_Mips_Internal_Rel
*dst
;
1167 dst
->r_offset
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_offset
);
1168 dst
->r_sym
= bfd_h_get_32 (abfd
, (bfd_byte
*) src
->r_sym
);
1169 dst
->r_ssym
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_ssym
);
1170 dst
->r_type3
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type3
);
1171 dst
->r_type2
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type2
);
1172 dst
->r_type
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type
);
1175 /* Swap in a MIPS 64-bit Rela reloc. */
1178 mips_elf64_swap_reloca_in (abfd
, src
, dst
)
1180 const Elf64_Mips_External_Rela
*src
;
1181 Elf64_Mips_Internal_Rela
*dst
;
1183 dst
->r_offset
= bfd_h_get_64 (abfd
, (bfd_byte
*) src
->r_offset
);
1184 dst
->r_sym
= bfd_h_get_32 (abfd
, (bfd_byte
*) src
->r_sym
);
1185 dst
->r_ssym
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_ssym
);
1186 dst
->r_type3
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type3
);
1187 dst
->r_type2
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type2
);
1188 dst
->r_type
= bfd_h_get_8 (abfd
, (bfd_byte
*) src
->r_type
);
1189 dst
->r_addend
= bfd_h_get_signed_64 (abfd
, (bfd_byte
*) src
->r_addend
);
1194 /* This is not currently used. */
1196 /* Swap out a MIPS 64-bit Rel reloc. */
1199 mips_elf64_swap_reloc_out (abfd
, src
, dst
)
1201 const Elf64_Mips_Internal_Rel
*src
;
1202 Elf64_Mips_External_Rel
*dst
;
1204 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1205 bfd_h_put_32 (abfd
, src
->r_sym
, (bfd_byte
*) dst
->r_sym
);
1206 bfd_h_put_8 (abfd
, src
->r_ssym
, (bfd_byte
*) dst
->r_ssym
);
1207 bfd_h_put_8 (abfd
, src
->r_type3
, (bfd_byte
*) dst
->r_type3
);
1208 bfd_h_put_8 (abfd
, src
->r_type2
, (bfd_byte
*) dst
->r_type2
);
1209 bfd_h_put_8 (abfd
, src
->r_type
, (bfd_byte
*) dst
->r_type
);
1214 /* Swap out a MIPS 64-bit Rela reloc. */
1217 mips_elf64_swap_reloca_out (abfd
, src
, dst
)
1219 const Elf64_Mips_Internal_Rela
*src
;
1220 Elf64_Mips_External_Rela
*dst
;
1222 bfd_h_put_64 (abfd
, src
->r_offset
, (bfd_byte
*) dst
->r_offset
);
1223 bfd_h_put_32 (abfd
, src
->r_sym
, (bfd_byte
*) dst
->r_sym
);
1224 bfd_h_put_8 (abfd
, src
->r_ssym
, (bfd_byte
*) dst
->r_ssym
);
1225 bfd_h_put_8 (abfd
, src
->r_type3
, (bfd_byte
*) dst
->r_type3
);
1226 bfd_h_put_8 (abfd
, src
->r_type2
, (bfd_byte
*) dst
->r_type2
);
1227 bfd_h_put_8 (abfd
, src
->r_type
, (bfd_byte
*) dst
->r_type
);
1228 bfd_h_put_64 (abfd
, src
->r_addend
, (bfd_byte
*) dst
->r_addend
);
1231 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1233 struct elf_reloc_map
1235 bfd_reloc_code_real_type bfd_reloc_val
;
1236 enum mips_elf64_reloc_type elf_reloc_val
;
1239 static CONST
struct elf_reloc_map mips_reloc_map
[] =
1241 { BFD_RELOC_NONE
, R_MIPS_NONE
, },
1242 { BFD_RELOC_16
, R_MIPS_16
},
1243 { BFD_RELOC_32
, R_MIPS_32
},
1244 { BFD_RELOC_64
, R_MIPS_64
},
1245 { BFD_RELOC_CTOR
, R_MIPS_64
},
1246 { BFD_RELOC_32_PCREL
, R_MIPS_REL32
},
1247 { BFD_RELOC_MIPS_JMP
, R_MIPS_26
},
1248 { BFD_RELOC_HI16_S
, R_MIPS_HI16
},
1249 { BFD_RELOC_LO16
, R_MIPS_LO16
},
1250 { BFD_RELOC_MIPS_GPREL
, R_MIPS_GPREL16
},
1251 { BFD_RELOC_MIPS_LITERAL
, R_MIPS_LITERAL
},
1252 { BFD_RELOC_MIPS_GOT16
, R_MIPS_GOT16
},
1253 { BFD_RELOC_16_PCREL
, R_MIPS_PC16
},
1254 { BFD_RELOC_MIPS_CALL16
, R_MIPS_CALL16
},
1255 { BFD_RELOC_MIPS_GPREL32
, R_MIPS_GPREL32
},
1256 { BFD_RELOC_MIPS_GOT_HI16
, R_MIPS_GOT_HI16
},
1257 { BFD_RELOC_MIPS_GOT_LO16
, R_MIPS_GOT_LO16
},
1258 { BFD_RELOC_MIPS_CALL_HI16
, R_MIPS_CALL_HI16
},
1259 { BFD_RELOC_MIPS_CALL_LO16
, R_MIPS_CALL_LO16
}
1262 /* Given a BFD reloc type, return a howto structure. */
1264 static reloc_howto_type
*
1265 mips_elf64_reloc_type_lookup (abfd
, code
)
1267 bfd_reloc_code_real_type code
;
1271 for (i
= 0; i
< sizeof (mips_reloc_map
) / sizeof (struct elf_reloc_map
); i
++)
1273 if (mips_reloc_map
[i
].bfd_reloc_val
== code
)
1277 v
= (int) mips_reloc_map
[i
].elf_reloc_val
;
1278 return &mips_elf64_howto_table_rel
[v
];
1285 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1286 to three relocs, we must tell the user to allocate more space. */
1289 mips_elf64_get_reloc_upper_bound (abfd
, sec
)
1293 return (sec
->reloc_count
* 3 + 1) * sizeof (arelent
*);
1296 /* Read the relocations from one reloc section. */
1299 mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
, rel_hdr
)
1303 const Elf_Internal_Shdr
*rel_hdr
;
1305 PTR allocated
= NULL
;
1306 bfd_byte
*native_relocs
;
1312 reloc_howto_type
*howto_table
;
1314 allocated
= (PTR
) bfd_malloc (rel_hdr
->sh_size
);
1315 if (allocated
== NULL
)
1318 if (bfd_seek (abfd
, rel_hdr
->sh_offset
, SEEK_SET
) != 0
1319 || (bfd_read (allocated
, 1, rel_hdr
->sh_size
, abfd
) != rel_hdr
->sh_size
))
1322 native_relocs
= (bfd_byte
*) allocated
;
1324 relents
= asect
->relocation
+ asect
->reloc_count
;
1326 entsize
= rel_hdr
->sh_entsize
;
1327 BFD_ASSERT (entsize
== sizeof (Elf64_Mips_External_Rel
)
1328 || entsize
== sizeof (Elf64_Mips_External_Rela
));
1330 count
= rel_hdr
->sh_size
/ entsize
;
1332 if (entsize
== sizeof (Elf64_Mips_External_Rel
))
1333 howto_table
= mips_elf64_howto_table_rel
;
1335 howto_table
= mips_elf64_howto_table_rela
;
1338 for (i
= 0; i
< count
; i
++, native_relocs
+= entsize
)
1340 Elf64_Mips_Internal_Rela rela
;
1341 boolean used_sym
, used_ssym
;
1344 if (entsize
== sizeof (Elf64_Mips_External_Rela
))
1345 mips_elf64_swap_reloca_in (abfd
,
1346 (Elf64_Mips_External_Rela
*) native_relocs
,
1350 Elf64_Mips_Internal_Rel rel
;
1352 mips_elf64_swap_reloc_in (abfd
,
1353 (Elf64_Mips_External_Rel
*) native_relocs
,
1355 rela
.r_offset
= rel
.r_offset
;
1356 rela
.r_sym
= rel
.r_sym
;
1357 rela
.r_ssym
= rel
.r_ssym
;
1358 rela
.r_type3
= rel
.r_type3
;
1359 rela
.r_type2
= rel
.r_type2
;
1360 rela
.r_type
= rel
.r_type
;
1364 /* Each entry represents up to three actual relocations. */
1368 for (ir
= 0; ir
< 3; ir
++)
1370 enum mips_elf64_reloc_type type
;
1377 type
= (enum mips_elf64_reloc_type
) rela
.r_type
;
1380 type
= (enum mips_elf64_reloc_type
) rela
.r_type2
;
1383 type
= (enum mips_elf64_reloc_type
) rela
.r_type3
;
1387 if (type
== R_MIPS_NONE
)
1389 /* There are no more relocations in this entry. If this
1390 is the first entry, we need to generate a dummy
1391 relocation so that the generic linker knows that
1392 there has been a break in the sequence of relocations
1393 applying to a particular address. */
1396 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1397 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1398 relent
->address
= rela
.r_offset
;
1400 relent
->address
= rela
.r_offset
- asect
->vma
;
1402 relent
->howto
= &howto_table
[(int) R_MIPS_NONE
];
1408 /* Some types require symbols, whereas some do not. */
1412 case R_MIPS_LITERAL
:
1413 case R_MIPS_INSERT_A
:
1414 case R_MIPS_INSERT_B
:
1416 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1422 if (rela
.r_sym
== 0)
1423 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1428 ps
= symbols
+ rela
.r_sym
- 1;
1430 if ((s
->flags
& BSF_SECTION_SYM
) == 0)
1431 relent
->sym_ptr_ptr
= ps
;
1433 relent
->sym_ptr_ptr
= s
->section
->symbol_ptr_ptr
;
1438 else if (! used_ssym
)
1440 switch (rela
.r_ssym
)
1443 relent
->sym_ptr_ptr
=
1444 bfd_abs_section_ptr
->symbol_ptr_ptr
;
1450 /* FIXME: I think these need to be handled using
1451 special howto structures. */
1463 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
1468 /* The address of an ELF reloc is section relative for an
1469 object file, and absolute for an executable file or
1470 shared library. The address of a BFD reloc is always
1471 section relative. */
1472 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1473 relent
->address
= rela
.r_offset
;
1475 relent
->address
= rela
.r_offset
- asect
->vma
;
1477 relent
->addend
= rela
.r_addend
;
1479 relent
->howto
= &howto_table
[(int) type
];
1485 asect
->reloc_count
+= relent
- relents
;
1487 if (allocated
!= NULL
)
1493 if (allocated
!= NULL
)
1498 /* Read the relocations. On Irix 6, there can be two reloc sections
1499 associated with a single data section. */
1502 mips_elf64_slurp_reloc_table (abfd
, asect
, symbols
, dynamic
)
1508 struct bfd_elf_section_data
* const d
= elf_section_data (asect
);
1512 bfd_set_error (bfd_error_invalid_operation
);
1516 if (asect
->relocation
!= NULL
1517 || (asect
->flags
& SEC_RELOC
) == 0
1518 || asect
->reloc_count
== 0)
1521 /* Allocate space for 3 arelent structures for each Rel structure. */
1522 asect
->relocation
= ((arelent
*)
1524 asect
->reloc_count
* 3 * sizeof (arelent
)));
1525 if (asect
->relocation
== NULL
)
1528 /* The slurp_one_reloc_table routine increments reloc_count. */
1529 asect
->reloc_count
= 0;
1531 if (! mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
, &d
->rel_hdr
))
1533 if (d
->rel_hdr2
!= NULL
)
1535 if (! mips_elf64_slurp_one_reloc_table (abfd
, asect
, symbols
,
1543 /* Write out the relocations. */
1546 mips_elf64_write_relocs (abfd
, sec
, data
)
1551 boolean
*failedp
= (boolean
*) data
;
1553 Elf_Internal_Shdr
*rela_hdr
;
1554 Elf64_Mips_External_Rela
*ext_rela
;
1556 asymbol
*last_sym
= 0;
1557 int last_sym_idx
= 0;
1559 /* If we have already failed, don't do anything. */
1563 if ((sec
->flags
& SEC_RELOC
) == 0)
1566 /* The linker backend writes the relocs out itself, and sets the
1567 reloc_count field to zero to inhibit writing them here. Also,
1568 sometimes the SEC_RELOC flag gets set even when there aren't any
1570 if (sec
->reloc_count
== 0)
1573 /* We can combine up to three relocs that refer to the same address
1574 if the latter relocs have no associated symbol. */
1576 for (idx
= 0; idx
< sec
->reloc_count
; idx
++)
1583 addr
= sec
->orelocation
[idx
]->address
;
1584 for (i
= 0; i
< 2; i
++)
1588 if (idx
+ 1 >= sec
->reloc_count
)
1590 r
= sec
->orelocation
[idx
+ 1];
1591 if (r
->address
!= addr
1592 || ! bfd_is_abs_section ((*r
->sym_ptr_ptr
)->section
)
1593 || (*r
->sym_ptr_ptr
)->value
!= 0)
1596 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1602 rela_hdr
= &elf_section_data (sec
)->rel_hdr
;
1604 rela_hdr
->sh_size
= rela_hdr
->sh_entsize
* count
;
1605 rela_hdr
->contents
= (PTR
) bfd_alloc (abfd
, rela_hdr
->sh_size
);
1606 if (rela_hdr
->contents
== NULL
)
1612 ext_rela
= (Elf64_Mips_External_Rela
*) rela_hdr
->contents
;
1613 for (idx
= 0; idx
< sec
->reloc_count
; idx
++, ext_rela
++)
1616 Elf64_Mips_Internal_Rela int_rela
;
1621 ptr
= sec
->orelocation
[idx
];
1623 /* The address of an ELF reloc is section relative for an object
1624 file, and absolute for an executable file or shared library.
1625 The address of a BFD reloc is always section relative. */
1626 if ((abfd
->flags
& (EXEC_P
| DYNAMIC
)) == 0)
1627 int_rela
.r_offset
= ptr
->address
;
1629 int_rela
.r_offset
= ptr
->address
+ sec
->vma
;
1631 sym
= *ptr
->sym_ptr_ptr
;
1632 if (sym
== last_sym
)
1637 n
= _bfd_elf_symbol_from_bfd_symbol (abfd
, &sym
);
1648 int_rela
.r_addend
= ptr
->addend
;
1650 int_rela
.r_ssym
= RSS_UNDEF
;
1652 if ((*ptr
->sym_ptr_ptr
)->the_bfd
->xvec
!= abfd
->xvec
1653 && ! _bfd_elf_validate_reloc (abfd
, ptr
))
1659 int_rela
.r_type
= ptr
->howto
->type
;
1660 int_rela
.r_type2
= (int) R_MIPS_NONE
;
1661 int_rela
.r_type3
= (int) R_MIPS_NONE
;
1663 for (i
= 0; i
< 2; i
++)
1667 if (idx
+ 1 >= sec
->reloc_count
)
1669 r
= sec
->orelocation
[idx
+ 1];
1670 if (r
->address
!= ptr
->address
1671 || ! bfd_is_abs_section ((*r
->sym_ptr_ptr
)->section
)
1672 || (*r
->sym_ptr_ptr
)->value
!= 0)
1675 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1678 int_rela
.r_type2
= r
->howto
->type
;
1680 int_rela
.r_type3
= r
->howto
->type
;
1685 mips_elf64_swap_reloca_out (abfd
, &int_rela
, ext_rela
);
1688 BFD_ASSERT (ext_rela
- (Elf64_Mips_External_Rela
*) rela_hdr
->contents
1692 /* Handle a 64-bit MIPS ELF specific section. */
1695 mips_elf64_section_from_shdr (abfd
, hdr
, name
)
1697 Elf_Internal_Shdr
*hdr
;
1700 if (! _bfd_mips_elf_section_from_shdr (abfd
, hdr
, name
))
1703 /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
1704 set the gp value based on what we find. We may see both
1705 SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
1706 they should agree. */
1707 if (hdr
->sh_type
== SHT_MIPS_OPTIONS
)
1709 bfd_byte
*contents
, *l
, *lend
;
1711 contents
= (bfd_byte
*) bfd_malloc (hdr
->sh_size
);
1712 if (contents
== NULL
)
1714 if (! bfd_get_section_contents (abfd
, hdr
->bfd_section
, contents
,
1715 (file_ptr
) 0, hdr
->sh_size
))
1721 lend
= contents
+ hdr
->sh_size
;
1722 while (l
+ sizeof (Elf_External_Options
) <= lend
)
1724 Elf_Internal_Options intopt
;
1726 bfd_mips_elf_swap_options_in (abfd
, (Elf_External_Options
*) l
,
1728 if (intopt
.kind
== ODK_REGINFO
)
1730 Elf64_Internal_RegInfo intreg
;
1732 bfd_mips_elf64_swap_reginfo_in
1734 ((Elf64_External_RegInfo
*)
1735 (l
+ sizeof (Elf_External_Options
))),
1737 elf_gp (abfd
) = intreg
.ri_gp_value
;
1747 /* Work over a section just before writing it out. We update the GP
1748 value in the SHT_MIPS_OPTIONS section based on the value we are
1752 mips_elf64_section_processing (abfd
, hdr
)
1754 Elf_Internal_Shdr
*hdr
;
1756 if (hdr
->sh_type
== SHT_MIPS_OPTIONS
1757 && hdr
->bfd_section
!= NULL
1758 && elf_section_data (hdr
->bfd_section
) != NULL
1759 && elf_section_data (hdr
->bfd_section
)->tdata
!= NULL
)
1761 bfd_byte
*contents
, *l
, *lend
;
1763 /* We stored the section contents in the elf_section_data tdata
1764 field in the set_section_contents routine. We save the
1765 section contents so that we don't have to read them again.
1766 At this point we know that elf_gp is set, so we can look
1767 through the section contents to see if there is an
1768 ODK_REGINFO structure. */
1770 contents
= (bfd_byte
*) elf_section_data (hdr
->bfd_section
)->tdata
;
1772 lend
= contents
+ hdr
->sh_size
;
1773 while (l
+ sizeof (Elf_External_Options
) <= lend
)
1775 Elf_Internal_Options intopt
;
1777 bfd_mips_elf_swap_options_in (abfd
, (Elf_External_Options
*) l
,
1779 if (intopt
.kind
== ODK_REGINFO
)
1786 + sizeof (Elf_External_Options
)
1787 + (sizeof (Elf64_External_RegInfo
) - 8)),
1790 bfd_h_put_64 (abfd
, elf_gp (abfd
), buf
);
1791 if (bfd_write (buf
, 1, 8, abfd
) != 8)
1798 return _bfd_mips_elf_section_processing (abfd
, hdr
);
1801 /* Irix 6 defines a brand new archive map format, so that they can
1802 have archives more than 4 GB in size. */
1804 /* Read an Irix 6 armap. */
1807 mips_elf64_slurp_armap (abfd
)
1810 struct artdata
*ardata
= bfd_ardata (abfd
);
1813 bfd_size_type i
, parsed_size
, nsymz
, stringsize
, carsym_size
, ptrsize
;
1814 struct areltdata
*mapdata
;
1815 bfd_byte int_buf
[8];
1817 bfd_byte
*raw_armap
= NULL
;
1820 ardata
->symdefs
= NULL
;
1822 /* Get the name of the first element. */
1823 arhdrpos
= bfd_tell (abfd
);
1824 i
= bfd_read ((PTR
) nextname
, 1, 16, abfd
);
1830 if (bfd_seek (abfd
, (file_ptr
) - 16, SEEK_CUR
) != 0)
1833 /* Archives with traditional armaps are still permitted. */
1834 if (strncmp (nextname
, "/ ", 16) == 0)
1835 return bfd_slurp_armap (abfd
);
1837 if (strncmp (nextname
, "/SYM64/ ", 16) != 0)
1839 bfd_has_map (abfd
) = false;
1843 mapdata
= (struct areltdata
*) _bfd_read_ar_hdr (abfd
);
1844 if (mapdata
== NULL
)
1846 parsed_size
= mapdata
->parsed_size
;
1847 bfd_release (abfd
, (PTR
) mapdata
);
1849 if (bfd_read (int_buf
, 1, 8, abfd
) != 8)
1851 if (bfd_get_error () != bfd_error_system_call
)
1852 bfd_set_error (bfd_error_malformed_archive
);
1856 nsymz
= bfd_getb64 (int_buf
);
1857 stringsize
= parsed_size
- 8 * nsymz
- 8;
1859 carsym_size
= nsymz
* sizeof (carsym
);
1860 ptrsize
= 8 * nsymz
;
1862 ardata
->symdefs
= (carsym
*) bfd_zalloc (abfd
, carsym_size
+ stringsize
+ 1);
1863 if (ardata
->symdefs
== NULL
)
1865 carsyms
= ardata
->symdefs
;
1866 stringbase
= ((char *) ardata
->symdefs
) + carsym_size
;
1868 raw_armap
= (bfd_byte
*) bfd_alloc (abfd
, ptrsize
);
1869 if (raw_armap
== NULL
)
1872 if (bfd_read (raw_armap
, 1, ptrsize
, abfd
) != ptrsize
1873 || bfd_read (stringbase
, 1, stringsize
, abfd
) != stringsize
)
1875 if (bfd_get_error () != bfd_error_system_call
)
1876 bfd_set_error (bfd_error_malformed_archive
);
1880 for (i
= 0; i
< nsymz
; i
++)
1882 carsyms
->file_offset
= bfd_getb64 (raw_armap
+ i
* 8);
1883 carsyms
->name
= stringbase
;
1884 stringbase
+= strlen (stringbase
) + 1;
1889 ardata
->symdef_count
= nsymz
;
1890 ardata
->first_file_filepos
= arhdrpos
+ sizeof (struct ar_hdr
) + parsed_size
;
1892 bfd_has_map (abfd
) = true;
1893 bfd_release (abfd
, raw_armap
);
1898 if (raw_armap
!= NULL
)
1899 bfd_release (abfd
, raw_armap
);
1900 if (ardata
->symdefs
!= NULL
)
1901 bfd_release (abfd
, ardata
->symdefs
);
1905 /* Write out an Irix 6 armap. The Irix 6 tools are supposed to be
1906 able to handle ordinary ELF armaps, but at least on Irix 6.2 the
1910 mips_elf64_write_armap (arch
, elength
, map
, symbol_count
, stridx
)
1912 unsigned int elength
;
1914 unsigned int symbol_count
;
1917 unsigned int ranlibsize
= (symbol_count
* 8) + 8;
1918 unsigned int stringsize
= stridx
;
1919 unsigned int mapsize
= stringsize
+ ranlibsize
;
1920 file_ptr archive_member_file_ptr
;
1921 bfd
*current
= arch
->archive_head
;
1928 padding
= BFD_ALIGN (mapsize
, 8) - mapsize
;
1931 /* work out where the first object file will go in the archive */
1932 archive_member_file_ptr
= (mapsize
1934 + sizeof (struct ar_hdr
)
1937 memset ((char *) (&hdr
), 0, sizeof (struct ar_hdr
));
1938 strcpy (hdr
.ar_name
, "/SYM64/");
1939 sprintf (hdr
.ar_size
, "%-10d", (int) mapsize
);
1940 sprintf (hdr
.ar_date
, "%ld", (long) time (NULL
));
1941 /* This, at least, is what Intel coff sets the values to.: */
1942 sprintf ((hdr
.ar_uid
), "%d", 0);
1943 sprintf ((hdr
.ar_gid
), "%d", 0);
1944 sprintf ((hdr
.ar_mode
), "%-7o", (unsigned) 0);
1945 strncpy (hdr
.ar_fmag
, ARFMAG
, 2);
1947 for (i
= 0; i
< sizeof (struct ar_hdr
); i
++)
1948 if (((char *) (&hdr
))[i
] == '\0')
1949 (((char *) (&hdr
))[i
]) = ' ';
1951 /* Write the ar header for this item and the number of symbols */
1953 if (bfd_write ((PTR
) &hdr
, 1, sizeof (struct ar_hdr
), arch
)
1954 != sizeof (struct ar_hdr
))
1957 bfd_putb64 (symbol_count
, buf
);
1958 if (bfd_write (buf
, 1, 8, arch
) != 8)
1961 /* Two passes, first write the file offsets for each symbol -
1962 remembering that each offset is on a two byte boundary. */
1964 /* Write out the file offset for the file associated with each
1965 symbol, and remember to keep the offsets padded out. */
1967 current
= arch
->archive_head
;
1969 while (current
!= (bfd
*) NULL
&& count
< symbol_count
)
1971 /* For each symbol which is used defined in this object, write out
1972 the object file's address in the archive */
1974 while (((bfd
*) (map
[count
]).pos
) == current
)
1976 bfd_putb64 (archive_member_file_ptr
, buf
);
1977 if (bfd_write (buf
, 1, 8, arch
) != 8)
1981 /* Add size of this archive entry */
1982 archive_member_file_ptr
+= (arelt_size (current
)
1983 + sizeof (struct ar_hdr
));
1984 /* remember about the even alignment */
1985 archive_member_file_ptr
+= archive_member_file_ptr
% 2;
1986 current
= current
->next
;
1989 /* now write the strings themselves */
1990 for (count
= 0; count
< symbol_count
; count
++)
1992 size_t len
= strlen (*map
[count
].name
) + 1;
1994 if (bfd_write (*map
[count
].name
, 1, len
, arch
) != len
)
1998 /* The spec says that this should be padded to an 8 byte boundary.
1999 However, the Irix 6.2 tools do not appear to do this. */
2000 while (padding
!= 0)
2002 if (bfd_write ("", 1, 1, arch
) != 1)
2010 /* ECOFF swapping routines. These are used when dealing with the
2011 .mdebug section, which is in the ECOFF debugging format. */
2012 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap
=
2014 /* Symbol table magic number. */
2016 /* Alignment of debugging information. E.g., 4. */
2018 /* Sizes of external symbolic information. */
2019 sizeof (struct hdr_ext
),
2020 sizeof (struct dnr_ext
),
2021 sizeof (struct pdr_ext
),
2022 sizeof (struct sym_ext
),
2023 sizeof (struct opt_ext
),
2024 sizeof (struct fdr_ext
),
2025 sizeof (struct rfd_ext
),
2026 sizeof (struct ext_ext
),
2027 /* Functions to swap in external symbolic data. */
2036 _bfd_ecoff_swap_tir_in
,
2037 _bfd_ecoff_swap_rndx_in
,
2038 /* Functions to swap out external symbolic data. */
2047 _bfd_ecoff_swap_tir_out
,
2048 _bfd_ecoff_swap_rndx_out
,
2049 /* Function to read in symbolic data. */
2050 _bfd_mips_elf_read_ecoff_info
2053 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
2054 standard ELF. This structure is used to redirect the relocation
2055 handling routines. */
2057 const struct elf_size_info mips_elf64_size_info
=
2059 sizeof (Elf64_External_Ehdr
),
2060 sizeof (Elf64_External_Phdr
),
2061 sizeof (Elf64_External_Shdr
),
2062 sizeof (Elf64_Mips_External_Rel
),
2063 sizeof (Elf64_Mips_External_Rela
),
2064 sizeof (Elf64_External_Sym
),
2065 sizeof (Elf64_External_Dyn
),
2066 sizeof (Elf_External_Note
),
2071 bfd_elf64_write_out_phdrs
,
2072 bfd_elf64_write_shdrs_and_ehdr
,
2073 mips_elf64_write_relocs
,
2074 bfd_elf64_swap_symbol_out
,
2075 mips_elf64_slurp_reloc_table
,
2076 bfd_elf64_slurp_symbol_table
,
2077 bfd_elf64_swap_dyn_in
2080 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
2081 #define TARGET_LITTLE_NAME "elf64-littlemips"
2082 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
2083 #define TARGET_BIG_NAME "elf64-bigmips"
2084 #define ELF_ARCH bfd_arch_mips
2085 #define ELF_MACHINE_CODE EM_MIPS
2086 #define ELF_MAXPAGESIZE 0x1000
2087 #define elf_backend_size_info mips_elf64_size_info
2088 #define elf_backend_object_p _bfd_mips_elf_object_p
2089 #define elf_backend_section_from_shdr mips_elf64_section_from_shdr
2090 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
2091 #define elf_backend_section_from_bfd_section \
2092 _bfd_mips_elf_section_from_bfd_section
2093 #define elf_backend_section_processing mips_elf64_section_processing
2094 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
2095 #define elf_backend_final_write_processing \
2096 _bfd_mips_elf_final_write_processing
2097 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
2099 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
2100 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
2101 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
2102 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
2103 #define bfd_elf64_bfd_copy_private_bfd_data \
2104 _bfd_mips_elf_copy_private_bfd_data
2105 #define bfd_elf64_bfd_merge_private_bfd_data \
2106 _bfd_mips_elf_merge_private_bfd_data
2107 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
2109 #define bfd_elf64_archive_functions
2110 #define bfd_elf64_archive_slurp_armap mips_elf64_slurp_armap
2111 #define bfd_elf64_archive_slurp_extended_name_table \
2112 _bfd_archive_coff_slurp_extended_name_table
2113 #define bfd_elf64_archive_construct_extended_name_table \
2114 _bfd_archive_coff_construct_extended_name_table
2115 #define bfd_elf64_archive_truncate_arname \
2116 _bfd_archive_coff_truncate_arname
2117 #define bfd_elf64_archive_write_armap mips_elf64_write_armap
2118 #define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
2119 #define bfd_elf64_archive_openr_next_archived_file \
2120 _bfd_archive_coff_openr_next_archived_file
2121 #define bfd_elf64_archive_get_elt_at_index \
2122 _bfd_archive_coff_get_elt_at_index
2123 #define bfd_elf64_archive_generic_stat_arch_elt \
2124 _bfd_archive_coff_generic_stat_arch_elt
2125 #define bfd_elf64_archive_update_armap_timestamp \
2126 _bfd_archive_coff_update_armap_timestamp
2128 #include "elf64-target.h"