1 /* MIPS-specific support for 64-bit ELF
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 Ian Lance Taylor, Cygnus Support
5 Linker support added by Mark Mitchell, CodeSourcery, LLC.
6 <mark@codesourcery.com>
8 This file is part of BFD, the Binary File Descriptor library.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 /* This file supports the 64-bit MIPS ELF ABI.
26 The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
27 overrides the usual ELF reloc handling, and handles reading and
28 writing the relocations here. */
30 /* TODO: Many things are unsupported, even if there is some code for it
31 . (which was mostly stolen from elf32-mips.c and slightly adapted).
33 . - Relocation handling for REL relocs is wrong in many cases and
35 . - Relocation handling for RELA relocs related to GOT support are
36 . also likely to be wrong.
37 . - Support for MIPS16 is untested.
38 . - Combined relocs with RSS_* entries are unsupported.
39 . - The whole GOT handling for NewABI is missing, some parts of
40 . the OldABI version is still lying around and should be removed.
50 #include "elfxx-mips.h"
53 /* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
54 use ECOFF. However, we support it anyhow for an easier changeover. */
56 #include "coff/symconst.h"
57 #include "coff/internal.h"
58 #include "coff/ecoff.h"
59 /* The 64 bit versions of the mdebug data structures are in alpha.h. */
60 #include "coff/alpha.h"
61 #define ECOFF_SIGNED_64
62 #include "ecoffswap.h"
64 static void mips_elf64_swap_reloc_in
65 PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
66 Elf64_Mips_Internal_Rel *));
67 static void mips_elf64_swap_reloca_in
68 PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
69 Elf64_Mips_Internal_Rela *));
70 static void mips_elf64_swap_reloc_out
71 PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
72 Elf64_Mips_External_Rel *));
73 static void mips_elf64_swap_reloca_out
74 PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
75 Elf64_Mips_External_Rela *));
76 static void mips_elf64_be_swap_reloc_in
77 PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rel *));
78 static void mips_elf64_be_swap_reloc_out
79 PARAMS ((bfd *, const Elf_Internal_Rel *, bfd_byte *));
80 static void mips_elf64_be_swap_reloca_in
81 PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
82 static void mips_elf64_be_swap_reloca_out
83 PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
84 static reloc_howto_type *bfd_elf64_bfd_reloc_type_lookup
85 PARAMS ((bfd *, bfd_reloc_code_real_type));
86 static reloc_howto_type *mips_elf64_rtype_to_howto
87 PARAMS ((unsigned int, boolean));
88 static void mips_elf64_info_to_howto_rel
89 PARAMS ((bfd *, arelent *, Elf64_Internal_Rel *));
90 static void mips_elf64_info_to_howto_rela
91 PARAMS ((bfd *, arelent *, Elf64_Internal_Rela *));
92 static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
93 static boolean mips_elf64_slurp_one_reloc_table
94 PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
95 static boolean mips_elf64_slurp_reloc_table
96 PARAMS ((bfd *, asection *, asymbol **, boolean));
97 static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
98 static void mips_elf64_write_rel
99 PARAMS((bfd *, asection *, Elf_Internal_Shdr *, int *, PTR));
100 static void mips_elf64_write_rela
101 PARAMS((bfd *, asection *, Elf_Internal_Shdr *, int *, PTR));
102 static bfd_reloc_status_type mips_elf64_hi16_reloc
103 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
104 static bfd_reloc_status_type mips_elf64_gprel16_reloc
105 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
106 static bfd_reloc_status_type mips_elf64_literal_reloc
107 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
108 static bfd_reloc_status_type mips_elf64_gprel32_reloc
109 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
110 static bfd_reloc_status_type mips_elf64_shift6_reloc
111 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
112 static bfd_reloc_status_type mips_elf64_got16_reloc
113 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
114 static bfd_reloc_status_type mips16_jump_reloc
115 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
116 static bfd_reloc_status_type mips16_gprel_reloc
117 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
118 static boolean mips_elf64_assign_gp PARAMS ((bfd *, bfd_vma *));
119 static bfd_reloc_status_type mips_elf64_final_gp
120 PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));
121 static boolean mips_elf64_object_p PARAMS ((bfd *));
122 static irix_compat_t elf64_mips_irix_compat PARAMS ((bfd *));
124 extern const bfd_target bfd_elf64_bigmips_vec;
125 extern const bfd_target bfd_elf64_littlemips_vec;
127 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
128 from smaller values. Start with zero, widen, *then* decrement. */
129 #define MINUS_ONE (((bfd_vma)0) - 1)
131 /* The number of local .got entries we reserve. */
132 #define MIPS_RESERVED_GOTNO (2)
134 /* The relocation table used for SHT_REL sections. */
136 static reloc_howto_type mips_elf64_howto_table_rel[] =
139 HOWTO (R_MIPS_NONE, /* type */
141 0, /* size (0 = byte, 1 = short, 2 = long) */
143 false, /* pc_relative */
145 complain_overflow_dont, /* complain_on_overflow */
146 bfd_elf_generic_reloc, /* special_function */
147 "R_MIPS_NONE", /* name */
148 false, /* partial_inplace */
151 false), /* pcrel_offset */
153 /* 16 bit relocation. */
154 HOWTO (R_MIPS_16, /* type */
156 2, /* size (0 = byte, 1 = short, 2 = long) */
158 false, /* pc_relative */
160 complain_overflow_signed, /* complain_on_overflow */
161 bfd_elf_generic_reloc, /* special_function */
162 "R_MIPS_16", /* name */
163 true, /* partial_inplace */
164 0x0000ffff, /* src_mask */
165 0x0000ffff, /* dst_mask */
166 false), /* pcrel_offset */
168 /* 32 bit relocation. */
169 HOWTO (R_MIPS_32, /* type */
171 2, /* size (0 = byte, 1 = short, 2 = long) */
173 false, /* pc_relative */
175 complain_overflow_dont, /* complain_on_overflow */
176 bfd_elf_generic_reloc, /* special_function */
177 "R_MIPS_32", /* name */
178 true, /* partial_inplace */
179 0xffffffff, /* src_mask */
180 0xffffffff, /* dst_mask */
181 false), /* pcrel_offset */
183 /* 32 bit symbol relative relocation. */
184 HOWTO (R_MIPS_REL32, /* type */
186 2, /* size (0 = byte, 1 = short, 2 = long) */
188 false, /* pc_relative */
190 complain_overflow_dont, /* complain_on_overflow */
191 bfd_elf_generic_reloc, /* special_function */
192 "R_MIPS_REL32", /* name */
193 true, /* partial_inplace */
194 0xffffffff, /* src_mask */
195 0xffffffff, /* dst_mask */
196 false), /* pcrel_offset */
198 /* 26 bit jump address. */
199 HOWTO (R_MIPS_26, /* type */
201 2, /* size (0 = byte, 1 = short, 2 = long) */
203 false, /* pc_relative */
205 complain_overflow_dont, /* complain_on_overflow */
206 /* This needs complex overflow
207 detection, because the upper 36
208 bits must match the PC + 4. */
209 bfd_elf_generic_reloc, /* special_function */
210 "R_MIPS_26", /* name */
211 true, /* partial_inplace */
212 0x03ffffff, /* src_mask */
213 0x03ffffff, /* dst_mask */
214 false), /* pcrel_offset */
216 /* R_MIPS_HI16 and R_MIPS_LO16 are unsupported for NewABI REL.
217 However, the native IRIX6 tools use them, so we try our best. */
219 /* High 16 bits of symbol value. */
220 HOWTO (R_MIPS_HI16, /* type */
222 2, /* size (0 = byte, 1 = short, 2 = long) */
224 false, /* pc_relative */
226 complain_overflow_dont, /* complain_on_overflow */
227 mips_elf64_hi16_reloc, /* special_function */
228 "R_MIPS_HI16", /* name */
229 true, /* partial_inplace */
230 0x0000ffff, /* src_mask */
231 0x0000ffff, /* dst_mask */
232 false), /* pcrel_offset */
234 /* Low 16 bits of symbol value. */
235 HOWTO (R_MIPS_LO16, /* type */
237 2, /* size (0 = byte, 1 = short, 2 = long) */
239 false, /* pc_relative */
241 complain_overflow_dont, /* complain_on_overflow */
242 bfd_elf_generic_reloc, /* special_function */
243 "R_MIPS_LO16", /* name */
244 true, /* partial_inplace */
245 0x0000ffff, /* src_mask */
246 0x0000ffff, /* dst_mask */
247 false), /* pcrel_offset */
249 /* GP relative reference. */
250 HOWTO (R_MIPS_GPREL16, /* type */
252 2, /* size (0 = byte, 1 = short, 2 = long) */
254 false, /* pc_relative */
256 complain_overflow_signed, /* complain_on_overflow */
257 mips_elf64_gprel16_reloc, /* special_function */
258 "R_MIPS_GPREL16", /* name */
259 true, /* partial_inplace */
260 0x0000ffff, /* src_mask */
261 0x0000ffff, /* dst_mask */
262 false), /* pcrel_offset */
264 /* Reference to literal section. */
265 HOWTO (R_MIPS_LITERAL, /* type */
267 2, /* size (0 = byte, 1 = short, 2 = long) */
269 false, /* pc_relative */
271 complain_overflow_signed, /* complain_on_overflow */
272 mips_elf64_literal_reloc, /* special_function */
273 "R_MIPS_LITERAL", /* name */
274 true, /* partial_inplace */
275 0x0000ffff, /* src_mask */
276 0x0000ffff, /* dst_mask */
277 false), /* pcrel_offset */
279 /* Reference to global offset table. */
280 HOWTO (R_MIPS_GOT16, /* type */
282 2, /* size (0 = byte, 1 = short, 2 = long) */
284 false, /* pc_relative */
286 complain_overflow_signed, /* complain_on_overflow */
287 mips_elf64_got16_reloc, /* special_function */
288 "R_MIPS_GOT16", /* name */
289 true, /* partial_inplace */
290 0x0000ffff, /* src_mask */
291 0x0000ffff, /* dst_mask */
292 false), /* pcrel_offset */
294 /* 16 bit PC relative reference. */
295 HOWTO (R_MIPS_PC16, /* type */
297 2, /* size (0 = byte, 1 = short, 2 = long) */
299 true, /* pc_relative */
301 complain_overflow_signed, /* complain_on_overflow */
302 bfd_elf_generic_reloc, /* special_function */
303 "R_MIPS_PC16", /* name */
304 true, /* partial_inplace */
305 0x0000ffff, /* src_mask */
306 0x0000ffff, /* dst_mask */
307 true), /* pcrel_offset */
309 /* 16 bit call through global offset table. */
310 HOWTO (R_MIPS_CALL16, /* type */
312 2, /* size (0 = byte, 1 = short, 2 = long) */
314 false, /* pc_relative */
316 complain_overflow_signed, /* complain_on_overflow */
317 bfd_elf_generic_reloc, /* special_function */
318 "R_MIPS_CALL16", /* name */
319 true, /* partial_inplace */
320 0x0000ffff, /* src_mask */
321 0x0000ffff, /* dst_mask */
322 false), /* pcrel_offset */
324 /* 32 bit GP relative reference. */
325 HOWTO (R_MIPS_GPREL32, /* type */
327 2, /* size (0 = byte, 1 = short, 2 = long) */
329 false, /* pc_relative */
331 complain_overflow_dont, /* complain_on_overflow */
332 mips_elf64_gprel32_reloc, /* special_function */
333 "R_MIPS_GPREL32", /* name */
334 true, /* partial_inplace */
335 0xffffffff, /* src_mask */
336 0xffffffff, /* dst_mask */
337 false), /* pcrel_offset */
343 /* A 5 bit shift field. */
344 HOWTO (R_MIPS_SHIFT5, /* type */
346 2, /* size (0 = byte, 1 = short, 2 = long) */
348 false, /* pc_relative */
350 complain_overflow_bitfield, /* complain_on_overflow */
351 bfd_elf_generic_reloc, /* special_function */
352 "R_MIPS_SHIFT5", /* name */
353 true, /* partial_inplace */
354 0x000007c0, /* src_mask */
355 0x000007c0, /* dst_mask */
356 false), /* pcrel_offset */
358 /* A 6 bit shift field. */
359 HOWTO (R_MIPS_SHIFT6, /* type */
361 2, /* size (0 = byte, 1 = short, 2 = long) */
363 false, /* pc_relative */
365 complain_overflow_bitfield, /* complain_on_overflow */
366 mips_elf64_shift6_reloc, /* special_function */
367 "R_MIPS_SHIFT6", /* name */
368 true, /* partial_inplace */
369 0x000007c4, /* src_mask */
370 0x000007c4, /* dst_mask */
371 false), /* pcrel_offset */
373 /* 64 bit relocation. */
374 HOWTO (R_MIPS_64, /* type */
376 4, /* size (0 = byte, 1 = short, 2 = long) */
378 false, /* pc_relative */
380 complain_overflow_dont, /* complain_on_overflow */
381 bfd_elf_generic_reloc, /* special_function */
382 "R_MIPS_64", /* name */
383 true, /* partial_inplace */
384 MINUS_ONE, /* src_mask */
385 MINUS_ONE, /* dst_mask */
386 false), /* pcrel_offset */
388 /* Displacement in the global offset table. */
389 HOWTO (R_MIPS_GOT_DISP, /* type */
391 2, /* size (0 = byte, 1 = short, 2 = long) */
393 false, /* pc_relative */
395 complain_overflow_signed, /* complain_on_overflow */
396 bfd_elf_generic_reloc, /* special_function */
397 "R_MIPS_GOT_DISP", /* name */
398 true, /* partial_inplace */
399 0x0000ffff, /* src_mask */
400 0x0000ffff, /* dst_mask */
401 false), /* pcrel_offset */
403 /* Displacement to page pointer in the global offset table. */
404 HOWTO (R_MIPS_GOT_PAGE, /* type */
406 2, /* size (0 = byte, 1 = short, 2 = long) */
408 false, /* pc_relative */
410 complain_overflow_signed, /* complain_on_overflow */
411 bfd_elf_generic_reloc, /* special_function */
412 "R_MIPS_GOT_PAGE", /* name */
413 true, /* partial_inplace */
414 0x0000ffff, /* src_mask */
415 0x0000ffff, /* dst_mask */
416 false), /* pcrel_offset */
418 /* Offset from page pointer in the global offset table. */
419 HOWTO (R_MIPS_GOT_OFST, /* type */
421 2, /* size (0 = byte, 1 = short, 2 = long) */
423 false, /* pc_relative */
425 complain_overflow_signed, /* complain_on_overflow */
426 bfd_elf_generic_reloc, /* special_function */
427 "R_MIPS_GOT_OFST", /* name */
428 true, /* partial_inplace */
429 0x0000ffff, /* src_mask */
430 0x0000ffff, /* dst_mask */
431 false), /* pcrel_offset */
433 /* High 16 bits of displacement in global offset table. */
434 HOWTO (R_MIPS_GOT_HI16, /* type */
436 2, /* size (0 = byte, 1 = short, 2 = long) */
438 false, /* pc_relative */
440 complain_overflow_dont, /* complain_on_overflow */
441 bfd_elf_generic_reloc, /* special_function */
442 "R_MIPS_GOT_HI16", /* name */
443 true, /* partial_inplace */
444 0x0000ffff, /* src_mask */
445 0x0000ffff, /* dst_mask */
446 false), /* pcrel_offset */
448 /* Low 16 bits of displacement in global offset table. */
449 HOWTO (R_MIPS_GOT_LO16, /* type */
451 2, /* size (0 = byte, 1 = short, 2 = long) */
453 false, /* pc_relative */
455 complain_overflow_dont, /* complain_on_overflow */
456 bfd_elf_generic_reloc, /* special_function */
457 "R_MIPS_GOT_LO16", /* name */
458 true, /* partial_inplace */
459 0x0000ffff, /* src_mask */
460 0x0000ffff, /* dst_mask */
461 false), /* pcrel_offset */
463 /* 64 bit substraction. */
464 HOWTO (R_MIPS_SUB, /* type */
466 4, /* size (0 = byte, 1 = short, 2 = long) */
468 false, /* pc_relative */
470 complain_overflow_dont, /* complain_on_overflow */
471 bfd_elf_generic_reloc, /* special_function */
472 "R_MIPS_SUB", /* name */
473 true, /* partial_inplace */
474 MINUS_ONE, /* src_mask */
475 MINUS_ONE, /* dst_mask */
476 false), /* pcrel_offset */
478 /* Insert the addend as an instruction. */
479 /* FIXME: Not handled correctly. */
480 HOWTO (R_MIPS_INSERT_A, /* type */
482 2, /* size (0 = byte, 1 = short, 2 = long) */
484 false, /* pc_relative */
486 complain_overflow_dont, /* complain_on_overflow */
487 bfd_elf_generic_reloc, /* special_function */
488 "R_MIPS_INSERT_A", /* name */
489 true, /* partial_inplace */
490 0xffffffff, /* src_mask */
491 0xffffffff, /* dst_mask */
492 false), /* pcrel_offset */
494 /* Insert the addend as an instruction, and change all relocations
495 to refer to the old instruction at the address. */
496 /* FIXME: Not handled correctly. */
497 HOWTO (R_MIPS_INSERT_B, /* type */
499 2, /* size (0 = byte, 1 = short, 2 = long) */
501 false, /* pc_relative */
503 complain_overflow_dont, /* complain_on_overflow */
504 bfd_elf_generic_reloc, /* special_function */
505 "R_MIPS_INSERT_B", /* name */
506 true, /* partial_inplace */
507 0xffffffff, /* src_mask */
508 0xffffffff, /* dst_mask */
509 false), /* pcrel_offset */
511 /* Delete a 32 bit instruction. */
512 /* FIXME: Not handled correctly. */
513 HOWTO (R_MIPS_DELETE, /* type */
515 2, /* size (0 = byte, 1 = short, 2 = long) */
517 false, /* pc_relative */
519 complain_overflow_dont, /* complain_on_overflow */
520 bfd_elf_generic_reloc, /* special_function */
521 "R_MIPS_DELETE", /* name */
522 true, /* partial_inplace */
523 0xffffffff, /* src_mask */
524 0xffffffff, /* dst_mask */
525 false), /* pcrel_offset */
527 /* The MIPS ELF64 ABI Draft wants us to support these for REL relocations.
529 a) It means building the addend from a R_MIPS_HIGHEST/R_MIPS_HIGHER/
530 R_MIPS_HI16/R_MIPS_LO16 sequence with varying ordering, using
532 b) No other NewABI toolchain actually emits such relocations. */
533 EMPTY_HOWTO (R_MIPS_HIGHER),
534 EMPTY_HOWTO (R_MIPS_HIGHEST),
536 /* High 16 bits of displacement in global offset table. */
537 HOWTO (R_MIPS_CALL_HI16, /* type */
539 2, /* size (0 = byte, 1 = short, 2 = long) */
541 false, /* pc_relative */
543 complain_overflow_dont, /* complain_on_overflow */
544 bfd_elf_generic_reloc, /* special_function */
545 "R_MIPS_CALL_HI16", /* name */
546 true, /* partial_inplace */
547 0x0000ffff, /* src_mask */
548 0x0000ffff, /* dst_mask */
549 false), /* pcrel_offset */
551 /* Low 16 bits of displacement in global offset table. */
552 HOWTO (R_MIPS_CALL_LO16, /* type */
554 2, /* size (0 = byte, 1 = short, 2 = long) */
556 false, /* pc_relative */
558 complain_overflow_dont, /* complain_on_overflow */
559 bfd_elf_generic_reloc, /* special_function */
560 "R_MIPS_CALL_LO16", /* name */
561 true, /* partial_inplace */
562 0x0000ffff, /* src_mask */
563 0x0000ffff, /* dst_mask */
564 false), /* pcrel_offset */
566 /* Section displacement, used by an associated event location section. */
567 HOWTO (R_MIPS_SCN_DISP, /* type */
569 2, /* size (0 = byte, 1 = short, 2 = long) */
571 false, /* pc_relative */
573 complain_overflow_dont, /* complain_on_overflow */
574 bfd_elf_generic_reloc, /* special_function */
575 "R_MIPS_SCN_DISP", /* name */
576 true, /* partial_inplace */
577 0xffffffff, /* src_mask */
578 0xffffffff, /* dst_mask */
579 false), /* pcrel_offset */
581 HOWTO (R_MIPS_REL16, /* type */
583 1, /* size (0 = byte, 1 = short, 2 = long) */
585 false, /* pc_relative */
587 complain_overflow_signed, /* complain_on_overflow */
588 bfd_elf_generic_reloc, /* special_function */
589 "R_MIPS_REL16", /* name */
590 true, /* partial_inplace */
591 0xffff, /* src_mask */
592 0xffff, /* dst_mask */
593 false), /* pcrel_offset */
595 /* These two are obsolete. */
596 EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
597 EMPTY_HOWTO (R_MIPS_PJUMP),
599 /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
600 It must be used for multigot GOT's (and only there). */
601 HOWTO (R_MIPS_RELGOT, /* type */
603 2, /* size (0 = byte, 1 = short, 2 = long) */
605 false, /* pc_relative */
607 complain_overflow_dont, /* complain_on_overflow */
608 bfd_elf_generic_reloc, /* special_function */
609 "R_MIPS_RELGOT", /* name */
610 true, /* partial_inplace */
611 0xffffffff, /* src_mask */
612 0xffffffff, /* dst_mask */
613 false), /* pcrel_offset */
615 /* Protected jump conversion. This is an optimization hint. No
616 relocation is required for correctness. */
617 HOWTO (R_MIPS_JALR, /* type */
619 2, /* size (0 = byte, 1 = short, 2 = long) */
621 false, /* pc_relative */
623 complain_overflow_dont, /* complain_on_overflow */
624 bfd_elf_generic_reloc, /* special_function */
625 "R_MIPS_JALR", /* name */
626 false, /* partial_inplace */
628 0x00000000, /* dst_mask */
629 false), /* pcrel_offset */
632 /* The relocation table used for SHT_RELA sections. */
634 static reloc_howto_type mips_elf64_howto_table_rela[] =
637 HOWTO (R_MIPS_NONE, /* type */
639 0, /* size (0 = byte, 1 = short, 2 = long) */
641 false, /* pc_relative */
643 complain_overflow_dont, /* complain_on_overflow */
644 bfd_elf_generic_reloc, /* special_function */
645 "R_MIPS_NONE", /* name */
646 false, /* partial_inplace */
649 false), /* pcrel_offset */
651 /* 16 bit relocation. */
652 HOWTO (R_MIPS_16, /* type */
654 2, /* size (0 = byte, 1 = short, 2 = long) */
656 false, /* pc_relative */
658 complain_overflow_signed, /* complain_on_overflow */
659 bfd_elf_generic_reloc, /* special_function */
660 "R_MIPS_16", /* name */
661 false, /* partial_inplace */
663 0x0000ffff, /* dst_mask */
664 false), /* pcrel_offset */
666 /* 32 bit relocation. */
667 HOWTO (R_MIPS_32, /* type */
669 2, /* size (0 = byte, 1 = short, 2 = long) */
671 false, /* pc_relative */
673 complain_overflow_dont, /* complain_on_overflow */
674 bfd_elf_generic_reloc, /* special_function */
675 "R_MIPS_32", /* name */
676 false, /* partial_inplace */
678 0xffffffff, /* dst_mask */
679 false), /* pcrel_offset */
681 /* 32 bit symbol relative relocation. */
682 HOWTO (R_MIPS_REL32, /* type */
684 2, /* size (0 = byte, 1 = short, 2 = long) */
686 false, /* pc_relative */
688 complain_overflow_dont, /* complain_on_overflow */
689 bfd_elf_generic_reloc, /* special_function */
690 "R_MIPS_REL32", /* name */
691 false, /* partial_inplace */
693 0xffffffff, /* dst_mask */
694 false), /* pcrel_offset */
696 /* 26 bit jump address. */
697 HOWTO (R_MIPS_26, /* type */
699 2, /* size (0 = byte, 1 = short, 2 = long) */
701 false, /* pc_relative */
703 complain_overflow_dont, /* complain_on_overflow */
704 /* This needs complex overflow
705 detection, because the upper 36
706 bits must match the PC + 4. */
707 bfd_elf_generic_reloc, /* special_function */
708 "R_MIPS_26", /* name */
709 false, /* partial_inplace */
711 0x03ffffff, /* dst_mask */
712 false), /* pcrel_offset */
714 /* High 16 bits of symbol value. */
715 HOWTO (R_MIPS_HI16, /* type */
717 2, /* size (0 = byte, 1 = short, 2 = long) */
719 false, /* pc_relative */
721 complain_overflow_dont, /* complain_on_overflow */
722 bfd_elf_generic_reloc, /* special_function */
723 "R_MIPS_HI16", /* name */
724 false, /* partial_inplace */
726 0x0000ffff, /* dst_mask */
727 false), /* pcrel_offset */
729 /* Low 16 bits of symbol value. */
730 HOWTO (R_MIPS_LO16, /* type */
732 2, /* size (0 = byte, 1 = short, 2 = long) */
734 false, /* pc_relative */
736 complain_overflow_dont, /* complain_on_overflow */
737 bfd_elf_generic_reloc, /* special_function */
738 "R_MIPS_LO16", /* name */
739 false, /* partial_inplace */
741 0x0000ffff, /* dst_mask */
742 false), /* pcrel_offset */
744 /* GP relative reference. */
745 HOWTO (R_MIPS_GPREL16, /* type */
747 2, /* size (0 = byte, 1 = short, 2 = long) */
749 false, /* pc_relative */
751 complain_overflow_signed, /* complain_on_overflow */
752 mips_elf64_gprel16_reloc, /* special_function */
753 "R_MIPS_GPREL16", /* name */
754 false, /* partial_inplace */
756 0x0000ffff, /* dst_mask */
757 false), /* pcrel_offset */
759 /* Reference to literal section. */
760 HOWTO (R_MIPS_LITERAL, /* type */
762 2, /* size (0 = byte, 1 = short, 2 = long) */
764 false, /* pc_relative */
766 complain_overflow_signed, /* complain_on_overflow */
767 mips_elf64_literal_reloc, /* special_function */
768 "R_MIPS_LITERAL", /* name */
769 false, /* partial_inplace */
771 0x0000ffff, /* dst_mask */
772 false), /* pcrel_offset */
774 /* Reference to global offset table. */
775 HOWTO (R_MIPS_GOT16, /* type */
777 2, /* size (0 = byte, 1 = short, 2 = long) */
779 false, /* pc_relative */
781 complain_overflow_signed, /* complain_on_overflow */
782 mips_elf64_got16_reloc, /* special_function */
783 "R_MIPS_GOT16", /* name */
784 false, /* partial_inplace */
786 0x0000ffff, /* dst_mask */
787 false), /* pcrel_offset */
789 /* 16 bit PC relative reference. */
790 HOWTO (R_MIPS_PC16, /* type */
792 2, /* size (0 = byte, 1 = short, 2 = long) */
794 true, /* pc_relative */
796 complain_overflow_signed, /* complain_on_overflow */
797 bfd_elf_generic_reloc, /* special_function */
798 "R_MIPS_PC16", /* name */
799 false, /* partial_inplace */
801 0x0000ffff, /* dst_mask */
802 true), /* pcrel_offset */
804 /* 16 bit call through global offset table. */
805 HOWTO (R_MIPS_CALL16, /* type */
807 2, /* size (0 = byte, 1 = short, 2 = long) */
809 false, /* pc_relative */
811 complain_overflow_signed, /* complain_on_overflow */
812 bfd_elf_generic_reloc, /* special_function */
813 "R_MIPS_CALL16", /* name */
814 false, /* partial_inplace */
816 0x0000ffff, /* dst_mask */
817 false), /* pcrel_offset */
819 /* 32 bit GP relative reference. */
820 HOWTO (R_MIPS_GPREL32, /* type */
822 2, /* size (0 = byte, 1 = short, 2 = long) */
824 false, /* pc_relative */
826 complain_overflow_dont, /* complain_on_overflow */
827 mips_elf64_gprel32_reloc, /* special_function */
828 "R_MIPS_GPREL32", /* name */
829 false, /* partial_inplace */
831 0xffffffff, /* dst_mask */
832 false), /* pcrel_offset */
838 /* A 5 bit shift field. */
839 HOWTO (R_MIPS_SHIFT5, /* type */
841 2, /* size (0 = byte, 1 = short, 2 = long) */
843 false, /* pc_relative */
845 complain_overflow_bitfield, /* complain_on_overflow */
846 bfd_elf_generic_reloc, /* special_function */
847 "R_MIPS_SHIFT5", /* name */
848 false, /* partial_inplace */
850 0x000007c0, /* dst_mask */
851 false), /* pcrel_offset */
853 /* A 6 bit shift field. */
854 HOWTO (R_MIPS_SHIFT6, /* type */
856 2, /* size (0 = byte, 1 = short, 2 = long) */
858 false, /* pc_relative */
860 complain_overflow_bitfield, /* complain_on_overflow */
861 mips_elf64_shift6_reloc, /* special_function */
862 "R_MIPS_SHIFT6", /* name */
863 false, /* partial_inplace */
865 0x000007c4, /* dst_mask */
866 false), /* pcrel_offset */
868 /* 64 bit relocation. */
869 HOWTO (R_MIPS_64, /* type */
871 4, /* size (0 = byte, 1 = short, 2 = long) */
873 false, /* pc_relative */
875 complain_overflow_dont, /* complain_on_overflow */
876 bfd_elf_generic_reloc, /* special_function */
877 "R_MIPS_64", /* name */
878 false, /* partial_inplace */
880 MINUS_ONE, /* dst_mask */
881 false), /* pcrel_offset */
883 /* Displacement in the global offset table. */
884 HOWTO (R_MIPS_GOT_DISP, /* type */
886 2, /* size (0 = byte, 1 = short, 2 = long) */
888 false, /* pc_relative */
890 complain_overflow_signed, /* complain_on_overflow */
891 bfd_elf_generic_reloc, /* special_function */
892 "R_MIPS_GOT_DISP", /* name */
893 false, /* partial_inplace */
895 0x0000ffff, /* dst_mask */
896 false), /* pcrel_offset */
898 /* Displacement to page pointer in the global offset table. */
899 HOWTO (R_MIPS_GOT_PAGE, /* type */
901 2, /* size (0 = byte, 1 = short, 2 = long) */
903 false, /* pc_relative */
905 complain_overflow_signed, /* complain_on_overflow */
906 bfd_elf_generic_reloc, /* special_function */
907 "R_MIPS_GOT_PAGE", /* name */
908 false, /* partial_inplace */
910 0x0000ffff, /* dst_mask */
911 false), /* pcrel_offset */
913 /* Offset from page pointer in the global offset table. */
914 HOWTO (R_MIPS_GOT_OFST, /* type */
916 2, /* size (0 = byte, 1 = short, 2 = long) */
918 false, /* pc_relative */
920 complain_overflow_signed, /* complain_on_overflow */
921 bfd_elf_generic_reloc, /* special_function */
922 "R_MIPS_GOT_OFST", /* name */
923 false, /* partial_inplace */
925 0x0000ffff, /* dst_mask */
926 false), /* pcrel_offset */
928 /* High 16 bits of displacement in global offset table. */
929 HOWTO (R_MIPS_GOT_HI16, /* type */
931 2, /* size (0 = byte, 1 = short, 2 = long) */
933 false, /* pc_relative */
935 complain_overflow_dont, /* complain_on_overflow */
936 bfd_elf_generic_reloc, /* special_function */
937 "R_MIPS_GOT_HI16", /* name */
938 false, /* partial_inplace */
940 0x0000ffff, /* dst_mask */
941 false), /* pcrel_offset */
943 /* Low 16 bits of displacement in global offset table. */
944 HOWTO (R_MIPS_GOT_LO16, /* type */
946 2, /* size (0 = byte, 1 = short, 2 = long) */
948 false, /* pc_relative */
950 complain_overflow_dont, /* complain_on_overflow */
951 bfd_elf_generic_reloc, /* special_function */
952 "R_MIPS_GOT_LO16", /* name */
953 false, /* partial_inplace */
955 0x0000ffff, /* dst_mask */
956 false), /* pcrel_offset */
958 /* 64 bit substraction. */
959 HOWTO (R_MIPS_SUB, /* type */
961 4, /* size (0 = byte, 1 = short, 2 = long) */
963 false, /* pc_relative */
965 complain_overflow_dont, /* complain_on_overflow */
966 bfd_elf_generic_reloc, /* special_function */
967 "R_MIPS_SUB", /* name */
968 false, /* partial_inplace */
970 MINUS_ONE, /* dst_mask */
971 false), /* pcrel_offset */
973 /* Insert the addend as an instruction. */
974 /* FIXME: Not handled correctly. */
975 HOWTO (R_MIPS_INSERT_A, /* type */
977 2, /* size (0 = byte, 1 = short, 2 = long) */
979 false, /* pc_relative */
981 complain_overflow_dont, /* complain_on_overflow */
982 bfd_elf_generic_reloc, /* special_function */
983 "R_MIPS_INSERT_A", /* name */
984 false, /* partial_inplace */
986 0xffffffff, /* dst_mask */
987 false), /* pcrel_offset */
989 /* Insert the addend as an instruction, and change all relocations
990 to refer to the old instruction at the address. */
991 /* FIXME: Not handled correctly. */
992 HOWTO (R_MIPS_INSERT_B, /* type */
994 2, /* size (0 = byte, 1 = short, 2 = long) */
996 false, /* pc_relative */
998 complain_overflow_dont, /* complain_on_overflow */
999 bfd_elf_generic_reloc, /* special_function */
1000 "R_MIPS_INSERT_B", /* name */
1001 false, /* partial_inplace */
1003 0xffffffff, /* dst_mask */
1004 false), /* pcrel_offset */
1006 /* Delete a 32 bit instruction. */
1007 /* FIXME: Not handled correctly. */
1008 HOWTO (R_MIPS_DELETE, /* type */
1010 2, /* size (0 = byte, 1 = short, 2 = long) */
1012 false, /* pc_relative */
1014 complain_overflow_dont, /* complain_on_overflow */
1015 bfd_elf_generic_reloc, /* special_function */
1016 "R_MIPS_DELETE", /* name */
1017 false, /* partial_inplace */
1019 0xffffffff, /* dst_mask */
1020 false), /* pcrel_offset */
1022 /* Get the higher value of a 64 bit addend. */
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 false, /* partial_inplace */
1034 0x0000ffff, /* dst_mask */
1035 false), /* pcrel_offset */
1037 /* Get the highest value of a 64 bit addend. */
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 false, /* partial_inplace */
1049 0x0000ffff, /* dst_mask */
1050 false), /* pcrel_offset */
1052 /* High 16 bits of displacement in global offset table. */
1053 HOWTO (R_MIPS_CALL_HI16, /* type */
1055 2, /* size (0 = byte, 1 = short, 2 = long) */
1057 false, /* pc_relative */
1059 complain_overflow_dont, /* complain_on_overflow */
1060 bfd_elf_generic_reloc, /* special_function */
1061 "R_MIPS_CALL_HI16", /* name */
1062 false, /* partial_inplace */
1064 0x0000ffff, /* dst_mask */
1065 false), /* pcrel_offset */
1067 /* Low 16 bits of displacement in global offset table. */
1068 HOWTO (R_MIPS_CALL_LO16, /* type */
1070 2, /* size (0 = byte, 1 = short, 2 = long) */
1072 false, /* pc_relative */
1074 complain_overflow_dont, /* complain_on_overflow */
1075 bfd_elf_generic_reloc, /* special_function */
1076 "R_MIPS_CALL_LO16", /* name */
1077 false, /* partial_inplace */
1079 0x0000ffff, /* dst_mask */
1080 false), /* pcrel_offset */
1082 /* Section displacement, used by an associated event location section. */
1083 HOWTO (R_MIPS_SCN_DISP, /* type */
1085 2, /* size (0 = byte, 1 = short, 2 = long) */
1087 false, /* pc_relative */
1089 complain_overflow_dont, /* complain_on_overflow */
1090 bfd_elf_generic_reloc, /* special_function */
1091 "R_MIPS_SCN_DISP", /* name */
1092 false, /* partial_inplace */
1094 0xffffffff, /* dst_mask */
1095 false), /* pcrel_offset */
1097 HOWTO (R_MIPS_REL16, /* type */
1099 1, /* size (0 = byte, 1 = short, 2 = long) */
1101 false, /* pc_relative */
1103 complain_overflow_signed, /* complain_on_overflow */
1104 bfd_elf_generic_reloc, /* special_function */
1105 "R_MIPS_REL16", /* name */
1106 false, /* partial_inplace */
1108 0xffff, /* dst_mask */
1109 false), /* pcrel_offset */
1111 /* These two are obsolete. */
1112 EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
1113 EMPTY_HOWTO (R_MIPS_PJUMP),
1115 /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
1116 It must be used for multigot GOT's (and only there). */
1117 HOWTO (R_MIPS_RELGOT, /* type */
1119 2, /* size (0 = byte, 1 = short, 2 = long) */
1121 false, /* pc_relative */
1123 complain_overflow_dont, /* complain_on_overflow */
1124 bfd_elf_generic_reloc, /* special_function */
1125 "R_MIPS_RELGOT", /* name */
1126 false, /* partial_inplace */
1128 0xffffffff, /* dst_mask */
1129 false), /* pcrel_offset */
1131 /* Protected jump conversion. This is an optimization hint. No
1132 relocation is required for correctness. */
1133 HOWTO (R_MIPS_JALR, /* type */
1135 2, /* size (0 = byte, 1 = short, 2 = long) */
1137 false, /* pc_relative */
1139 complain_overflow_dont, /* complain_on_overflow */
1140 bfd_elf_generic_reloc, /* special_function */
1141 "R_MIPS_JALR", /* name */
1142 false, /* partial_inplace */
1144 0x00000000, /* dst_mask */
1145 false), /* pcrel_offset */
1148 /* The reloc used for the mips16 jump instruction. */
1149 static reloc_howto_type elf_mips16_jump_howto =
1150 HOWTO (R_MIPS16_26, /* type */
1152 2, /* size (0 = byte, 1 = short, 2 = long) */
1154 false, /* pc_relative */
1156 complain_overflow_dont, /* complain_on_overflow */
1157 /* This needs complex overflow
1158 detection, because the upper four
1159 bits must match the PC. */
1160 mips16_jump_reloc, /* special_function */
1161 "R_MIPS16_26", /* name */
1162 true, /* partial_inplace */
1163 0x3ffffff, /* src_mask */
1164 0x3ffffff, /* dst_mask */
1165 false); /* pcrel_offset */
1167 /* The reloc used for the mips16 gprel instruction. */
1168 static reloc_howto_type elf_mips16_gprel_howto =
1169 HOWTO (R_MIPS16_GPREL, /* type */
1171 2, /* size (0 = byte, 1 = short, 2 = long) */
1173 false, /* pc_relative */
1175 complain_overflow_signed, /* complain_on_overflow */
1176 mips16_gprel_reloc, /* special_function */
1177 "R_MIPS16_GPREL", /* name */
1178 true, /* partial_inplace */
1179 0x07ff001f, /* src_mask */
1180 0x07ff001f, /* dst_mask */
1181 false); /* pcrel_offset */
1183 /* GNU extension to record C++ vtable hierarchy */
1184 static reloc_howto_type elf_mips_gnu_vtinherit_howto =
1185 HOWTO (R_MIPS_GNU_VTINHERIT, /* type */
1187 2, /* size (0 = byte, 1 = short, 2 = long) */
1189 false, /* pc_relative */
1191 complain_overflow_dont, /* complain_on_overflow */
1192 NULL, /* special_function */
1193 "R_MIPS_GNU_VTINHERIT", /* name */
1194 false, /* partial_inplace */
1197 false); /* pcrel_offset */
1199 /* GNU extension to record C++ vtable member usage */
1200 static reloc_howto_type elf_mips_gnu_vtentry_howto =
1201 HOWTO (R_MIPS_GNU_VTENTRY, /* type */
1203 2, /* size (0 = byte, 1 = short, 2 = long) */
1205 false, /* pc_relative */
1207 complain_overflow_dont, /* complain_on_overflow */
1208 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
1209 "R_MIPS_GNU_VTENTRY", /* name */
1210 false, /* partial_inplace */
1213 false); /* pcrel_offset */
1215 /* Swap in a MIPS 64-bit Rel reloc. */
1218 mips_elf64_swap_reloc_in (abfd, src, dst)
1220 const Elf64_Mips_External_Rel *src;
1221 Elf64_Mips_Internal_Rel *dst;
1223 dst->r_offset = H_GET_64 (abfd, src->r_offset);
1224 dst->r_sym = H_GET_32 (abfd, src->r_sym);
1225 dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1226 dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1227 dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1228 dst->r_type = H_GET_8 (abfd, src->r_type);
1231 /* Swap in a MIPS 64-bit Rela reloc. */
1234 mips_elf64_swap_reloca_in (abfd, src, dst)
1236 const Elf64_Mips_External_Rela *src;
1237 Elf64_Mips_Internal_Rela *dst;
1239 dst->r_offset = H_GET_64 (abfd, src->r_offset);
1240 dst->r_sym = H_GET_32 (abfd, src->r_sym);
1241 dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1242 dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1243 dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1244 dst->r_type = H_GET_8 (abfd, src->r_type);
1245 dst->r_addend = H_GET_S64 (abfd, src->r_addend);
1248 /* Swap out a MIPS 64-bit Rel reloc. */
1251 mips_elf64_swap_reloc_out (abfd, src, dst)
1253 const Elf64_Mips_Internal_Rel *src;
1254 Elf64_Mips_External_Rel *dst;
1256 H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1257 H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1258 H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1259 H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1260 H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1261 H_PUT_8 (abfd, src->r_type, dst->r_type);
1264 /* Swap out a MIPS 64-bit Rela reloc. */
1267 mips_elf64_swap_reloca_out (abfd, src, dst)
1269 const Elf64_Mips_Internal_Rela *src;
1270 Elf64_Mips_External_Rela *dst;
1272 H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1273 H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1274 H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1275 H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1276 H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1277 H_PUT_8 (abfd, src->r_type, dst->r_type);
1278 H_PUT_S64 (abfd, src->r_addend, dst->r_addend);
1281 /* Swap in a MIPS 64-bit Rel reloc. */
1284 mips_elf64_be_swap_reloc_in (abfd, src, dst)
1286 const bfd_byte *src;
1287 Elf_Internal_Rel *dst;
1289 Elf64_Mips_Internal_Rel mirel;
1291 mips_elf64_swap_reloc_in (abfd,
1292 (const Elf64_Mips_External_Rel *) src,
1295 dst[0].r_offset = mirel.r_offset;
1296 dst[0].r_info = ELF64_R_INFO (mirel.r_sym, mirel.r_type);
1297 dst[1].r_offset = mirel.r_offset;
1298 dst[1].r_info = ELF64_R_INFO (mirel.r_ssym, mirel.r_type2);
1299 dst[2].r_offset = mirel.r_offset;
1300 dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirel.r_type3);
1303 /* Swap in a MIPS 64-bit Rela reloc. */
1306 mips_elf64_be_swap_reloca_in (abfd, src, dst)
1308 const bfd_byte *src;
1309 Elf_Internal_Rela *dst;
1311 Elf64_Mips_Internal_Rela mirela;
1313 mips_elf64_swap_reloca_in (abfd,
1314 (const Elf64_Mips_External_Rela *) src,
1317 dst[0].r_offset = mirela.r_offset;
1318 dst[0].r_info = ELF64_R_INFO (mirela.r_sym, mirela.r_type);
1319 dst[0].r_addend = mirela.r_addend;
1320 dst[1].r_offset = mirela.r_offset;
1321 dst[1].r_info = ELF64_R_INFO (mirela.r_ssym, mirela.r_type2);
1322 dst[1].r_addend = 0;
1323 dst[2].r_offset = mirela.r_offset;
1324 dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirela.r_type3);
1325 dst[2].r_addend = 0;
1328 /* Swap out a MIPS 64-bit Rel reloc. */
1331 mips_elf64_be_swap_reloc_out (abfd, src, dst)
1333 const Elf_Internal_Rel *src;
1336 Elf64_Mips_Internal_Rel mirel;
1338 mirel.r_offset = src[0].r_offset;
1339 BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1341 BFD_ASSERT(src[0].r_offset == src[2].r_offset);
1344 mirel.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1345 mirel.r_sym = ELF64_R_SYM (src[0].r_info);
1346 mirel.r_type2 = ELF64_MIPS_R_TYPE (src[1].r_info);
1347 mirel.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1348 mirel.r_type3 = ELF64_MIPS_R_TYPE (src[2].r_info);
1350 mips_elf64_swap_reloc_out (abfd, &mirel,
1351 (Elf64_Mips_External_Rel *) dst);
1354 /* Swap out a MIPS 64-bit Rela reloc. */
1357 mips_elf64_be_swap_reloca_out (abfd, src, dst)
1359 const Elf_Internal_Rela *src;
1362 Elf64_Mips_Internal_Rela mirela;
1364 mirela.r_offset = src[0].r_offset;
1365 BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1366 BFD_ASSERT(src[0].r_offset == src[2].r_offset);
1368 mirela.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1369 mirela.r_sym = ELF64_R_SYM (src[0].r_info);
1370 mirela.r_addend = src[0].r_addend;
1371 BFD_ASSERT(src[1].r_addend == 0);
1372 BFD_ASSERT(src[2].r_addend == 0);
1374 mirela.r_type2 = ELF64_MIPS_R_TYPE (src[1].r_info);
1375 mirela.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1376 mirela.r_type3 = ELF64_MIPS_R_TYPE (src[2].r_info);
1378 mips_elf64_swap_reloca_out (abfd, &mirela,
1379 (Elf64_Mips_External_Rela *) dst);
1382 /* Do a R_MIPS_HI16 relocation. */
1384 static bfd_reloc_status_type
1385 mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data, input_section,
1386 output_bfd, error_message)
1387 bfd *abfd ATTRIBUTE_UNUSED;
1388 arelent *reloc_entry;
1390 PTR data ATTRIBUTE_UNUSED;
1391 asection *input_section;
1393 char **error_message ATTRIBUTE_UNUSED;
1395 /* If we're relocating, and this is an external symbol, we don't
1396 want to change anything. */
1397 if (output_bfd != (bfd *) NULL
1398 && (symbol->flags & BSF_SECTION_SYM) == 0
1399 && (! reloc_entry->howto->partial_inplace
1400 || reloc_entry->addend == 0))
1402 reloc_entry->address += input_section->output_offset;
1403 return bfd_reloc_ok;
1406 if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
1407 reloc_entry->addend += 0x8000;
1409 return bfd_reloc_continue;
1412 /* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset
1413 table used for PIC code. If the symbol is an external symbol, the
1414 instruction is modified to contain the offset of the appropriate
1415 entry in the global offset table. If the symbol is a section
1416 symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
1417 addends are combined to form the real addend against the section
1418 symbol; the GOT16 is modified to contain the offset of an entry in
1419 the global offset table, and the LO16 is modified to offset it
1420 appropriately. Thus an offset larger than 16 bits requires a
1421 modified value in the global offset table.
1423 This implementation suffices for the assembler, but the linker does
1424 not yet know how to create global offset tables. */
1426 static bfd_reloc_status_type
1427 mips_elf64_got16_reloc (abfd, reloc_entry, symbol, data, input_section,
1428 output_bfd, error_message)
1430 arelent *reloc_entry;
1433 asection *input_section;
1435 char **error_message;
1437 /* If we're relocating, and this is a local symbol, we can handle it
1438 just like an R_MIPS_HI16. */
1439 if (output_bfd != (bfd *) NULL
1440 && (symbol->flags & BSF_SECTION_SYM) != 0)
1441 return mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data,
1442 input_section, output_bfd, error_message);
1445 /* Otherwise we try to handle it as R_MIPS_GOT_DISP. */
1446 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
1447 input_section, output_bfd, error_message);
1450 /* Set the GP value for OUTPUT_BFD. Returns false if this is a
1451 dangerous relocation. */
1454 mips_elf64_assign_gp (output_bfd, pgp)
1462 /* If we've already figured out what GP will be, just return it. */
1463 *pgp = _bfd_get_gp_value (output_bfd);
1467 count = bfd_get_symcount (output_bfd);
1468 sym = bfd_get_outsymbols (output_bfd);
1470 /* The linker script will have created a symbol named `_gp' with the
1471 appropriate value. */
1472 if (sym == (asymbol **) NULL)
1476 for (i = 0; i < count; i++, sym++)
1478 register const char *name;
1480 name = bfd_asymbol_name (*sym);
1481 if (*name == '_' && strcmp (name, "_gp") == 0)
1483 *pgp = bfd_asymbol_value (*sym);
1484 _bfd_set_gp_value (output_bfd, *pgp);
1492 /* Only get the error once. */
1494 _bfd_set_gp_value (output_bfd, *pgp);
1501 /* We have to figure out the gp value, so that we can adjust the
1502 symbol value correctly. We look up the symbol _gp in the output
1503 BFD. If we can't find it, we're stuck. We cache it in the ELF
1504 target data. We don't need to adjust the symbol value for an
1505 external symbol if we are producing relocateable output. */
1507 static bfd_reloc_status_type
1508 mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message, pgp)
1511 boolean relocateable;
1512 char **error_message;
1515 if (bfd_is_und_section (symbol->section)
1519 return bfd_reloc_undefined;
1522 *pgp = _bfd_get_gp_value (output_bfd);
1525 || (symbol->flags & BSF_SECTION_SYM) != 0))
1529 /* Make up a value. */
1530 *pgp = symbol->section->output_section->vma /*+ 0x4000*/;
1531 _bfd_set_gp_value (output_bfd, *pgp);
1533 else if (!mips_elf64_assign_gp (output_bfd, pgp))
1536 (char *) _("GP relative relocation when _gp not defined");
1537 return bfd_reloc_dangerous;
1541 return bfd_reloc_ok;
1544 /* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must
1545 become the offset from the gp register. */
1547 static bfd_reloc_status_type
1548 mips_elf64_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
1549 output_bfd, error_message)
1551 arelent *reloc_entry;
1554 asection *input_section;
1556 char **error_message;
1558 boolean relocateable;
1559 bfd_reloc_status_type ret;
1562 /* If we're relocating, and this is an external symbol with no
1563 addend, we don't want to change anything. We will only have an
1564 addend if this is a newly created reloc, not read from an ELF
1566 if (output_bfd != (bfd *) NULL
1567 && (symbol->flags & BSF_SECTION_SYM) == 0
1568 && (! reloc_entry->howto->partial_inplace
1569 || reloc_entry->addend == 0))
1571 reloc_entry->address += input_section->output_offset;
1572 return bfd_reloc_ok;
1575 if (output_bfd != (bfd *) NULL)
1576 relocateable = true;
1579 relocateable = false;
1580 output_bfd = symbol->section->output_section->owner;
1583 ret = mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
1585 if (ret != bfd_reloc_ok)
1588 return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1589 input_section, relocateable,
1593 /* Do a R_MIPS_LITERAL relocation. */
1595 static bfd_reloc_status_type
1596 mips_elf64_literal_reloc (abfd, reloc_entry, symbol, data, input_section,
1597 output_bfd, error_message)
1599 arelent *reloc_entry;
1602 asection *input_section;
1604 char **error_message;
1606 boolean relocateable;
1607 bfd_reloc_status_type ret;
1610 /* If we're relocating, and this is an external symbol, we don't
1611 want to change anything. */
1612 if (output_bfd != (bfd *) NULL
1613 && (symbol->flags & BSF_SECTION_SYM) == 0
1614 && (! reloc_entry->howto->partial_inplace
1615 || reloc_entry->addend == 0))
1617 reloc_entry->address += input_section->output_offset;
1618 return bfd_reloc_ok;
1621 /* FIXME: The entries in the .lit8 and .lit4 sections should be merged. */
1622 if (output_bfd != (bfd *) NULL)
1623 relocateable = true;
1626 relocateable = false;
1627 output_bfd = symbol->section->output_section->owner;
1630 ret = mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
1632 if (ret != bfd_reloc_ok)
1635 return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1636 input_section, relocateable,
1640 /* Do a R_MIPS_GPREL32 relocation. This is a 32 bit value which must
1641 become the offset from the gp register. */
1643 static bfd_reloc_status_type
1644 mips_elf64_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
1645 output_bfd, error_message)
1647 arelent *reloc_entry;
1650 asection *input_section;
1652 char **error_message;
1654 boolean relocateable;
1655 bfd_reloc_status_type ret;
1660 /* If we're relocating, and this is an external symbol with no
1661 addend, we don't want to change anything. We will only have an
1662 addend if this is a newly created reloc, not read from an ELF
1664 if (output_bfd != (bfd *) NULL
1665 && (symbol->flags & BSF_SECTION_SYM) == 0
1666 && reloc_entry->addend == 0)
1668 *error_message = (char *)
1669 _("32bits gp relative relocation occurs for an external symbol");
1670 return bfd_reloc_outofrange;
1673 if (output_bfd != (bfd *) NULL)
1675 relocateable = true;
1676 gp = _bfd_get_gp_value (output_bfd);
1680 relocateable = false;
1681 output_bfd = symbol->section->output_section->owner;
1683 ret = mips_elf64_final_gp (output_bfd, symbol, relocateable,
1684 error_message, &gp);
1685 if (ret != bfd_reloc_ok)
1689 if (bfd_is_com_section (symbol->section))
1692 relocation = symbol->value;
1694 relocation += symbol->section->output_section->vma;
1695 relocation += symbol->section->output_offset;
1697 if (reloc_entry->address > input_section->_cooked_size)
1698 return bfd_reloc_outofrange;
1700 if (reloc_entry->howto->src_mask == 0)
1702 /* This case arises with the 64-bit MIPS ELF ABI. */
1706 val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1708 /* Set val to the offset into the section or symbol. */
1709 val += reloc_entry->addend;
1711 /* Adjust val for the final section location and GP value. If we
1712 are producing relocateable output, we don't want to do this for
1713 an external symbol. */
1715 || (symbol->flags & BSF_SECTION_SYM) != 0)
1716 val += relocation - gp;
1718 bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
1721 reloc_entry->address += input_section->output_offset;
1723 return bfd_reloc_ok;
1726 /* Do a R_MIPS_SHIFT6 relocation. The MSB of the shift is stored at bit 2,
1727 the rest is at bits 6-10. The bitpos already got right by the howto. */
1729 static bfd_reloc_status_type
1730 mips_elf64_shift6_reloc (abfd, reloc_entry, symbol, data, input_section,
1731 output_bfd, error_message)
1732 bfd *abfd ATTRIBUTE_UNUSED;
1733 arelent *reloc_entry;
1735 PTR data ATTRIBUTE_UNUSED;
1736 asection *input_section;
1738 char **error_message ATTRIBUTE_UNUSED;
1740 /* If we're relocating, and this is an external symbol, we don't
1741 want to change anything. */
1742 if (output_bfd != (bfd *) NULL
1743 && (symbol->flags & BSF_SECTION_SYM) == 0
1744 && (! reloc_entry->howto->partial_inplace
1745 || reloc_entry->addend == 0))
1747 reloc_entry->address += input_section->output_offset;
1748 return bfd_reloc_ok;
1751 reloc_entry->addend = (reloc_entry->addend & 0x00007c0)
1752 | (reloc_entry->addend & 0x00000800) >> 9;
1754 return bfd_reloc_continue;
1757 /* Handle a mips16 jump. */
1759 static bfd_reloc_status_type
1760 mips16_jump_reloc (abfd, reloc_entry, symbol, data, input_section,
1761 output_bfd, error_message)
1762 bfd *abfd ATTRIBUTE_UNUSED;
1763 arelent *reloc_entry;
1765 PTR data ATTRIBUTE_UNUSED;
1766 asection *input_section;
1768 char **error_message ATTRIBUTE_UNUSED;
1770 if (output_bfd != (bfd *) NULL
1771 && (symbol->flags & BSF_SECTION_SYM) == 0
1772 && (! reloc_entry->howto->partial_inplace
1773 || reloc_entry->addend == 0))
1775 reloc_entry->address += input_section->output_offset;
1776 return bfd_reloc_ok;
1781 static boolean warned;
1784 (*_bfd_error_handler)
1785 (_("Linking mips16 objects into %s format is not supported"),
1786 bfd_get_target (input_section->output_section->owner));
1790 return bfd_reloc_undefined;
1793 /* Handle a mips16 GP relative reloc. */
1795 static bfd_reloc_status_type
1796 mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section,
1797 output_bfd, error_message)
1799 arelent *reloc_entry;
1802 asection *input_section;
1804 char **error_message;
1806 boolean relocateable;
1807 bfd_reloc_status_type ret;
1809 unsigned short extend, insn;
1810 unsigned long final;
1812 /* If we're relocating, and this is an external symbol with no
1813 addend, we don't want to change anything. We will only have an
1814 addend if this is a newly created reloc, not read from an ELF
1816 if (output_bfd != NULL
1817 && (symbol->flags & BSF_SECTION_SYM) == 0
1818 && reloc_entry->addend == 0)
1820 reloc_entry->address += input_section->output_offset;
1821 return bfd_reloc_ok;
1824 if (output_bfd != NULL)
1825 relocateable = true;
1828 relocateable = false;
1829 output_bfd = symbol->section->output_section->owner;
1832 ret = mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
1834 if (ret != bfd_reloc_ok)
1837 if (reloc_entry->address > input_section->_cooked_size)
1838 return bfd_reloc_outofrange;
1840 /* Pick up the mips16 extend instruction and the real instruction. */
1841 extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
1842 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
1844 /* Stuff the current addend back as a 32 bit value, do the usual
1845 relocation, and then clean up. */
1847 (bfd_vma) (((extend & 0x1f) << 11)
1850 (bfd_byte *) data + reloc_entry->address);
1852 ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1853 input_section, relocateable, data, gp);
1855 final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1857 (bfd_vma) ((extend & 0xf800)
1858 | ((final >> 11) & 0x1f)
1860 (bfd_byte *) data + reloc_entry->address);
1862 (bfd_vma) ((insn & 0xffe0)
1864 (bfd_byte *) data + reloc_entry->address + 2);
1869 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1871 struct elf_reloc_map {
1872 bfd_reloc_code_real_type bfd_val;
1873 enum elf_mips_reloc_type elf_val;
1876 static const struct elf_reloc_map mips_reloc_map[] =
1878 { BFD_RELOC_NONE, R_MIPS_NONE },
1879 { BFD_RELOC_16, R_MIPS_16 },
1880 { BFD_RELOC_32, R_MIPS_32 },
1881 /* There is no BFD reloc for R_MIPS_REL32. */
1882 { BFD_RELOC_64, R_MIPS_64 },
1883 { BFD_RELOC_CTOR, R_MIPS_64 },
1884 { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
1885 { BFD_RELOC_HI16_S, R_MIPS_HI16 },
1886 { BFD_RELOC_LO16, R_MIPS_LO16 },
1887 { BFD_RELOC_GPREL16, R_MIPS_GPREL16 },
1888 { BFD_RELOC_GPREL32, R_MIPS_GPREL32 },
1889 { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
1890 { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
1891 { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
1892 { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
1893 { BFD_RELOC_MIPS_SHIFT5, R_MIPS_SHIFT5 },
1894 { BFD_RELOC_MIPS_SHIFT6, R_MIPS_SHIFT6 },
1895 { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP },
1896 { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
1897 { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
1898 { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
1899 { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
1900 { BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
1901 { BFD_RELOC_MIPS_INSERT_A, R_MIPS_INSERT_A },
1902 { BFD_RELOC_MIPS_INSERT_B, R_MIPS_INSERT_B },
1903 { BFD_RELOC_MIPS_DELETE, R_MIPS_DELETE },
1904 { BFD_RELOC_MIPS_HIGHEST, R_MIPS_HIGHEST },
1905 { BFD_RELOC_MIPS_HIGHER, R_MIPS_HIGHER },
1906 { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
1907 { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
1908 { BFD_RELOC_MIPS_SCN_DISP, R_MIPS_SCN_DISP },
1909 { BFD_RELOC_MIPS_REL16, R_MIPS_REL16 },
1910 /* Use of R_MIPS_ADD_IMMEDIATE and R_MIPS_PJUMP is deprecated. */
1911 { BFD_RELOC_MIPS_RELGOT, R_MIPS_RELGOT },
1912 { BFD_RELOC_MIPS_JALR, R_MIPS_JALR }
1915 /* Given a BFD reloc type, return a howto structure. */
1917 static reloc_howto_type *
1918 bfd_elf64_bfd_reloc_type_lookup (abfd, code)
1919 bfd *abfd ATTRIBUTE_UNUSED;
1920 bfd_reloc_code_real_type code;
1923 /* FIXME: We default to RELA here instead of choosing the right
1924 relocation variant. */
1925 reloc_howto_type *howto_table = mips_elf64_howto_table_rela;
1927 for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map);
1930 if (mips_reloc_map[i].bfd_val == code)
1931 return &howto_table[(int) mips_reloc_map[i].elf_val];
1936 case BFD_RELOC_MIPS16_JMP:
1937 return &elf_mips16_jump_howto;
1938 case BFD_RELOC_MIPS16_GPREL:
1939 return &elf_mips16_gprel_howto;
1940 case BFD_RELOC_VTABLE_INHERIT:
1941 return &elf_mips_gnu_vtinherit_howto;
1942 case BFD_RELOC_VTABLE_ENTRY:
1943 return &elf_mips_gnu_vtentry_howto;
1945 bfd_set_error (bfd_error_bad_value);
1950 /* Given a MIPS Elf64_Internal_Rel, fill in an arelent structure. */
1952 static reloc_howto_type *
1953 mips_elf64_rtype_to_howto (r_type, rela_p)
1954 unsigned int r_type;
1960 return &elf_mips16_jump_howto;
1961 case R_MIPS16_GPREL:
1962 return &elf_mips16_gprel_howto;
1963 case R_MIPS_GNU_VTINHERIT:
1964 return &elf_mips_gnu_vtinherit_howto;
1965 case R_MIPS_GNU_VTENTRY:
1966 return &elf_mips_gnu_vtentry_howto;
1968 BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
1970 return &mips_elf64_howto_table_rela[r_type];
1972 return &mips_elf64_howto_table_rel[r_type];
1977 /* Prevent relocation handling by bfd for MIPS ELF64. */
1980 mips_elf64_info_to_howto_rel (abfd, cache_ptr, dst)
1981 bfd *abfd ATTRIBUTE_UNUSED;
1982 arelent *cache_ptr ATTRIBUTE_UNUSED;
1983 Elf64_Internal_Rel *dst ATTRIBUTE_UNUSED;
1989 mips_elf64_info_to_howto_rela (abfd, cache_ptr, dst)
1990 bfd *abfd ATTRIBUTE_UNUSED;
1991 arelent *cache_ptr ATTRIBUTE_UNUSED;
1992 Elf64_Internal_Rela *dst ATTRIBUTE_UNUSED;
1997 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1998 to three relocs, we must tell the user to allocate more space. */
2001 mips_elf64_get_reloc_upper_bound (abfd, sec)
2002 bfd *abfd ATTRIBUTE_UNUSED;
2005 return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
2008 /* Read the relocations from one reloc section. */
2011 mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
2015 const Elf_Internal_Shdr *rel_hdr;
2017 PTR allocated = NULL;
2018 bfd_byte *native_relocs;
2024 reloc_howto_type *howto_table;
2026 allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
2027 if (allocated == NULL)
2030 if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
2031 || (bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
2034 native_relocs = (bfd_byte *) allocated;
2036 relents = asect->relocation + asect->reloc_count;
2038 entsize = rel_hdr->sh_entsize;
2039 BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
2040 || entsize == sizeof (Elf64_Mips_External_Rela));
2042 count = rel_hdr->sh_size / entsize;
2044 if (entsize == sizeof (Elf64_Mips_External_Rel))
2045 howto_table = mips_elf64_howto_table_rel;
2047 howto_table = mips_elf64_howto_table_rela;
2050 for (i = 0; i < count; i++, native_relocs += entsize)
2052 Elf64_Mips_Internal_Rela rela;
2053 boolean used_sym, used_ssym;
2056 if (entsize == sizeof (Elf64_Mips_External_Rela))
2057 mips_elf64_swap_reloca_in (abfd,
2058 (Elf64_Mips_External_Rela *) native_relocs,
2062 Elf64_Mips_Internal_Rel rel;
2064 mips_elf64_swap_reloc_in (abfd,
2065 (Elf64_Mips_External_Rel *) native_relocs,
2067 rela.r_offset = rel.r_offset;
2068 rela.r_sym = rel.r_sym;
2069 rela.r_ssym = rel.r_ssym;
2070 rela.r_type3 = rel.r_type3;
2071 rela.r_type2 = rel.r_type2;
2072 rela.r_type = rel.r_type;
2076 /* Each entry represents up to three actual relocations. */
2080 for (ir = 0; ir < 3; ir++)
2082 enum elf_mips_reloc_type type;
2089 type = (enum elf_mips_reloc_type) rela.r_type;
2092 type = (enum elf_mips_reloc_type) rela.r_type2;
2095 type = (enum elf_mips_reloc_type) rela.r_type3;
2099 if (type == R_MIPS_NONE)
2101 /* There are no more relocations in this entry. If this
2102 is the first entry, we need to generate a dummy
2103 relocation so that the generic linker knows that
2104 there has been a break in the sequence of relocations
2105 applying to a particular address. */
2108 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2109 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2110 relent->address = rela.r_offset;
2112 relent->address = rela.r_offset - asect->vma;
2114 relent->howto = &howto_table[(int) R_MIPS_NONE];
2120 /* Some types require symbols, whereas some do not. */
2124 case R_MIPS_LITERAL:
2125 case R_MIPS_INSERT_A:
2126 case R_MIPS_INSERT_B:
2128 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2134 if (rela.r_sym == 0)
2135 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2140 ps = symbols + rela.r_sym - 1;
2142 if ((s->flags & BSF_SECTION_SYM) == 0)
2143 relent->sym_ptr_ptr = ps;
2145 relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
2150 else if (! used_ssym)
2152 switch (rela.r_ssym)
2155 relent->sym_ptr_ptr =
2156 bfd_abs_section_ptr->symbol_ptr_ptr;
2162 /* FIXME: I think these need to be handled using
2163 special howto structures. */
2175 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2180 /* The address of an ELF reloc is section relative for an
2181 object file, and absolute for an executable file or
2182 shared library. The address of a BFD reloc is always
2183 section relative. */
2184 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2185 relent->address = rela.r_offset;
2187 relent->address = rela.r_offset - asect->vma;
2189 relent->addend = rela.r_addend;
2191 relent->howto = &howto_table[(int) type];
2197 asect->reloc_count += relent - relents;
2199 if (allocated != NULL)
2205 if (allocated != NULL)
2210 /* Read the relocations. On Irix 6, there can be two reloc sections
2211 associated with a single data section. */
2214 mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
2221 struct bfd_elf_section_data * const d = elf_section_data (asect);
2225 bfd_set_error (bfd_error_invalid_operation);
2229 if (asect->relocation != NULL
2230 || (asect->flags & SEC_RELOC) == 0
2231 || asect->reloc_count == 0)
2234 /* Allocate space for 3 arelent structures for each Rel structure. */
2235 amt = asect->reloc_count;
2236 amt *= 3 * sizeof (arelent);
2237 asect->relocation = (arelent *) bfd_alloc (abfd, amt);
2238 if (asect->relocation == NULL)
2241 /* The slurp_one_reloc_table routine increments reloc_count. */
2242 asect->reloc_count = 0;
2244 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
2246 if (d->rel_hdr2 != NULL)
2248 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
2256 /* Write out the relocations. */
2259 mips_elf64_write_relocs (abfd, sec, data)
2264 boolean *failedp = (boolean *) data;
2266 Elf_Internal_Shdr *rel_hdr;
2269 /* If we have already failed, don't do anything. */
2273 if ((sec->flags & SEC_RELOC) == 0)
2276 /* The linker backend writes the relocs out itself, and sets the
2277 reloc_count field to zero to inhibit writing them here. Also,
2278 sometimes the SEC_RELOC flag gets set even when there aren't any
2280 if (sec->reloc_count == 0)
2283 /* We can combine up to three relocs that refer to the same address
2284 if the latter relocs have no associated symbol. */
2286 for (idx = 0; idx < sec->reloc_count; idx++)
2293 addr = sec->orelocation[idx]->address;
2294 for (i = 0; i < 2; i++)
2298 if (idx + 1 >= sec->reloc_count)
2300 r = sec->orelocation[idx + 1];
2301 if (r->address != addr
2302 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2303 || (*r->sym_ptr_ptr)->value != 0)
2306 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2312 rel_hdr = &elf_section_data (sec)->rel_hdr;
2314 /* Do the actual relocation. */
2316 if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rel))
2317 mips_elf64_write_rel (abfd, sec, rel_hdr, &count, data);
2318 else if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rela))
2319 mips_elf64_write_rela (abfd, sec, rel_hdr, &count, data);
2325 mips_elf64_write_rel (abfd, sec, rel_hdr, count, data)
2328 Elf_Internal_Shdr *rel_hdr;
2332 boolean *failedp = (boolean *) data;
2333 Elf64_Mips_External_Rel *ext_rel;
2335 asymbol *last_sym = 0;
2336 int last_sym_idx = 0;
2338 rel_hdr->sh_size = (bfd_vma)(rel_hdr->sh_entsize * *count);
2339 rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size);
2340 if (rel_hdr->contents == NULL)
2346 ext_rel = (Elf64_Mips_External_Rel *) rel_hdr->contents;
2347 for (idx = 0; idx < sec->reloc_count; idx++, ext_rel++)
2350 Elf64_Mips_Internal_Rel int_rel;
2355 ptr = sec->orelocation[idx];
2357 /* The address of an ELF reloc is section relative for an object
2358 file, and absolute for an executable file or shared library.
2359 The address of a BFD reloc is always section relative. */
2360 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2361 int_rel.r_offset = ptr->address;
2363 int_rel.r_offset = ptr->address + sec->vma;
2365 sym = *ptr->sym_ptr_ptr;
2366 if (sym == last_sym)
2371 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2381 int_rel.r_ssym = RSS_UNDEF;
2383 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2384 && ! _bfd_elf_validate_reloc (abfd, ptr))
2390 int_rel.r_type = ptr->howto->type;
2391 int_rel.r_type2 = (int) R_MIPS_NONE;
2392 int_rel.r_type3 = (int) R_MIPS_NONE;
2394 for (i = 0; i < 2; i++)
2398 if (idx + 1 >= sec->reloc_count)
2400 r = sec->orelocation[idx + 1];
2401 if (r->address != ptr->address
2402 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2403 || (*r->sym_ptr_ptr)->value != 0)
2406 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2409 int_rel.r_type2 = r->howto->type;
2411 int_rel.r_type3 = r->howto->type;
2416 mips_elf64_swap_reloc_out (abfd, &int_rel, ext_rel);
2419 BFD_ASSERT (ext_rel - (Elf64_Mips_External_Rel *) rel_hdr->contents
2424 mips_elf64_write_rela (abfd, sec, rela_hdr, count, data)
2427 Elf_Internal_Shdr *rela_hdr;
2431 boolean *failedp = (boolean *) data;
2432 Elf64_Mips_External_Rela *ext_rela;
2434 asymbol *last_sym = 0;
2435 int last_sym_idx = 0;
2437 rela_hdr->sh_size = (bfd_vma)(rela_hdr->sh_entsize * *count);
2438 rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
2439 if (rela_hdr->contents == NULL)
2445 ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
2446 for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
2449 Elf64_Mips_Internal_Rela int_rela;
2454 ptr = sec->orelocation[idx];
2456 /* The address of an ELF reloc is section relative for an object
2457 file, and absolute for an executable file or shared library.
2458 The address of a BFD reloc is always section relative. */
2459 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2460 int_rela.r_offset = ptr->address;
2462 int_rela.r_offset = ptr->address + sec->vma;
2464 sym = *ptr->sym_ptr_ptr;
2465 if (sym == last_sym)
2470 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2480 int_rela.r_addend = ptr->addend;
2481 int_rela.r_ssym = RSS_UNDEF;
2483 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2484 && ! _bfd_elf_validate_reloc (abfd, ptr))
2490 int_rela.r_type = ptr->howto->type;
2491 int_rela.r_type2 = (int) R_MIPS_NONE;
2492 int_rela.r_type3 = (int) R_MIPS_NONE;
2494 for (i = 0; i < 2; i++)
2498 if (idx + 1 >= sec->reloc_count)
2500 r = sec->orelocation[idx + 1];
2501 if (r->address != ptr->address
2502 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2503 || (*r->sym_ptr_ptr)->value != 0)
2506 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2509 int_rela.r_type2 = r->howto->type;
2511 int_rela.r_type3 = r->howto->type;
2516 mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
2519 BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
2523 /* Set the right machine number for a MIPS ELF file. */
2526 mips_elf64_object_p (abfd)
2531 /* Irix 6 is broken. Object file symbol tables are not always
2532 sorted correctly such that local symbols precede global symbols,
2533 and the sh_info field in the symbol table is not always right. */
2534 if (elf64_mips_irix_compat (abfd) != ict_none)
2535 elf_bad_symtab (abfd) = true;
2537 mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags);
2538 bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach);
2542 /* Depending on the target vector we generate some version of Irix
2543 executables or "normal" MIPS ELF ABI executables. */
2544 static irix_compat_t
2545 elf64_mips_irix_compat (abfd)
2548 if ((abfd->xvec == &bfd_elf64_bigmips_vec)
2549 || (abfd->xvec == &bfd_elf64_littlemips_vec))
2555 /* ECOFF swapping routines. These are used when dealing with the
2556 .mdebug section, which is in the ECOFF debugging format. */
2557 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
2559 /* Symbol table magic number. */
2561 /* Alignment of debugging information. E.g., 4. */
2563 /* Sizes of external symbolic information. */
2564 sizeof (struct hdr_ext),
2565 sizeof (struct dnr_ext),
2566 sizeof (struct pdr_ext),
2567 sizeof (struct sym_ext),
2568 sizeof (struct opt_ext),
2569 sizeof (struct fdr_ext),
2570 sizeof (struct rfd_ext),
2571 sizeof (struct ext_ext),
2572 /* Functions to swap in external symbolic data. */
2581 _bfd_ecoff_swap_tir_in,
2582 _bfd_ecoff_swap_rndx_in,
2583 /* Functions to swap out external symbolic data. */
2592 _bfd_ecoff_swap_tir_out,
2593 _bfd_ecoff_swap_rndx_out,
2594 /* Function to read in symbolic data. */
2595 _bfd_mips_elf_read_ecoff_info
2598 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
2599 standard ELF. This structure is used to redirect the relocation
2600 handling routines. */
2602 const struct elf_size_info mips_elf64_size_info =
2604 sizeof (Elf64_External_Ehdr),
2605 sizeof (Elf64_External_Phdr),
2606 sizeof (Elf64_External_Shdr),
2607 sizeof (Elf64_Mips_External_Rel),
2608 sizeof (Elf64_Mips_External_Rela),
2609 sizeof (Elf64_External_Sym),
2610 sizeof (Elf64_External_Dyn),
2611 sizeof (Elf_External_Note),
2612 4, /* hash-table entry size */
2613 3, /* internal relocations per external relocations */
2618 bfd_elf64_write_out_phdrs,
2619 bfd_elf64_write_shdrs_and_ehdr,
2620 mips_elf64_write_relocs,
2621 bfd_elf64_swap_symbol_in,
2622 bfd_elf64_swap_symbol_out,
2623 mips_elf64_slurp_reloc_table,
2624 bfd_elf64_slurp_symbol_table,
2625 bfd_elf64_swap_dyn_in,
2626 bfd_elf64_swap_dyn_out,
2627 mips_elf64_be_swap_reloc_in,
2628 mips_elf64_be_swap_reloc_out,
2629 mips_elf64_be_swap_reloca_in,
2630 mips_elf64_be_swap_reloca_out
2633 #define ELF_ARCH bfd_arch_mips
2634 #define ELF_MACHINE_CODE EM_MIPS
2636 /* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses
2637 a value of 0x1000, and we are compatible.
2638 FIXME: How does this affect NewABI? */
2639 #define ELF_MAXPAGESIZE 0x1000
2641 #define elf_backend_collect true
2642 #define elf_backend_type_change_ok true
2643 #define elf_backend_can_gc_sections true
2644 #define elf_info_to_howto mips_elf64_info_to_howto_rela
2645 #define elf_info_to_howto_rel mips_elf64_info_to_howto_rel
2646 #define elf_backend_object_p mips_elf64_object_p
2647 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
2648 #define elf_backend_section_processing _bfd_mips_elf_section_processing
2649 #define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
2650 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
2651 #define elf_backend_section_from_bfd_section \
2652 _bfd_mips_elf_section_from_bfd_section
2653 #define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook
2654 #define elf_backend_link_output_symbol_hook \
2655 _bfd_mips_elf_link_output_symbol_hook
2656 #define elf_backend_create_dynamic_sections \
2657 _bfd_mips_elf_create_dynamic_sections
2658 #define elf_backend_check_relocs _bfd_mips_elf_check_relocs
2659 #define elf_backend_adjust_dynamic_symbol \
2660 _bfd_mips_elf_adjust_dynamic_symbol
2661 #define elf_backend_always_size_sections \
2662 _bfd_mips_elf_always_size_sections
2663 #define elf_backend_size_dynamic_sections \
2664 _bfd_mips_elf_size_dynamic_sections
2665 #define elf_backend_relocate_section _bfd_mips_elf_relocate_section
2666 #define elf_backend_finish_dynamic_symbol \
2667 _bfd_mips_elf_finish_dynamic_symbol
2668 #define elf_backend_finish_dynamic_sections \
2669 _bfd_mips_elf_finish_dynamic_sections
2670 #define elf_backend_final_write_processing \
2671 _bfd_mips_elf_final_write_processing
2672 #define elf_backend_additional_program_headers \
2673 _bfd_mips_elf_additional_program_headers
2674 #define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
2675 #define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook
2676 #define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
2677 #define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
2678 #define elf_backend_ignore_discarded_relocs \
2679 _bfd_mips_elf_ignore_discarded_relocs
2680 #define elf_backend_mips_irix_compat elf64_mips_irix_compat
2681 #define elf_backend_mips_rtype_to_howto mips_elf64_rtype_to_howto
2682 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
2683 #define elf_backend_size_info mips_elf64_size_info
2685 #define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
2686 #define elf_backend_plt_header_size 0
2688 /* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
2689 work better/work only in RELA, so we default to this. */
2690 #define elf_backend_may_use_rel_p 1
2691 #define elf_backend_may_use_rela_p 1
2692 #define elf_backend_default_use_rela_p 1
2694 #define elf_backend_write_section _bfd_mips_elf_write_section
2696 /* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit
2697 MIPS-specific function only applies to IRIX5, which had no 64-bit
2699 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
2700 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
2701 #define bfd_elf64_bfd_get_relocated_section_contents \
2702 _bfd_elf_mips_get_relocated_section_contents
2703 #define bfd_elf64_bfd_link_hash_table_create \
2704 _bfd_mips_elf_link_hash_table_create
2705 #define bfd_elf64_bfd_final_link _bfd_mips_elf_final_link
2706 #define bfd_elf64_bfd_merge_private_bfd_data \
2707 _bfd_mips_elf_merge_private_bfd_data
2708 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
2709 #define bfd_elf64_bfd_print_private_bfd_data \
2710 _bfd_mips_elf_print_private_bfd_data
2712 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
2714 /* MIPS ELF64 archive functions. */
2715 #define bfd_elf64_archive_functions
2716 extern boolean bfd_elf64_archive_slurp_armap
2718 extern boolean bfd_elf64_archive_write_armap
2719 PARAMS((bfd *, unsigned int, struct orl *, unsigned int, int));
2720 #define bfd_elf64_archive_slurp_extended_name_table \
2721 _bfd_archive_coff_slurp_extended_name_table
2722 #define bfd_elf64_archive_construct_extended_name_table \
2723 _bfd_archive_coff_construct_extended_name_table
2724 #define bfd_elf64_archive_truncate_arname \
2725 _bfd_archive_coff_truncate_arname
2726 #define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
2727 #define bfd_elf64_archive_openr_next_archived_file \
2728 _bfd_archive_coff_openr_next_archived_file
2729 #define bfd_elf64_archive_get_elt_at_index \
2730 _bfd_archive_coff_get_elt_at_index
2731 #define bfd_elf64_archive_generic_stat_arch_elt \
2732 _bfd_archive_coff_generic_stat_arch_elt
2733 #define bfd_elf64_archive_update_armap_timestamp \
2734 _bfd_archive_coff_update_armap_timestamp
2736 /* The SGI style (n)64 NewABI. */
2737 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
2738 #define TARGET_LITTLE_NAME "elf64-littlemips"
2739 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
2740 #define TARGET_BIG_NAME "elf64-bigmips"
2742 #include "elf64-target.h"
2744 #define INCLUDED_TARGET_FILE /* More a type of flag. */
2746 /* The SYSV-style 'traditional' (n)64 NewABI. */
2747 #undef TARGET_LITTLE_SYM
2748 #undef TARGET_LITTLE_NAME
2749 #undef TARGET_BIG_SYM
2750 #undef TARGET_BIG_NAME
2752 #define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
2753 #define TARGET_LITTLE_NAME "elf64-tradlittlemips"
2754 #define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
2755 #define TARGET_BIG_NAME "elf64-tradbigmips"
2757 /* Include the target file again for this target. */
2758 #include "elf64-target.h"