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_Rela *));
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_Rela *,
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_Rela *));
78 static void mips_elf64_be_swap_reloc_out
79 PARAMS ((bfd *, const Elf_Internal_Rela *, 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 *, Elf_Internal_Rela *));
90 static void mips_elf64_info_to_howto_rela
91 PARAMS ((bfd *, arelent *, Elf_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_Rela *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);
1232 /* Swap in a MIPS 64-bit Rela reloc. */
1235 mips_elf64_swap_reloca_in (abfd, src, dst)
1237 const Elf64_Mips_External_Rela *src;
1238 Elf64_Mips_Internal_Rela *dst;
1240 dst->r_offset = H_GET_64 (abfd, src->r_offset);
1241 dst->r_sym = H_GET_32 (abfd, src->r_sym);
1242 dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1243 dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1244 dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1245 dst->r_type = H_GET_8 (abfd, src->r_type);
1246 dst->r_addend = H_GET_S64 (abfd, src->r_addend);
1249 /* Swap out a MIPS 64-bit Rel reloc. */
1252 mips_elf64_swap_reloc_out (abfd, src, dst)
1254 const Elf64_Mips_Internal_Rela *src;
1255 Elf64_Mips_External_Rel *dst;
1257 H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1258 H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1259 H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1260 H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1261 H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1262 H_PUT_8 (abfd, src->r_type, dst->r_type);
1265 /* Swap out a MIPS 64-bit Rela reloc. */
1268 mips_elf64_swap_reloca_out (abfd, src, dst)
1270 const Elf64_Mips_Internal_Rela *src;
1271 Elf64_Mips_External_Rela *dst;
1273 H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1274 H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1275 H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1276 H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1277 H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1278 H_PUT_8 (abfd, src->r_type, dst->r_type);
1279 H_PUT_S64 (abfd, src->r_addend, dst->r_addend);
1282 /* Swap in a MIPS 64-bit Rel reloc. */
1285 mips_elf64_be_swap_reloc_in (abfd, src, dst)
1287 const bfd_byte *src;
1288 Elf_Internal_Rela *dst;
1290 Elf64_Mips_Internal_Rela mirel;
1292 mips_elf64_swap_reloc_in (abfd,
1293 (const Elf64_Mips_External_Rel *) src,
1296 dst[0].r_offset = mirel.r_offset;
1297 dst[0].r_info = ELF64_R_INFO (mirel.r_sym, mirel.r_type);
1298 dst[0].r_addend = 0;
1299 dst[1].r_offset = mirel.r_offset;
1300 dst[1].r_info = ELF64_R_INFO (mirel.r_ssym, mirel.r_type2);
1301 dst[1].r_addend = 0;
1302 dst[2].r_offset = mirel.r_offset;
1303 dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirel.r_type3);
1304 dst[2].r_addend = 0;
1307 /* Swap in a MIPS 64-bit Rela reloc. */
1310 mips_elf64_be_swap_reloca_in (abfd, src, dst)
1312 const bfd_byte *src;
1313 Elf_Internal_Rela *dst;
1315 Elf64_Mips_Internal_Rela mirela;
1317 mips_elf64_swap_reloca_in (abfd,
1318 (const Elf64_Mips_External_Rela *) src,
1321 dst[0].r_offset = mirela.r_offset;
1322 dst[0].r_info = ELF64_R_INFO (mirela.r_sym, mirela.r_type);
1323 dst[0].r_addend = mirela.r_addend;
1324 dst[1].r_offset = mirela.r_offset;
1325 dst[1].r_info = ELF64_R_INFO (mirela.r_ssym, mirela.r_type2);
1326 dst[1].r_addend = 0;
1327 dst[2].r_offset = mirela.r_offset;
1328 dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirela.r_type3);
1329 dst[2].r_addend = 0;
1332 /* Swap out a MIPS 64-bit Rel reloc. */
1335 mips_elf64_be_swap_reloc_out (abfd, src, dst)
1337 const Elf_Internal_Rela *src;
1340 Elf64_Mips_Internal_Rela mirel;
1342 mirel.r_offset = src[0].r_offset;
1343 BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1345 BFD_ASSERT(src[0].r_offset == src[2].r_offset);
1348 mirel.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1349 mirel.r_sym = ELF64_R_SYM (src[0].r_info);
1350 mirel.r_type2 = ELF64_MIPS_R_TYPE (src[1].r_info);
1351 mirel.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1352 mirel.r_type3 = ELF64_MIPS_R_TYPE (src[2].r_info);
1354 mips_elf64_swap_reloc_out (abfd, &mirel,
1355 (Elf64_Mips_External_Rel *) dst);
1358 /* Swap out a MIPS 64-bit Rela reloc. */
1361 mips_elf64_be_swap_reloca_out (abfd, src, dst)
1363 const Elf_Internal_Rela *src;
1366 Elf64_Mips_Internal_Rela mirela;
1368 mirela.r_offset = src[0].r_offset;
1369 BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1370 BFD_ASSERT(src[0].r_offset == src[2].r_offset);
1372 mirela.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1373 mirela.r_sym = ELF64_R_SYM (src[0].r_info);
1374 mirela.r_addend = src[0].r_addend;
1375 BFD_ASSERT(src[1].r_addend == 0);
1376 BFD_ASSERT(src[2].r_addend == 0);
1378 mirela.r_type2 = ELF64_MIPS_R_TYPE (src[1].r_info);
1379 mirela.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1380 mirela.r_type3 = ELF64_MIPS_R_TYPE (src[2].r_info);
1382 mips_elf64_swap_reloca_out (abfd, &mirela,
1383 (Elf64_Mips_External_Rela *) dst);
1386 /* Do a R_MIPS_HI16 relocation. */
1388 static bfd_reloc_status_type
1389 mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data, input_section,
1390 output_bfd, error_message)
1391 bfd *abfd ATTRIBUTE_UNUSED;
1392 arelent *reloc_entry;
1394 PTR data ATTRIBUTE_UNUSED;
1395 asection *input_section;
1397 char **error_message ATTRIBUTE_UNUSED;
1399 /* If we're relocating, and this is an external symbol, we don't
1400 want to change anything. */
1401 if (output_bfd != (bfd *) NULL
1402 && (symbol->flags & BSF_SECTION_SYM) == 0
1403 && (! reloc_entry->howto->partial_inplace
1404 || reloc_entry->addend == 0))
1406 reloc_entry->address += input_section->output_offset;
1407 return bfd_reloc_ok;
1410 if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
1411 reloc_entry->addend += 0x8000;
1413 return bfd_reloc_continue;
1416 /* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset
1417 table used for PIC code. If the symbol is an external symbol, the
1418 instruction is modified to contain the offset of the appropriate
1419 entry in the global offset table. If the symbol is a section
1420 symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
1421 addends are combined to form the real addend against the section
1422 symbol; the GOT16 is modified to contain the offset of an entry in
1423 the global offset table, and the LO16 is modified to offset it
1424 appropriately. Thus an offset larger than 16 bits requires a
1425 modified value in the global offset table.
1427 This implementation suffices for the assembler, but the linker does
1428 not yet know how to create global offset tables. */
1430 static bfd_reloc_status_type
1431 mips_elf64_got16_reloc (abfd, reloc_entry, symbol, data, input_section,
1432 output_bfd, error_message)
1434 arelent *reloc_entry;
1437 asection *input_section;
1439 char **error_message;
1441 /* If we're relocating, and this is a local symbol, we can handle it
1442 just like an R_MIPS_HI16. */
1443 if (output_bfd != (bfd *) NULL
1444 && (symbol->flags & BSF_SECTION_SYM) != 0)
1445 return mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data,
1446 input_section, output_bfd, error_message);
1449 /* Otherwise we try to handle it as R_MIPS_GOT_DISP. */
1450 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
1451 input_section, output_bfd, error_message);
1454 /* Set the GP value for OUTPUT_BFD. Returns false if this is a
1455 dangerous relocation. */
1458 mips_elf64_assign_gp (output_bfd, pgp)
1466 /* If we've already figured out what GP will be, just return it. */
1467 *pgp = _bfd_get_gp_value (output_bfd);
1471 count = bfd_get_symcount (output_bfd);
1472 sym = bfd_get_outsymbols (output_bfd);
1474 /* The linker script will have created a symbol named `_gp' with the
1475 appropriate value. */
1476 if (sym == (asymbol **) NULL)
1480 for (i = 0; i < count; i++, sym++)
1482 register const char *name;
1484 name = bfd_asymbol_name (*sym);
1485 if (*name == '_' && strcmp (name, "_gp") == 0)
1487 *pgp = bfd_asymbol_value (*sym);
1488 _bfd_set_gp_value (output_bfd, *pgp);
1496 /* Only get the error once. */
1498 _bfd_set_gp_value (output_bfd, *pgp);
1505 /* We have to figure out the gp value, so that we can adjust the
1506 symbol value correctly. We look up the symbol _gp in the output
1507 BFD. If we can't find it, we're stuck. We cache it in the ELF
1508 target data. We don't need to adjust the symbol value for an
1509 external symbol if we are producing relocateable output. */
1511 static bfd_reloc_status_type
1512 mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message, pgp)
1515 boolean relocateable;
1516 char **error_message;
1519 if (bfd_is_und_section (symbol->section)
1523 return bfd_reloc_undefined;
1526 *pgp = _bfd_get_gp_value (output_bfd);
1529 || (symbol->flags & BSF_SECTION_SYM) != 0))
1533 /* Make up a value. */
1534 *pgp = symbol->section->output_section->vma /*+ 0x4000*/;
1535 _bfd_set_gp_value (output_bfd, *pgp);
1537 else if (!mips_elf64_assign_gp (output_bfd, pgp))
1540 (char *) _("GP relative relocation when _gp not defined");
1541 return bfd_reloc_dangerous;
1545 return bfd_reloc_ok;
1548 /* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must
1549 become the offset from the gp register. */
1551 static bfd_reloc_status_type
1552 mips_elf64_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
1553 output_bfd, error_message)
1555 arelent *reloc_entry;
1558 asection *input_section;
1560 char **error_message;
1562 boolean relocateable;
1563 bfd_reloc_status_type ret;
1566 /* If we're relocating, and this is an external symbol with no
1567 addend, we don't want to change anything. We will only have an
1568 addend if this is a newly created reloc, not read from an ELF
1570 if (output_bfd != (bfd *) NULL
1571 && (symbol->flags & BSF_SECTION_SYM) == 0
1572 && (! reloc_entry->howto->partial_inplace
1573 || reloc_entry->addend == 0))
1575 reloc_entry->address += input_section->output_offset;
1576 return bfd_reloc_ok;
1579 if (output_bfd != (bfd *) NULL)
1580 relocateable = true;
1583 relocateable = false;
1584 output_bfd = symbol->section->output_section->owner;
1587 ret = mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
1589 if (ret != bfd_reloc_ok)
1592 return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1593 input_section, relocateable,
1597 /* Do a R_MIPS_LITERAL relocation. */
1599 static bfd_reloc_status_type
1600 mips_elf64_literal_reloc (abfd, reloc_entry, symbol, data, input_section,
1601 output_bfd, error_message)
1603 arelent *reloc_entry;
1606 asection *input_section;
1608 char **error_message;
1610 boolean relocateable;
1611 bfd_reloc_status_type ret;
1614 /* If we're relocating, and this is an external symbol, we don't
1615 want to change anything. */
1616 if (output_bfd != (bfd *) NULL
1617 && (symbol->flags & BSF_SECTION_SYM) == 0
1618 && (! reloc_entry->howto->partial_inplace
1619 || reloc_entry->addend == 0))
1621 reloc_entry->address += input_section->output_offset;
1622 return bfd_reloc_ok;
1625 /* FIXME: The entries in the .lit8 and .lit4 sections should be merged. */
1626 if (output_bfd != (bfd *) NULL)
1627 relocateable = true;
1630 relocateable = false;
1631 output_bfd = symbol->section->output_section->owner;
1634 ret = mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
1636 if (ret != bfd_reloc_ok)
1639 return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1640 input_section, relocateable,
1644 /* Do a R_MIPS_GPREL32 relocation. This is a 32 bit value which must
1645 become the offset from the gp register. */
1647 static bfd_reloc_status_type
1648 mips_elf64_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
1649 output_bfd, error_message)
1651 arelent *reloc_entry;
1654 asection *input_section;
1656 char **error_message;
1658 boolean relocateable;
1659 bfd_reloc_status_type ret;
1664 /* If we're relocating, and this is an external symbol with no
1665 addend, we don't want to change anything. We will only have an
1666 addend if this is a newly created reloc, not read from an ELF
1668 if (output_bfd != (bfd *) NULL
1669 && (symbol->flags & BSF_SECTION_SYM) == 0
1670 && reloc_entry->addend == 0)
1672 *error_message = (char *)
1673 _("32bits gp relative relocation occurs for an external symbol");
1674 return bfd_reloc_outofrange;
1677 if (output_bfd != (bfd *) NULL)
1679 relocateable = true;
1680 gp = _bfd_get_gp_value (output_bfd);
1684 relocateable = false;
1685 output_bfd = symbol->section->output_section->owner;
1687 ret = mips_elf64_final_gp (output_bfd, symbol, relocateable,
1688 error_message, &gp);
1689 if (ret != bfd_reloc_ok)
1693 if (bfd_is_com_section (symbol->section))
1696 relocation = symbol->value;
1698 relocation += symbol->section->output_section->vma;
1699 relocation += symbol->section->output_offset;
1701 if (reloc_entry->address > input_section->_cooked_size)
1702 return bfd_reloc_outofrange;
1704 if (reloc_entry->howto->src_mask == 0)
1706 /* This case arises with the 64-bit MIPS ELF ABI. */
1710 val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1712 /* Set val to the offset into the section or symbol. */
1713 val += reloc_entry->addend;
1715 /* Adjust val for the final section location and GP value. If we
1716 are producing relocateable output, we don't want to do this for
1717 an external symbol. */
1719 || (symbol->flags & BSF_SECTION_SYM) != 0)
1720 val += relocation - gp;
1722 bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
1725 reloc_entry->address += input_section->output_offset;
1727 return bfd_reloc_ok;
1730 /* Do a R_MIPS_SHIFT6 relocation. The MSB of the shift is stored at bit 2,
1731 the rest is at bits 6-10. The bitpos already got right by the howto. */
1733 static bfd_reloc_status_type
1734 mips_elf64_shift6_reloc (abfd, reloc_entry, symbol, data, input_section,
1735 output_bfd, error_message)
1736 bfd *abfd ATTRIBUTE_UNUSED;
1737 arelent *reloc_entry;
1739 PTR data ATTRIBUTE_UNUSED;
1740 asection *input_section;
1742 char **error_message ATTRIBUTE_UNUSED;
1744 /* If we're relocating, and this is an external symbol, we don't
1745 want to change anything. */
1746 if (output_bfd != (bfd *) NULL
1747 && (symbol->flags & BSF_SECTION_SYM) == 0
1748 && (! reloc_entry->howto->partial_inplace
1749 || reloc_entry->addend == 0))
1751 reloc_entry->address += input_section->output_offset;
1752 return bfd_reloc_ok;
1755 reloc_entry->addend = (reloc_entry->addend & 0x00007c0)
1756 | (reloc_entry->addend & 0x00000800) >> 9;
1758 return bfd_reloc_continue;
1761 /* Handle a mips16 jump. */
1763 static bfd_reloc_status_type
1764 mips16_jump_reloc (abfd, reloc_entry, symbol, data, input_section,
1765 output_bfd, error_message)
1766 bfd *abfd ATTRIBUTE_UNUSED;
1767 arelent *reloc_entry;
1769 PTR data ATTRIBUTE_UNUSED;
1770 asection *input_section;
1772 char **error_message ATTRIBUTE_UNUSED;
1774 if (output_bfd != (bfd *) NULL
1775 && (symbol->flags & BSF_SECTION_SYM) == 0
1776 && (! reloc_entry->howto->partial_inplace
1777 || reloc_entry->addend == 0))
1779 reloc_entry->address += input_section->output_offset;
1780 return bfd_reloc_ok;
1785 static boolean warned;
1788 (*_bfd_error_handler)
1789 (_("Linking mips16 objects into %s format is not supported"),
1790 bfd_get_target (input_section->output_section->owner));
1794 return bfd_reloc_undefined;
1797 /* Handle a mips16 GP relative reloc. */
1799 static bfd_reloc_status_type
1800 mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section,
1801 output_bfd, error_message)
1803 arelent *reloc_entry;
1806 asection *input_section;
1808 char **error_message;
1810 boolean relocateable;
1811 bfd_reloc_status_type ret;
1813 unsigned short extend, insn;
1814 unsigned long final;
1816 /* If we're relocating, and this is an external symbol with no
1817 addend, we don't want to change anything. We will only have an
1818 addend if this is a newly created reloc, not read from an ELF
1820 if (output_bfd != NULL
1821 && (symbol->flags & BSF_SECTION_SYM) == 0
1822 && reloc_entry->addend == 0)
1824 reloc_entry->address += input_section->output_offset;
1825 return bfd_reloc_ok;
1828 if (output_bfd != NULL)
1829 relocateable = true;
1832 relocateable = false;
1833 output_bfd = symbol->section->output_section->owner;
1836 ret = mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
1838 if (ret != bfd_reloc_ok)
1841 if (reloc_entry->address > input_section->_cooked_size)
1842 return bfd_reloc_outofrange;
1844 /* Pick up the mips16 extend instruction and the real instruction. */
1845 extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
1846 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
1848 /* Stuff the current addend back as a 32 bit value, do the usual
1849 relocation, and then clean up. */
1851 (bfd_vma) (((extend & 0x1f) << 11)
1854 (bfd_byte *) data + reloc_entry->address);
1856 ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1857 input_section, relocateable, data, gp);
1859 final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1861 (bfd_vma) ((extend & 0xf800)
1862 | ((final >> 11) & 0x1f)
1864 (bfd_byte *) data + reloc_entry->address);
1866 (bfd_vma) ((insn & 0xffe0)
1868 (bfd_byte *) data + reloc_entry->address + 2);
1873 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1875 struct elf_reloc_map {
1876 bfd_reloc_code_real_type bfd_val;
1877 enum elf_mips_reloc_type elf_val;
1880 static const struct elf_reloc_map mips_reloc_map[] =
1882 { BFD_RELOC_NONE, R_MIPS_NONE },
1883 { BFD_RELOC_16, R_MIPS_16 },
1884 { BFD_RELOC_32, R_MIPS_32 },
1885 /* There is no BFD reloc for R_MIPS_REL32. */
1886 { BFD_RELOC_64, R_MIPS_64 },
1887 { BFD_RELOC_CTOR, R_MIPS_64 },
1888 { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
1889 { BFD_RELOC_HI16_S, R_MIPS_HI16 },
1890 { BFD_RELOC_LO16, R_MIPS_LO16 },
1891 { BFD_RELOC_GPREL16, R_MIPS_GPREL16 },
1892 { BFD_RELOC_GPREL32, R_MIPS_GPREL32 },
1893 { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
1894 { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
1895 { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
1896 { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
1897 { BFD_RELOC_MIPS_SHIFT5, R_MIPS_SHIFT5 },
1898 { BFD_RELOC_MIPS_SHIFT6, R_MIPS_SHIFT6 },
1899 { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP },
1900 { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
1901 { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
1902 { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
1903 { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
1904 { BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
1905 { BFD_RELOC_MIPS_INSERT_A, R_MIPS_INSERT_A },
1906 { BFD_RELOC_MIPS_INSERT_B, R_MIPS_INSERT_B },
1907 { BFD_RELOC_MIPS_DELETE, R_MIPS_DELETE },
1908 { BFD_RELOC_MIPS_HIGHEST, R_MIPS_HIGHEST },
1909 { BFD_RELOC_MIPS_HIGHER, R_MIPS_HIGHER },
1910 { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
1911 { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
1912 { BFD_RELOC_MIPS_SCN_DISP, R_MIPS_SCN_DISP },
1913 { BFD_RELOC_MIPS_REL16, R_MIPS_REL16 },
1914 /* Use of R_MIPS_ADD_IMMEDIATE and R_MIPS_PJUMP is deprecated. */
1915 { BFD_RELOC_MIPS_RELGOT, R_MIPS_RELGOT },
1916 { BFD_RELOC_MIPS_JALR, R_MIPS_JALR }
1919 /* Given a BFD reloc type, return a howto structure. */
1921 static reloc_howto_type *
1922 bfd_elf64_bfd_reloc_type_lookup (abfd, code)
1923 bfd *abfd ATTRIBUTE_UNUSED;
1924 bfd_reloc_code_real_type code;
1927 /* FIXME: We default to RELA here instead of choosing the right
1928 relocation variant. */
1929 reloc_howto_type *howto_table = mips_elf64_howto_table_rela;
1931 for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map);
1934 if (mips_reloc_map[i].bfd_val == code)
1935 return &howto_table[(int) mips_reloc_map[i].elf_val];
1940 case BFD_RELOC_MIPS16_JMP:
1941 return &elf_mips16_jump_howto;
1942 case BFD_RELOC_MIPS16_GPREL:
1943 return &elf_mips16_gprel_howto;
1944 case BFD_RELOC_VTABLE_INHERIT:
1945 return &elf_mips_gnu_vtinherit_howto;
1946 case BFD_RELOC_VTABLE_ENTRY:
1947 return &elf_mips_gnu_vtentry_howto;
1949 bfd_set_error (bfd_error_bad_value);
1954 /* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */
1956 static reloc_howto_type *
1957 mips_elf64_rtype_to_howto (r_type, rela_p)
1958 unsigned int r_type;
1964 return &elf_mips16_jump_howto;
1965 case R_MIPS16_GPREL:
1966 return &elf_mips16_gprel_howto;
1967 case R_MIPS_GNU_VTINHERIT:
1968 return &elf_mips_gnu_vtinherit_howto;
1969 case R_MIPS_GNU_VTENTRY:
1970 return &elf_mips_gnu_vtentry_howto;
1972 BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
1974 return &mips_elf64_howto_table_rela[r_type];
1976 return &mips_elf64_howto_table_rel[r_type];
1981 /* Prevent relocation handling by bfd for MIPS ELF64. */
1984 mips_elf64_info_to_howto_rel (abfd, cache_ptr, dst)
1985 bfd *abfd ATTRIBUTE_UNUSED;
1986 arelent *cache_ptr ATTRIBUTE_UNUSED;
1987 Elf_Internal_Rela *dst ATTRIBUTE_UNUSED;
1993 mips_elf64_info_to_howto_rela (abfd, cache_ptr, dst)
1994 bfd *abfd ATTRIBUTE_UNUSED;
1995 arelent *cache_ptr ATTRIBUTE_UNUSED;
1996 Elf_Internal_Rela *dst ATTRIBUTE_UNUSED;
2001 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
2002 to three relocs, we must tell the user to allocate more space. */
2005 mips_elf64_get_reloc_upper_bound (abfd, sec)
2006 bfd *abfd ATTRIBUTE_UNUSED;
2009 return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
2012 /* Read the relocations from one reloc section. */
2015 mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
2019 const Elf_Internal_Shdr *rel_hdr;
2021 PTR allocated = NULL;
2022 bfd_byte *native_relocs;
2028 reloc_howto_type *howto_table;
2030 allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
2031 if (allocated == NULL)
2034 if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
2035 || (bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
2038 native_relocs = (bfd_byte *) allocated;
2040 relents = asect->relocation + asect->reloc_count;
2042 entsize = rel_hdr->sh_entsize;
2043 BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
2044 || entsize == sizeof (Elf64_Mips_External_Rela));
2046 count = rel_hdr->sh_size / entsize;
2048 if (entsize == sizeof (Elf64_Mips_External_Rel))
2049 howto_table = mips_elf64_howto_table_rel;
2051 howto_table = mips_elf64_howto_table_rela;
2054 for (i = 0; i < count; i++, native_relocs += entsize)
2056 Elf64_Mips_Internal_Rela rela;
2057 boolean used_sym, used_ssym;
2060 if (entsize == sizeof (Elf64_Mips_External_Rela))
2061 mips_elf64_swap_reloca_in (abfd,
2062 (Elf64_Mips_External_Rela *) native_relocs,
2065 mips_elf64_swap_reloc_in (abfd,
2066 (Elf64_Mips_External_Rel *) native_relocs,
2069 /* Each entry represents exactly three actual relocations. */
2073 for (ir = 0; ir < 3; ir++)
2075 enum elf_mips_reloc_type type;
2082 type = (enum elf_mips_reloc_type) rela.r_type;
2085 type = (enum elf_mips_reloc_type) rela.r_type2;
2088 type = (enum elf_mips_reloc_type) rela.r_type3;
2092 /* Some types require symbols, whereas some do not. */
2096 case R_MIPS_LITERAL:
2097 case R_MIPS_INSERT_A:
2098 case R_MIPS_INSERT_B:
2100 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2106 if (rela.r_sym == 0)
2107 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2112 ps = symbols + rela.r_sym - 1;
2114 if ((s->flags & BSF_SECTION_SYM) == 0)
2115 relent->sym_ptr_ptr = ps;
2117 relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
2122 else if (! used_ssym)
2124 switch (rela.r_ssym)
2127 relent->sym_ptr_ptr =
2128 bfd_abs_section_ptr->symbol_ptr_ptr;
2134 /* FIXME: I think these need to be handled using
2135 special howto structures. */
2147 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2152 /* The address of an ELF reloc is section relative for an
2153 object file, and absolute for an executable file or
2154 shared library. The address of a BFD reloc is always
2155 section relative. */
2156 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2157 relent->address = rela.r_offset;
2159 relent->address = rela.r_offset - asect->vma;
2161 relent->addend = rela.r_addend;
2163 relent->howto = &howto_table[(int) type];
2169 asect->reloc_count += (relent - relents) / 3;
2171 if (allocated != NULL)
2177 if (allocated != NULL)
2182 /* Read the relocations. On Irix 6, there can be two reloc sections
2183 associated with a single data section. */
2186 mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
2193 struct bfd_elf_section_data * const d = elf_section_data (asect);
2197 bfd_set_error (bfd_error_invalid_operation);
2201 if (asect->relocation != NULL
2202 || (asect->flags & SEC_RELOC) == 0
2203 || asect->reloc_count == 0)
2206 /* Allocate space for 3 arelent structures for each Rel structure. */
2207 amt = asect->reloc_count;
2208 amt *= 3 * sizeof (arelent);
2209 asect->relocation = (arelent *) bfd_alloc (abfd, amt);
2210 if (asect->relocation == NULL)
2213 /* The slurp_one_reloc_table routine increments reloc_count. */
2214 asect->reloc_count = 0;
2216 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
2218 if (d->rel_hdr2 != NULL)
2220 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
2228 /* Write out the relocations. */
2231 mips_elf64_write_relocs (abfd, sec, data)
2236 boolean *failedp = (boolean *) data;
2238 Elf_Internal_Shdr *rel_hdr;
2241 /* If we have already failed, don't do anything. */
2245 if ((sec->flags & SEC_RELOC) == 0)
2248 /* The linker backend writes the relocs out itself, and sets the
2249 reloc_count field to zero to inhibit writing them here. Also,
2250 sometimes the SEC_RELOC flag gets set even when there aren't any
2252 if (sec->reloc_count == 0)
2255 /* We can combine up to three relocs that refer to the same address
2256 if the latter relocs have no associated symbol. */
2258 for (idx = 0; idx < sec->reloc_count; idx++)
2265 addr = sec->orelocation[idx]->address;
2266 for (i = 0; i < 2; i++)
2270 if (idx + 1 >= sec->reloc_count)
2272 r = sec->orelocation[idx + 1];
2273 if (r->address != addr
2274 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2275 || (*r->sym_ptr_ptr)->value != 0)
2278 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2284 rel_hdr = &elf_section_data (sec)->rel_hdr;
2286 /* Do the actual relocation. */
2288 if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rel))
2289 mips_elf64_write_rel (abfd, sec, rel_hdr, &count, data);
2290 else if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rela))
2291 mips_elf64_write_rela (abfd, sec, rel_hdr, &count, data);
2297 mips_elf64_write_rel (abfd, sec, rel_hdr, count, data)
2300 Elf_Internal_Shdr *rel_hdr;
2304 boolean *failedp = (boolean *) data;
2305 Elf64_Mips_External_Rel *ext_rel;
2307 asymbol *last_sym = 0;
2308 int last_sym_idx = 0;
2310 rel_hdr->sh_size = (bfd_vma)(rel_hdr->sh_entsize * *count);
2311 rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size);
2312 if (rel_hdr->contents == NULL)
2318 ext_rel = (Elf64_Mips_External_Rel *) rel_hdr->contents;
2319 for (idx = 0; idx < sec->reloc_count; idx++, ext_rel++)
2322 Elf64_Mips_Internal_Rela int_rel;
2327 ptr = sec->orelocation[idx];
2329 /* The address of an ELF reloc is section relative for an object
2330 file, and absolute for an executable file or shared library.
2331 The address of a BFD reloc is always section relative. */
2332 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2333 int_rel.r_offset = ptr->address;
2335 int_rel.r_offset = ptr->address + sec->vma;
2337 sym = *ptr->sym_ptr_ptr;
2338 if (sym == last_sym)
2343 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2353 int_rel.r_ssym = RSS_UNDEF;
2355 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2356 && ! _bfd_elf_validate_reloc (abfd, ptr))
2362 int_rel.r_type = ptr->howto->type;
2363 int_rel.r_type2 = (int) R_MIPS_NONE;
2364 int_rel.r_type3 = (int) R_MIPS_NONE;
2366 for (i = 0; i < 2; i++)
2370 if (idx + 1 >= sec->reloc_count)
2372 r = sec->orelocation[idx + 1];
2373 if (r->address != ptr->address
2374 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2375 || (*r->sym_ptr_ptr)->value != 0)
2378 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2381 int_rel.r_type2 = r->howto->type;
2383 int_rel.r_type3 = r->howto->type;
2388 mips_elf64_swap_reloc_out (abfd, &int_rel, ext_rel);
2391 BFD_ASSERT (ext_rel - (Elf64_Mips_External_Rel *) rel_hdr->contents
2396 mips_elf64_write_rela (abfd, sec, rela_hdr, count, data)
2399 Elf_Internal_Shdr *rela_hdr;
2403 boolean *failedp = (boolean *) data;
2404 Elf64_Mips_External_Rela *ext_rela;
2406 asymbol *last_sym = 0;
2407 int last_sym_idx = 0;
2409 rela_hdr->sh_size = (bfd_vma)(rela_hdr->sh_entsize * *count);
2410 rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
2411 if (rela_hdr->contents == NULL)
2417 ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
2418 for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
2421 Elf64_Mips_Internal_Rela int_rela;
2426 ptr = sec->orelocation[idx];
2428 /* The address of an ELF reloc is section relative for an object
2429 file, and absolute for an executable file or shared library.
2430 The address of a BFD reloc is always section relative. */
2431 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2432 int_rela.r_offset = ptr->address;
2434 int_rela.r_offset = ptr->address + sec->vma;
2436 sym = *ptr->sym_ptr_ptr;
2437 if (sym == last_sym)
2442 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2452 int_rela.r_addend = ptr->addend;
2453 int_rela.r_ssym = RSS_UNDEF;
2455 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2456 && ! _bfd_elf_validate_reloc (abfd, ptr))
2462 int_rela.r_type = ptr->howto->type;
2463 int_rela.r_type2 = (int) R_MIPS_NONE;
2464 int_rela.r_type3 = (int) R_MIPS_NONE;
2466 for (i = 0; i < 2; i++)
2470 if (idx + 1 >= sec->reloc_count)
2472 r = sec->orelocation[idx + 1];
2473 if (r->address != ptr->address
2474 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2475 || (*r->sym_ptr_ptr)->value != 0)
2478 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2481 int_rela.r_type2 = r->howto->type;
2483 int_rela.r_type3 = r->howto->type;
2488 mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
2491 BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
2495 /* Set the right machine number for a MIPS ELF file. */
2498 mips_elf64_object_p (abfd)
2503 /* Irix 6 is broken. Object file symbol tables are not always
2504 sorted correctly such that local symbols precede global symbols,
2505 and the sh_info field in the symbol table is not always right. */
2506 if (elf64_mips_irix_compat (abfd) != ict_none)
2507 elf_bad_symtab (abfd) = true;
2509 mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags);
2510 bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach);
2514 /* Depending on the target vector we generate some version of Irix
2515 executables or "normal" MIPS ELF ABI executables. */
2516 static irix_compat_t
2517 elf64_mips_irix_compat (abfd)
2520 if ((abfd->xvec == &bfd_elf64_bigmips_vec)
2521 || (abfd->xvec == &bfd_elf64_littlemips_vec))
2527 /* ECOFF swapping routines. These are used when dealing with the
2528 .mdebug section, which is in the ECOFF debugging format. */
2529 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
2531 /* Symbol table magic number. */
2533 /* Alignment of debugging information. E.g., 4. */
2535 /* Sizes of external symbolic information. */
2536 sizeof (struct hdr_ext),
2537 sizeof (struct dnr_ext),
2538 sizeof (struct pdr_ext),
2539 sizeof (struct sym_ext),
2540 sizeof (struct opt_ext),
2541 sizeof (struct fdr_ext),
2542 sizeof (struct rfd_ext),
2543 sizeof (struct ext_ext),
2544 /* Functions to swap in external symbolic data. */
2553 _bfd_ecoff_swap_tir_in,
2554 _bfd_ecoff_swap_rndx_in,
2555 /* Functions to swap out external symbolic data. */
2564 _bfd_ecoff_swap_tir_out,
2565 _bfd_ecoff_swap_rndx_out,
2566 /* Function to read in symbolic data. */
2567 _bfd_mips_elf_read_ecoff_info
2570 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
2571 standard ELF. This structure is used to redirect the relocation
2572 handling routines. */
2574 const struct elf_size_info mips_elf64_size_info =
2576 sizeof (Elf64_External_Ehdr),
2577 sizeof (Elf64_External_Phdr),
2578 sizeof (Elf64_External_Shdr),
2579 sizeof (Elf64_Mips_External_Rel),
2580 sizeof (Elf64_Mips_External_Rela),
2581 sizeof (Elf64_External_Sym),
2582 sizeof (Elf64_External_Dyn),
2583 sizeof (Elf_External_Note),
2584 4, /* hash-table entry size */
2585 3, /* internal relocations per external relocations */
2590 bfd_elf64_write_out_phdrs,
2591 bfd_elf64_write_shdrs_and_ehdr,
2592 mips_elf64_write_relocs,
2593 bfd_elf64_swap_symbol_in,
2594 bfd_elf64_swap_symbol_out,
2595 mips_elf64_slurp_reloc_table,
2596 bfd_elf64_slurp_symbol_table,
2597 bfd_elf64_swap_dyn_in,
2598 bfd_elf64_swap_dyn_out,
2599 mips_elf64_be_swap_reloc_in,
2600 mips_elf64_be_swap_reloc_out,
2601 mips_elf64_be_swap_reloca_in,
2602 mips_elf64_be_swap_reloca_out
2605 #define ELF_ARCH bfd_arch_mips
2606 #define ELF_MACHINE_CODE EM_MIPS
2608 /* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses
2609 a value of 0x1000, and we are compatible.
2610 FIXME: How does this affect NewABI? */
2611 #define ELF_MAXPAGESIZE 0x1000
2613 #define elf_backend_collect true
2614 #define elf_backend_type_change_ok true
2615 #define elf_backend_can_gc_sections true
2616 #define elf_info_to_howto mips_elf64_info_to_howto_rela
2617 #define elf_info_to_howto_rel mips_elf64_info_to_howto_rel
2618 #define elf_backend_object_p mips_elf64_object_p
2619 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
2620 #define elf_backend_section_processing _bfd_mips_elf_section_processing
2621 #define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
2622 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
2623 #define elf_backend_section_from_bfd_section \
2624 _bfd_mips_elf_section_from_bfd_section
2625 #define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook
2626 #define elf_backend_link_output_symbol_hook \
2627 _bfd_mips_elf_link_output_symbol_hook
2628 #define elf_backend_create_dynamic_sections \
2629 _bfd_mips_elf_create_dynamic_sections
2630 #define elf_backend_check_relocs _bfd_mips_elf_check_relocs
2631 #define elf_backend_adjust_dynamic_symbol \
2632 _bfd_mips_elf_adjust_dynamic_symbol
2633 #define elf_backend_always_size_sections \
2634 _bfd_mips_elf_always_size_sections
2635 #define elf_backend_size_dynamic_sections \
2636 _bfd_mips_elf_size_dynamic_sections
2637 #define elf_backend_relocate_section _bfd_mips_elf_relocate_section
2638 #define elf_backend_finish_dynamic_symbol \
2639 _bfd_mips_elf_finish_dynamic_symbol
2640 #define elf_backend_finish_dynamic_sections \
2641 _bfd_mips_elf_finish_dynamic_sections
2642 #define elf_backend_final_write_processing \
2643 _bfd_mips_elf_final_write_processing
2644 #define elf_backend_additional_program_headers \
2645 _bfd_mips_elf_additional_program_headers
2646 #define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
2647 #define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook
2648 #define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
2649 #define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
2650 #define elf_backend_ignore_discarded_relocs \
2651 _bfd_mips_elf_ignore_discarded_relocs
2652 #define elf_backend_mips_irix_compat elf64_mips_irix_compat
2653 #define elf_backend_mips_rtype_to_howto mips_elf64_rtype_to_howto
2654 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
2655 #define elf_backend_size_info mips_elf64_size_info
2657 #define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
2658 #define elf_backend_plt_header_size 0
2660 /* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
2661 work better/work only in RELA, so we default to this. */
2662 #define elf_backend_may_use_rel_p 1
2663 #define elf_backend_may_use_rela_p 1
2664 #define elf_backend_default_use_rela_p 1
2666 #define elf_backend_write_section _bfd_mips_elf_write_section
2668 /* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit
2669 MIPS-specific function only applies to IRIX5, which had no 64-bit
2671 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
2672 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
2673 #define bfd_elf64_bfd_get_relocated_section_contents \
2674 _bfd_elf_mips_get_relocated_section_contents
2675 #define bfd_elf64_bfd_link_hash_table_create \
2676 _bfd_mips_elf_link_hash_table_create
2677 #define bfd_elf64_bfd_final_link _bfd_mips_elf_final_link
2678 #define bfd_elf64_bfd_merge_private_bfd_data \
2679 _bfd_mips_elf_merge_private_bfd_data
2680 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
2681 #define bfd_elf64_bfd_print_private_bfd_data \
2682 _bfd_mips_elf_print_private_bfd_data
2684 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
2686 /* MIPS ELF64 archive functions. */
2687 #define bfd_elf64_archive_functions
2688 extern boolean bfd_elf64_archive_slurp_armap
2690 extern boolean bfd_elf64_archive_write_armap
2691 PARAMS((bfd *, unsigned int, struct orl *, unsigned int, int));
2692 #define bfd_elf64_archive_slurp_extended_name_table \
2693 _bfd_archive_coff_slurp_extended_name_table
2694 #define bfd_elf64_archive_construct_extended_name_table \
2695 _bfd_archive_coff_construct_extended_name_table
2696 #define bfd_elf64_archive_truncate_arname \
2697 _bfd_archive_coff_truncate_arname
2698 #define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
2699 #define bfd_elf64_archive_openr_next_archived_file \
2700 _bfd_archive_coff_openr_next_archived_file
2701 #define bfd_elf64_archive_get_elt_at_index \
2702 _bfd_archive_coff_get_elt_at_index
2703 #define bfd_elf64_archive_generic_stat_arch_elt \
2704 _bfd_archive_coff_generic_stat_arch_elt
2705 #define bfd_elf64_archive_update_armap_timestamp \
2706 _bfd_archive_coff_update_armap_timestamp
2708 /* The SGI style (n)64 NewABI. */
2709 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
2710 #define TARGET_LITTLE_NAME "elf64-littlemips"
2711 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
2712 #define TARGET_BIG_NAME "elf64-bigmips"
2714 #include "elf64-target.h"
2716 #define INCLUDED_TARGET_FILE /* More a type of flag. */
2718 /* The SYSV-style 'traditional' (n)64 NewABI. */
2719 #undef TARGET_LITTLE_SYM
2720 #undef TARGET_LITTLE_NAME
2721 #undef TARGET_BIG_SYM
2722 #undef TARGET_BIG_NAME
2724 #define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
2725 #define TARGET_LITTLE_NAME "elf64-tradlittlemips"
2726 #define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
2727 #define TARGET_BIG_NAME "elf64-tradbigmips"
2729 /* Include the target file again for this target. */
2730 #include "elf64-target.h"