* config/tc-avr.c (mcu_types): Add atmega16u4.
[binutils.git] / bfd / elf64-mips.c
blobad00a3db19b4a36e646080904fc3365f03b8a4e7
1 /* MIPS-specific support for 64-bit ELF
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2007 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
26 /* This file supports the 64-bit MIPS ELF ABI.
28 The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
29 overrides the usual ELF reloc handling, and handles reading and
30 writing the relocations here. */
32 /* TODO: Many things are unsupported, even if there is some code for it
33 . (which was mostly stolen from elf32-mips.c and slightly adapted).
35 . - Relocation handling for REL relocs is wrong in many cases and
36 . generally untested.
37 . - Relocation handling for RELA relocs related to GOT support are
38 . also likely to be wrong.
39 . - Support for MIPS16 is untested.
40 . - Combined relocs with RSS_* entries are unsupported.
41 . - The whole GOT handling for NewABI is missing, some parts of
42 . the OldABI version is still lying around and should be removed.
45 #include "sysdep.h"
46 #include "bfd.h"
47 #include "libbfd.h"
48 #include "aout/ar.h"
49 #include "bfdlink.h"
50 #include "genlink.h"
51 #include "elf-bfd.h"
52 #include "elfxx-mips.h"
53 #include "elf/mips.h"
55 /* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
56 use ECOFF. However, we support it anyhow for an easier changeover. */
57 #include "coff/sym.h"
58 #include "coff/symconst.h"
59 #include "coff/internal.h"
60 #include "coff/ecoff.h"
61 /* The 64 bit versions of the mdebug data structures are in alpha.h. */
62 #include "coff/alpha.h"
63 #define ECOFF_SIGNED_64
64 #include "ecoffswap.h"
66 static void mips_elf64_swap_reloc_in
67 (bfd *, const Elf64_Mips_External_Rel *, Elf64_Mips_Internal_Rela *);
68 static void mips_elf64_swap_reloca_in
69 (bfd *, const Elf64_Mips_External_Rela *, Elf64_Mips_Internal_Rela *);
70 static void mips_elf64_swap_reloc_out
71 (bfd *, const Elf64_Mips_Internal_Rela *, Elf64_Mips_External_Rel *);
72 static void mips_elf64_swap_reloca_out
73 (bfd *, const Elf64_Mips_Internal_Rela *, Elf64_Mips_External_Rela *);
74 static void mips_elf64_be_swap_reloc_in
75 (bfd *, const bfd_byte *, Elf_Internal_Rela *);
76 static void mips_elf64_be_swap_reloc_out
77 (bfd *, const Elf_Internal_Rela *, bfd_byte *);
78 static void mips_elf64_be_swap_reloca_in
79 (bfd *, const bfd_byte *, Elf_Internal_Rela *);
80 static void mips_elf64_be_swap_reloca_out
81 (bfd *, const Elf_Internal_Rela *, bfd_byte *);
82 static reloc_howto_type *bfd_elf64_bfd_reloc_type_lookup
83 (bfd *, bfd_reloc_code_real_type);
84 static reloc_howto_type *mips_elf64_rtype_to_howto
85 (unsigned int, bfd_boolean);
86 static void mips_elf64_info_to_howto_rel
87 (bfd *, arelent *, Elf_Internal_Rela *);
88 static void mips_elf64_info_to_howto_rela
89 (bfd *, arelent *, Elf_Internal_Rela *);
90 static long mips_elf64_get_reloc_upper_bound
91 (bfd *, asection *);
92 static long mips_elf64_canonicalize_reloc
93 (bfd *, asection *, arelent **, asymbol **);
94 static long mips_elf64_get_dynamic_reloc_upper_bound
95 (bfd *);
96 static long mips_elf64_canonicalize_dynamic_reloc
97 (bfd *, arelent **, asymbol **);
98 static bfd_boolean mips_elf64_slurp_one_reloc_table
99 (bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type, arelent *,
100 asymbol **, bfd_boolean);
101 static bfd_boolean mips_elf64_slurp_reloc_table
102 (bfd *, asection *, asymbol **, bfd_boolean);
103 static void mips_elf64_write_relocs
104 (bfd *, asection *, void *);
105 static void mips_elf64_write_rel
106 (bfd *, asection *, Elf_Internal_Shdr *, int *, void *);
107 static void mips_elf64_write_rela
108 (bfd *, asection *, Elf_Internal_Shdr *, int *, void *);
109 static bfd_reloc_status_type mips_elf64_gprel16_reloc
110 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
111 static bfd_reloc_status_type mips_elf64_literal_reloc
112 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
113 static bfd_reloc_status_type mips_elf64_gprel32_reloc
114 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
115 static bfd_reloc_status_type mips_elf64_shift6_reloc
116 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
117 static bfd_reloc_status_type mips16_gprel_reloc
118 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
119 static bfd_boolean mips_elf64_assign_gp
120 (bfd *, bfd_vma *);
121 static bfd_reloc_status_type mips_elf64_final_gp
122 (bfd *, asymbol *, bfd_boolean, char **, bfd_vma *);
123 static bfd_boolean mips_elf64_object_p
124 (bfd *);
125 static irix_compat_t elf64_mips_irix_compat
126 (bfd *);
127 static bfd_boolean elf64_mips_grok_prstatus
128 (bfd *, Elf_Internal_Note *);
129 static bfd_boolean elf64_mips_grok_psinfo
130 (bfd *, Elf_Internal_Note *);
132 extern const bfd_target bfd_elf64_bigmips_vec;
133 extern const bfd_target bfd_elf64_littlemips_vec;
135 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
136 from smaller values. Start with zero, widen, *then* decrement. */
137 #define MINUS_ONE (((bfd_vma)0) - 1)
139 /* The number of local .got entries we reserve. */
140 #define MIPS_RESERVED_GOTNO (2)
142 /* The relocation table used for SHT_REL sections. */
144 static reloc_howto_type mips_elf64_howto_table_rel[] =
146 /* No relocation. */
147 HOWTO (R_MIPS_NONE, /* type */
148 0, /* rightshift */
149 0, /* size (0 = byte, 1 = short, 2 = long) */
150 0, /* bitsize */
151 FALSE, /* pc_relative */
152 0, /* bitpos */
153 complain_overflow_dont, /* complain_on_overflow */
154 _bfd_mips_elf_generic_reloc, /* special_function */
155 "R_MIPS_NONE", /* name */
156 FALSE, /* partial_inplace */
157 0, /* src_mask */
158 0, /* dst_mask */
159 FALSE), /* pcrel_offset */
161 /* 16 bit relocation. */
162 HOWTO (R_MIPS_16, /* type */
163 0, /* rightshift */
164 2, /* size (0 = byte, 1 = short, 2 = long) */
165 16, /* bitsize */
166 FALSE, /* pc_relative */
167 0, /* bitpos */
168 complain_overflow_signed, /* complain_on_overflow */
169 _bfd_mips_elf_generic_reloc, /* special_function */
170 "R_MIPS_16", /* name */
171 TRUE, /* partial_inplace */
172 0x0000ffff, /* src_mask */
173 0x0000ffff, /* dst_mask */
174 FALSE), /* pcrel_offset */
176 /* 32 bit relocation. */
177 HOWTO (R_MIPS_32, /* type */
178 0, /* rightshift */
179 2, /* size (0 = byte, 1 = short, 2 = long) */
180 32, /* bitsize */
181 FALSE, /* pc_relative */
182 0, /* bitpos */
183 complain_overflow_dont, /* complain_on_overflow */
184 _bfd_mips_elf_generic_reloc, /* special_function */
185 "R_MIPS_32", /* name */
186 TRUE, /* partial_inplace */
187 0xffffffff, /* src_mask */
188 0xffffffff, /* dst_mask */
189 FALSE), /* pcrel_offset */
191 /* 32 bit symbol relative relocation. */
192 HOWTO (R_MIPS_REL32, /* type */
193 0, /* rightshift */
194 2, /* size (0 = byte, 1 = short, 2 = long) */
195 32, /* bitsize */
196 FALSE, /* pc_relative */
197 0, /* bitpos */
198 complain_overflow_dont, /* complain_on_overflow */
199 _bfd_mips_elf_generic_reloc, /* special_function */
200 "R_MIPS_REL32", /* name */
201 TRUE, /* partial_inplace */
202 0xffffffff, /* src_mask */
203 0xffffffff, /* dst_mask */
204 FALSE), /* pcrel_offset */
206 /* 26 bit jump address. */
207 HOWTO (R_MIPS_26, /* type */
208 2, /* rightshift */
209 2, /* size (0 = byte, 1 = short, 2 = long) */
210 26, /* bitsize */
211 FALSE, /* pc_relative */
212 0, /* bitpos */
213 complain_overflow_dont, /* complain_on_overflow */
214 /* This needs complex overflow
215 detection, because the upper 36
216 bits must match the PC + 4. */
217 _bfd_mips_elf_generic_reloc, /* special_function */
218 "R_MIPS_26", /* name */
219 TRUE, /* partial_inplace */
220 0x03ffffff, /* src_mask */
221 0x03ffffff, /* dst_mask */
222 FALSE), /* pcrel_offset */
224 /* R_MIPS_HI16 and R_MIPS_LO16 are unsupported for NewABI REL.
225 However, the native IRIX6 tools use them, so we try our best. */
227 /* High 16 bits of symbol value. */
228 HOWTO (R_MIPS_HI16, /* type */
229 16, /* rightshift */
230 2, /* size (0 = byte, 1 = short, 2 = long) */
231 16, /* bitsize */
232 FALSE, /* pc_relative */
233 0, /* bitpos */
234 complain_overflow_dont, /* complain_on_overflow */
235 _bfd_mips_elf_hi16_reloc, /* special_function */
236 "R_MIPS_HI16", /* name */
237 TRUE, /* partial_inplace */
238 0x0000ffff, /* src_mask */
239 0x0000ffff, /* dst_mask */
240 FALSE), /* pcrel_offset */
242 /* Low 16 bits of symbol value. */
243 HOWTO (R_MIPS_LO16, /* type */
244 0, /* rightshift */
245 2, /* size (0 = byte, 1 = short, 2 = long) */
246 16, /* bitsize */
247 FALSE, /* pc_relative */
248 0, /* bitpos */
249 complain_overflow_dont, /* complain_on_overflow */
250 _bfd_mips_elf_lo16_reloc, /* special_function */
251 "R_MIPS_LO16", /* name */
252 TRUE, /* partial_inplace */
253 0x0000ffff, /* src_mask */
254 0x0000ffff, /* dst_mask */
255 FALSE), /* pcrel_offset */
257 /* GP relative reference. */
258 HOWTO (R_MIPS_GPREL16, /* type */
259 0, /* rightshift */
260 2, /* size (0 = byte, 1 = short, 2 = long) */
261 16, /* bitsize */
262 FALSE, /* pc_relative */
263 0, /* bitpos */
264 complain_overflow_signed, /* complain_on_overflow */
265 mips_elf64_gprel16_reloc, /* special_function */
266 "R_MIPS_GPREL16", /* name */
267 TRUE, /* partial_inplace */
268 0x0000ffff, /* src_mask */
269 0x0000ffff, /* dst_mask */
270 FALSE), /* pcrel_offset */
272 /* Reference to literal section. */
273 HOWTO (R_MIPS_LITERAL, /* type */
274 0, /* rightshift */
275 2, /* size (0 = byte, 1 = short, 2 = long) */
276 16, /* bitsize */
277 FALSE, /* pc_relative */
278 0, /* bitpos */
279 complain_overflow_signed, /* complain_on_overflow */
280 mips_elf64_literal_reloc, /* special_function */
281 "R_MIPS_LITERAL", /* name */
282 TRUE, /* partial_inplace */
283 0x0000ffff, /* src_mask */
284 0x0000ffff, /* dst_mask */
285 FALSE), /* pcrel_offset */
287 /* Reference to global offset table. */
288 HOWTO (R_MIPS_GOT16, /* type */
289 0, /* rightshift */
290 2, /* size (0 = byte, 1 = short, 2 = long) */
291 16, /* bitsize */
292 FALSE, /* pc_relative */
293 0, /* bitpos */
294 complain_overflow_signed, /* complain_on_overflow */
295 _bfd_mips_elf_got16_reloc, /* special_function */
296 "R_MIPS_GOT16", /* name */
297 TRUE, /* partial_inplace */
298 0x0000ffff, /* src_mask */
299 0x0000ffff, /* dst_mask */
300 FALSE), /* pcrel_offset */
302 /* 16 bit PC relative reference. Note that the ABI document has a typo
303 and claims R_MIPS_PC16 to be not rightshifted, rendering it useless.
304 We do the right thing here. */
305 HOWTO (R_MIPS_PC16, /* type */
306 2, /* rightshift */
307 2, /* size (0 = byte, 1 = short, 2 = long) */
308 16, /* bitsize */
309 TRUE, /* pc_relative */
310 0, /* bitpos */
311 complain_overflow_signed, /* complain_on_overflow */
312 _bfd_mips_elf_generic_reloc, /* special_function */
313 "R_MIPS_PC16", /* name */
314 TRUE, /* partial_inplace */
315 0x0000ffff, /* src_mask */
316 0x0000ffff, /* dst_mask */
317 TRUE), /* pcrel_offset */
319 /* 16 bit call through global offset table. */
320 HOWTO (R_MIPS_CALL16, /* type */
321 0, /* rightshift */
322 2, /* size (0 = byte, 1 = short, 2 = long) */
323 16, /* bitsize */
324 FALSE, /* pc_relative */
325 0, /* bitpos */
326 complain_overflow_signed, /* complain_on_overflow */
327 _bfd_mips_elf_generic_reloc, /* special_function */
328 "R_MIPS_CALL16", /* name */
329 TRUE, /* partial_inplace */
330 0x0000ffff, /* src_mask */
331 0x0000ffff, /* dst_mask */
332 FALSE), /* pcrel_offset */
334 /* 32 bit GP relative reference. */
335 HOWTO (R_MIPS_GPREL32, /* type */
336 0, /* rightshift */
337 2, /* size (0 = byte, 1 = short, 2 = long) */
338 32, /* bitsize */
339 FALSE, /* pc_relative */
340 0, /* bitpos */
341 complain_overflow_dont, /* complain_on_overflow */
342 mips_elf64_gprel32_reloc, /* special_function */
343 "R_MIPS_GPREL32", /* name */
344 TRUE, /* partial_inplace */
345 0xffffffff, /* src_mask */
346 0xffffffff, /* dst_mask */
347 FALSE), /* pcrel_offset */
349 EMPTY_HOWTO (13),
350 EMPTY_HOWTO (14),
351 EMPTY_HOWTO (15),
353 /* A 5 bit shift field. */
354 HOWTO (R_MIPS_SHIFT5, /* type */
355 0, /* rightshift */
356 2, /* size (0 = byte, 1 = short, 2 = long) */
357 5, /* bitsize */
358 FALSE, /* pc_relative */
359 6, /* bitpos */
360 complain_overflow_bitfield, /* complain_on_overflow */
361 _bfd_mips_elf_generic_reloc, /* special_function */
362 "R_MIPS_SHIFT5", /* name */
363 TRUE, /* partial_inplace */
364 0x000007c0, /* src_mask */
365 0x000007c0, /* dst_mask */
366 FALSE), /* pcrel_offset */
368 /* A 6 bit shift field. */
369 HOWTO (R_MIPS_SHIFT6, /* type */
370 0, /* rightshift */
371 2, /* size (0 = byte, 1 = short, 2 = long) */
372 6, /* bitsize */
373 FALSE, /* pc_relative */
374 6, /* bitpos */
375 complain_overflow_bitfield, /* complain_on_overflow */
376 mips_elf64_shift6_reloc, /* special_function */
377 "R_MIPS_SHIFT6", /* name */
378 TRUE, /* partial_inplace */
379 0x000007c4, /* src_mask */
380 0x000007c4, /* dst_mask */
381 FALSE), /* pcrel_offset */
383 /* 64 bit relocation. */
384 HOWTO (R_MIPS_64, /* type */
385 0, /* rightshift */
386 4, /* size (0 = byte, 1 = short, 2 = long) */
387 64, /* bitsize */
388 FALSE, /* pc_relative */
389 0, /* bitpos */
390 complain_overflow_dont, /* complain_on_overflow */
391 _bfd_mips_elf_generic_reloc, /* special_function */
392 "R_MIPS_64", /* name */
393 TRUE, /* partial_inplace */
394 MINUS_ONE, /* src_mask */
395 MINUS_ONE, /* dst_mask */
396 FALSE), /* pcrel_offset */
398 /* Displacement in the global offset table. */
399 HOWTO (R_MIPS_GOT_DISP, /* type */
400 0, /* rightshift */
401 2, /* size (0 = byte, 1 = short, 2 = long) */
402 16, /* bitsize */
403 FALSE, /* pc_relative */
404 0, /* bitpos */
405 complain_overflow_signed, /* complain_on_overflow */
406 _bfd_mips_elf_generic_reloc, /* special_function */
407 "R_MIPS_GOT_DISP", /* name */
408 TRUE, /* partial_inplace */
409 0x0000ffff, /* src_mask */
410 0x0000ffff, /* dst_mask */
411 FALSE), /* pcrel_offset */
413 /* Displacement to page pointer in the global offset table. */
414 HOWTO (R_MIPS_GOT_PAGE, /* type */
415 0, /* rightshift */
416 2, /* size (0 = byte, 1 = short, 2 = long) */
417 16, /* bitsize */
418 FALSE, /* pc_relative */
419 0, /* bitpos */
420 complain_overflow_signed, /* complain_on_overflow */
421 _bfd_mips_elf_generic_reloc, /* special_function */
422 "R_MIPS_GOT_PAGE", /* name */
423 TRUE, /* partial_inplace */
424 0x0000ffff, /* src_mask */
425 0x0000ffff, /* dst_mask */
426 FALSE), /* pcrel_offset */
428 /* Offset from page pointer in the global offset table. */
429 HOWTO (R_MIPS_GOT_OFST, /* type */
430 0, /* rightshift */
431 2, /* size (0 = byte, 1 = short, 2 = long) */
432 16, /* bitsize */
433 FALSE, /* pc_relative */
434 0, /* bitpos */
435 complain_overflow_signed, /* complain_on_overflow */
436 _bfd_mips_elf_generic_reloc, /* special_function */
437 "R_MIPS_GOT_OFST", /* name */
438 TRUE, /* partial_inplace */
439 0x0000ffff, /* src_mask */
440 0x0000ffff, /* dst_mask */
441 FALSE), /* pcrel_offset */
443 /* High 16 bits of displacement in global offset table. */
444 HOWTO (R_MIPS_GOT_HI16, /* type */
445 0, /* rightshift */
446 2, /* size (0 = byte, 1 = short, 2 = long) */
447 16, /* bitsize */
448 FALSE, /* pc_relative */
449 0, /* bitpos */
450 complain_overflow_dont, /* complain_on_overflow */
451 _bfd_mips_elf_generic_reloc, /* special_function */
452 "R_MIPS_GOT_HI16", /* name */
453 TRUE, /* partial_inplace */
454 0x0000ffff, /* src_mask */
455 0x0000ffff, /* dst_mask */
456 FALSE), /* pcrel_offset */
458 /* Low 16 bits of displacement in global offset table. */
459 HOWTO (R_MIPS_GOT_LO16, /* type */
460 0, /* rightshift */
461 2, /* size (0 = byte, 1 = short, 2 = long) */
462 16, /* bitsize */
463 FALSE, /* pc_relative */
464 0, /* bitpos */
465 complain_overflow_dont, /* complain_on_overflow */
466 _bfd_mips_elf_generic_reloc, /* special_function */
467 "R_MIPS_GOT_LO16", /* name */
468 TRUE, /* partial_inplace */
469 0x0000ffff, /* src_mask */
470 0x0000ffff, /* dst_mask */
471 FALSE), /* pcrel_offset */
473 /* 64 bit subtraction. */
474 HOWTO (R_MIPS_SUB, /* type */
475 0, /* rightshift */
476 4, /* size (0 = byte, 1 = short, 2 = long) */
477 64, /* bitsize */
478 FALSE, /* pc_relative */
479 0, /* bitpos */
480 complain_overflow_dont, /* complain_on_overflow */
481 _bfd_mips_elf_generic_reloc, /* special_function */
482 "R_MIPS_SUB", /* name */
483 TRUE, /* partial_inplace */
484 MINUS_ONE, /* src_mask */
485 MINUS_ONE, /* dst_mask */
486 FALSE), /* pcrel_offset */
488 /* Insert the addend as an instruction. */
489 /* FIXME: Not handled correctly. */
490 HOWTO (R_MIPS_INSERT_A, /* type */
491 0, /* rightshift */
492 2, /* size (0 = byte, 1 = short, 2 = long) */
493 32, /* bitsize */
494 FALSE, /* pc_relative */
495 0, /* bitpos */
496 complain_overflow_dont, /* complain_on_overflow */
497 _bfd_mips_elf_generic_reloc, /* special_function */
498 "R_MIPS_INSERT_A", /* name */
499 TRUE, /* partial_inplace */
500 0xffffffff, /* src_mask */
501 0xffffffff, /* dst_mask */
502 FALSE), /* pcrel_offset */
504 /* Insert the addend as an instruction, and change all relocations
505 to refer to the old instruction at the address. */
506 /* FIXME: Not handled correctly. */
507 HOWTO (R_MIPS_INSERT_B, /* type */
508 0, /* rightshift */
509 2, /* size (0 = byte, 1 = short, 2 = long) */
510 32, /* bitsize */
511 FALSE, /* pc_relative */
512 0, /* bitpos */
513 complain_overflow_dont, /* complain_on_overflow */
514 _bfd_mips_elf_generic_reloc, /* special_function */
515 "R_MIPS_INSERT_B", /* name */
516 TRUE, /* partial_inplace */
517 0xffffffff, /* src_mask */
518 0xffffffff, /* dst_mask */
519 FALSE), /* pcrel_offset */
521 /* Delete a 32 bit instruction. */
522 /* FIXME: Not handled correctly. */
523 HOWTO (R_MIPS_DELETE, /* type */
524 0, /* rightshift */
525 2, /* size (0 = byte, 1 = short, 2 = long) */
526 32, /* bitsize */
527 FALSE, /* pc_relative */
528 0, /* bitpos */
529 complain_overflow_dont, /* complain_on_overflow */
530 _bfd_mips_elf_generic_reloc, /* special_function */
531 "R_MIPS_DELETE", /* name */
532 TRUE, /* partial_inplace */
533 0xffffffff, /* src_mask */
534 0xffffffff, /* dst_mask */
535 FALSE), /* pcrel_offset */
537 /* The MIPS ELF64 ABI Draft wants us to support these for REL relocations.
538 We don't, because
539 a) It means building the addend from a R_MIPS_HIGHEST/R_MIPS_HIGHER/
540 R_MIPS_HI16/R_MIPS_LO16 sequence with varying ordering, using
541 fallable heuristics.
542 b) No other NewABI toolchain actually emits such relocations. */
543 EMPTY_HOWTO (R_MIPS_HIGHER),
544 EMPTY_HOWTO (R_MIPS_HIGHEST),
546 /* High 16 bits of displacement in global offset table. */
547 HOWTO (R_MIPS_CALL_HI16, /* type */
548 0, /* rightshift */
549 2, /* size (0 = byte, 1 = short, 2 = long) */
550 16, /* bitsize */
551 FALSE, /* pc_relative */
552 0, /* bitpos */
553 complain_overflow_dont, /* complain_on_overflow */
554 _bfd_mips_elf_generic_reloc, /* special_function */
555 "R_MIPS_CALL_HI16", /* name */
556 TRUE, /* partial_inplace */
557 0x0000ffff, /* src_mask */
558 0x0000ffff, /* dst_mask */
559 FALSE), /* pcrel_offset */
561 /* Low 16 bits of displacement in global offset table. */
562 HOWTO (R_MIPS_CALL_LO16, /* type */
563 0, /* rightshift */
564 2, /* size (0 = byte, 1 = short, 2 = long) */
565 16, /* bitsize */
566 FALSE, /* pc_relative */
567 0, /* bitpos */
568 complain_overflow_dont, /* complain_on_overflow */
569 _bfd_mips_elf_generic_reloc, /* special_function */
570 "R_MIPS_CALL_LO16", /* name */
571 TRUE, /* partial_inplace */
572 0x0000ffff, /* src_mask */
573 0x0000ffff, /* dst_mask */
574 FALSE), /* pcrel_offset */
576 /* Section displacement, used by an associated event location section. */
577 HOWTO (R_MIPS_SCN_DISP, /* type */
578 0, /* rightshift */
579 2, /* size (0 = byte, 1 = short, 2 = long) */
580 32, /* bitsize */
581 FALSE, /* pc_relative */
582 0, /* bitpos */
583 complain_overflow_dont, /* complain_on_overflow */
584 _bfd_mips_elf_generic_reloc, /* special_function */
585 "R_MIPS_SCN_DISP", /* name */
586 TRUE, /* partial_inplace */
587 0xffffffff, /* src_mask */
588 0xffffffff, /* dst_mask */
589 FALSE), /* pcrel_offset */
591 HOWTO (R_MIPS_REL16, /* type */
592 0, /* rightshift */
593 1, /* size (0 = byte, 1 = short, 2 = long) */
594 16, /* bitsize */
595 FALSE, /* pc_relative */
596 0, /* bitpos */
597 complain_overflow_signed, /* complain_on_overflow */
598 _bfd_mips_elf_generic_reloc, /* special_function */
599 "R_MIPS_REL16", /* name */
600 TRUE, /* partial_inplace */
601 0xffff, /* src_mask */
602 0xffff, /* dst_mask */
603 FALSE), /* pcrel_offset */
605 /* These two are obsolete. */
606 EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
607 EMPTY_HOWTO (R_MIPS_PJUMP),
609 /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
610 It must be used for multigot GOT's (and only there). */
611 HOWTO (R_MIPS_RELGOT, /* type */
612 0, /* rightshift */
613 2, /* size (0 = byte, 1 = short, 2 = long) */
614 32, /* bitsize */
615 FALSE, /* pc_relative */
616 0, /* bitpos */
617 complain_overflow_dont, /* complain_on_overflow */
618 _bfd_mips_elf_generic_reloc, /* special_function */
619 "R_MIPS_RELGOT", /* name */
620 TRUE, /* partial_inplace */
621 0xffffffff, /* src_mask */
622 0xffffffff, /* dst_mask */
623 FALSE), /* pcrel_offset */
625 /* Protected jump conversion. This is an optimization hint. No
626 relocation is required for correctness. */
627 HOWTO (R_MIPS_JALR, /* type */
628 0, /* rightshift */
629 2, /* size (0 = byte, 1 = short, 2 = long) */
630 32, /* bitsize */
631 FALSE, /* pc_relative */
632 0, /* bitpos */
633 complain_overflow_dont, /* complain_on_overflow */
634 _bfd_mips_elf_generic_reloc, /* special_function */
635 "R_MIPS_JALR", /* name */
636 FALSE, /* partial_inplace */
637 0, /* src_mask */
638 0x00000000, /* dst_mask */
639 FALSE), /* pcrel_offset */
641 /* TLS relocations. */
642 EMPTY_HOWTO (R_MIPS_TLS_DTPMOD32),
643 EMPTY_HOWTO (R_MIPS_TLS_DTPREL32),
645 HOWTO (R_MIPS_TLS_DTPMOD64, /* type */
646 0, /* rightshift */
647 4, /* size (0 = byte, 1 = short, 2 = long) */
648 64, /* bitsize */
649 FALSE, /* pc_relative */
650 0, /* bitpos */
651 complain_overflow_dont, /* complain_on_overflow */
652 _bfd_mips_elf_generic_reloc, /* special_function */
653 "R_MIPS_TLS_DTPMOD64", /* name */
654 TRUE, /* partial_inplace */
655 MINUS_ONE, /* src_mask */
656 MINUS_ONE, /* dst_mask */
657 FALSE), /* pcrel_offset */
659 HOWTO (R_MIPS_TLS_DTPREL64, /* type */
660 0, /* rightshift */
661 4, /* size (0 = byte, 1 = short, 2 = long) */
662 64, /* bitsize */
663 FALSE, /* pc_relative */
664 0, /* bitpos */
665 complain_overflow_dont, /* complain_on_overflow */
666 _bfd_mips_elf_generic_reloc, /* special_function */
667 "R_MIPS_TLS_DTPREL64", /* name */
668 TRUE, /* partial_inplace */
669 MINUS_ONE, /* src_mask */
670 MINUS_ONE, /* dst_mask */
671 FALSE), /* pcrel_offset */
673 /* TLS general dynamic variable reference. */
674 HOWTO (R_MIPS_TLS_GD, /* type */
675 0, /* rightshift */
676 2, /* size (0 = byte, 1 = short, 2 = long) */
677 16, /* bitsize */
678 FALSE, /* pc_relative */
679 0, /* bitpos */
680 complain_overflow_signed, /* complain_on_overflow */
681 _bfd_mips_elf_generic_reloc, /* special_function */
682 "R_MIPS_TLS_GD", /* name */
683 TRUE, /* partial_inplace */
684 0x0000ffff, /* src_mask */
685 0x0000ffff, /* dst_mask */
686 FALSE), /* pcrel_offset */
688 /* TLS local dynamic variable reference. */
689 HOWTO (R_MIPS_TLS_LDM, /* type */
690 0, /* rightshift */
691 2, /* size (0 = byte, 1 = short, 2 = long) */
692 16, /* bitsize */
693 FALSE, /* pc_relative */
694 0, /* bitpos */
695 complain_overflow_signed, /* complain_on_overflow */
696 _bfd_mips_elf_generic_reloc, /* special_function */
697 "R_MIPS_TLS_LDM", /* name */
698 TRUE, /* partial_inplace */
699 0x0000ffff, /* src_mask */
700 0x0000ffff, /* dst_mask */
701 FALSE), /* pcrel_offset */
703 /* TLS local dynamic offset. */
704 HOWTO (R_MIPS_TLS_DTPREL_HI16, /* type */
705 0, /* rightshift */
706 2, /* size (0 = byte, 1 = short, 2 = long) */
707 16, /* bitsize */
708 FALSE, /* pc_relative */
709 0, /* bitpos */
710 complain_overflow_signed, /* complain_on_overflow */
711 _bfd_mips_elf_generic_reloc, /* special_function */
712 "R_MIPS_TLS_DTPREL_HI16", /* name */
713 TRUE, /* partial_inplace */
714 0x0000ffff, /* src_mask */
715 0x0000ffff, /* dst_mask */
716 FALSE), /* pcrel_offset */
718 /* TLS local dynamic offset. */
719 HOWTO (R_MIPS_TLS_DTPREL_LO16, /* type */
720 0, /* rightshift */
721 2, /* size (0 = byte, 1 = short, 2 = long) */
722 16, /* bitsize */
723 FALSE, /* pc_relative */
724 0, /* bitpos */
725 complain_overflow_signed, /* complain_on_overflow */
726 _bfd_mips_elf_generic_reloc, /* special_function */
727 "R_MIPS_TLS_DTPREL_LO16", /* name */
728 TRUE, /* partial_inplace */
729 0x0000ffff, /* src_mask */
730 0x0000ffff, /* dst_mask */
731 FALSE), /* pcrel_offset */
733 /* TLS thread pointer offset. */
734 HOWTO (R_MIPS_TLS_GOTTPREL, /* type */
735 0, /* rightshift */
736 2, /* size (0 = byte, 1 = short, 2 = long) */
737 16, /* bitsize */
738 FALSE, /* pc_relative */
739 0, /* bitpos */
740 complain_overflow_signed, /* complain_on_overflow */
741 _bfd_mips_elf_generic_reloc, /* special_function */
742 "R_MIPS_TLS_GOTTPREL", /* name */
743 TRUE, /* partial_inplace */
744 0x0000ffff, /* src_mask */
745 0x0000ffff, /* dst_mask */
746 FALSE), /* pcrel_offset */
748 /* TLS IE dynamic relocations. */
749 EMPTY_HOWTO (R_MIPS_TLS_TPREL32),
751 HOWTO (R_MIPS_TLS_TPREL64, /* type */
752 0, /* rightshift */
753 4, /* size (0 = byte, 1 = short, 2 = long) */
754 64, /* bitsize */
755 FALSE, /* pc_relative */
756 0, /* bitpos */
757 complain_overflow_dont, /* complain_on_overflow */
758 _bfd_mips_elf_generic_reloc, /* special_function */
759 "R_MIPS_TLS_TPREL64", /* name */
760 TRUE, /* partial_inplace */
761 MINUS_ONE, /* src_mask */
762 MINUS_ONE, /* dst_mask */
763 FALSE), /* pcrel_offset */
765 /* TLS thread pointer offset. */
766 HOWTO (R_MIPS_TLS_TPREL_HI16, /* type */
767 0, /* rightshift */
768 2, /* size (0 = byte, 1 = short, 2 = long) */
769 16, /* bitsize */
770 FALSE, /* pc_relative */
771 0, /* bitpos */
772 complain_overflow_signed, /* complain_on_overflow */
773 _bfd_mips_elf_generic_reloc, /* special_function */
774 "R_MIPS_TLS_TPREL_HI16", /* name */
775 TRUE, /* partial_inplace */
776 0x0000ffff, /* src_mask */
777 0x0000ffff, /* dst_mask */
778 FALSE), /* pcrel_offset */
780 /* TLS thread pointer offset. */
781 HOWTO (R_MIPS_TLS_TPREL_LO16, /* type */
782 0, /* rightshift */
783 2, /* size (0 = byte, 1 = short, 2 = long) */
784 16, /* bitsize */
785 FALSE, /* pc_relative */
786 0, /* bitpos */
787 complain_overflow_signed, /* complain_on_overflow */
788 _bfd_mips_elf_generic_reloc, /* special_function */
789 "R_MIPS_TLS_TPREL_LO16", /* name */
790 TRUE, /* partial_inplace */
791 0x0000ffff, /* src_mask */
792 0x0000ffff, /* dst_mask */
793 FALSE), /* pcrel_offset */
795 /* 32 bit relocation with no addend. */
796 HOWTO (R_MIPS_GLOB_DAT, /* type */
797 0, /* rightshift */
798 2, /* size (0 = byte, 1 = short, 2 = long) */
799 32, /* bitsize */
800 FALSE, /* pc_relative */
801 0, /* bitpos */
802 complain_overflow_dont, /* complain_on_overflow */
803 _bfd_mips_elf_generic_reloc, /* special_function */
804 "R_MIPS_GLOB_DAT", /* name */
805 FALSE, /* partial_inplace */
806 0x0, /* src_mask */
807 0xffffffff, /* dst_mask */
808 FALSE), /* pcrel_offset */
811 /* The relocation table used for SHT_RELA sections. */
813 static reloc_howto_type mips_elf64_howto_table_rela[] =
815 /* No relocation. */
816 HOWTO (R_MIPS_NONE, /* type */
817 0, /* rightshift */
818 0, /* size (0 = byte, 1 = short, 2 = long) */
819 0, /* bitsize */
820 FALSE, /* pc_relative */
821 0, /* bitpos */
822 complain_overflow_dont, /* complain_on_overflow */
823 _bfd_mips_elf_generic_reloc, /* special_function */
824 "R_MIPS_NONE", /* name */
825 FALSE, /* partial_inplace */
826 0, /* src_mask */
827 0, /* dst_mask */
828 FALSE), /* pcrel_offset */
830 /* 16 bit relocation. */
831 HOWTO (R_MIPS_16, /* type */
832 0, /* rightshift */
833 2, /* size (0 = byte, 1 = short, 2 = long) */
834 16, /* bitsize */
835 FALSE, /* pc_relative */
836 0, /* bitpos */
837 complain_overflow_signed, /* complain_on_overflow */
838 _bfd_mips_elf_generic_reloc, /* special_function */
839 "R_MIPS_16", /* name */
840 FALSE, /* partial_inplace */
841 0, /* src_mask */
842 0x0000ffff, /* dst_mask */
843 FALSE), /* pcrel_offset */
845 /* 32 bit relocation. */
846 HOWTO (R_MIPS_32, /* type */
847 0, /* rightshift */
848 2, /* size (0 = byte, 1 = short, 2 = long) */
849 32, /* bitsize */
850 FALSE, /* pc_relative */
851 0, /* bitpos */
852 complain_overflow_dont, /* complain_on_overflow */
853 _bfd_mips_elf_generic_reloc, /* special_function */
854 "R_MIPS_32", /* name */
855 FALSE, /* partial_inplace */
856 0, /* src_mask */
857 0xffffffff, /* dst_mask */
858 FALSE), /* pcrel_offset */
860 /* 32 bit symbol relative relocation. */
861 HOWTO (R_MIPS_REL32, /* type */
862 0, /* rightshift */
863 2, /* size (0 = byte, 1 = short, 2 = long) */
864 32, /* bitsize */
865 FALSE, /* pc_relative */
866 0, /* bitpos */
867 complain_overflow_dont, /* complain_on_overflow */
868 _bfd_mips_elf_generic_reloc, /* special_function */
869 "R_MIPS_REL32", /* name */
870 FALSE, /* partial_inplace */
871 0, /* src_mask */
872 0xffffffff, /* dst_mask */
873 FALSE), /* pcrel_offset */
875 /* 26 bit jump address. */
876 HOWTO (R_MIPS_26, /* type */
877 2, /* rightshift */
878 2, /* size (0 = byte, 1 = short, 2 = long) */
879 26, /* bitsize */
880 FALSE, /* pc_relative */
881 0, /* bitpos */
882 complain_overflow_dont, /* complain_on_overflow */
883 /* This needs complex overflow
884 detection, because the upper 36
885 bits must match the PC + 4. */
886 _bfd_mips_elf_generic_reloc, /* special_function */
887 "R_MIPS_26", /* name */
888 FALSE, /* partial_inplace */
889 0, /* src_mask */
890 0x03ffffff, /* dst_mask */
891 FALSE), /* pcrel_offset */
893 /* High 16 bits of symbol value. */
894 HOWTO (R_MIPS_HI16, /* type */
895 0, /* rightshift */
896 2, /* size (0 = byte, 1 = short, 2 = long) */
897 16, /* bitsize */
898 FALSE, /* pc_relative */
899 0, /* bitpos */
900 complain_overflow_dont, /* complain_on_overflow */
901 _bfd_mips_elf_generic_reloc, /* special_function */
902 "R_MIPS_HI16", /* name */
903 FALSE, /* partial_inplace */
904 0, /* src_mask */
905 0x0000ffff, /* dst_mask */
906 FALSE), /* pcrel_offset */
908 /* Low 16 bits of symbol value. */
909 HOWTO (R_MIPS_LO16, /* type */
910 0, /* rightshift */
911 2, /* size (0 = byte, 1 = short, 2 = long) */
912 16, /* bitsize */
913 FALSE, /* pc_relative */
914 0, /* bitpos */
915 complain_overflow_dont, /* complain_on_overflow */
916 _bfd_mips_elf_generic_reloc, /* special_function */
917 "R_MIPS_LO16", /* name */
918 FALSE, /* partial_inplace */
919 0, /* src_mask */
920 0x0000ffff, /* dst_mask */
921 FALSE), /* pcrel_offset */
923 /* GP relative reference. */
924 HOWTO (R_MIPS_GPREL16, /* type */
925 0, /* rightshift */
926 2, /* size (0 = byte, 1 = short, 2 = long) */
927 16, /* bitsize */
928 FALSE, /* pc_relative */
929 0, /* bitpos */
930 complain_overflow_signed, /* complain_on_overflow */
931 mips_elf64_gprel16_reloc, /* special_function */
932 "R_MIPS_GPREL16", /* name */
933 FALSE, /* partial_inplace */
934 0, /* src_mask */
935 0x0000ffff, /* dst_mask */
936 FALSE), /* pcrel_offset */
938 /* Reference to literal section. */
939 HOWTO (R_MIPS_LITERAL, /* type */
940 0, /* rightshift */
941 2, /* size (0 = byte, 1 = short, 2 = long) */
942 16, /* bitsize */
943 FALSE, /* pc_relative */
944 0, /* bitpos */
945 complain_overflow_signed, /* complain_on_overflow */
946 mips_elf64_literal_reloc, /* special_function */
947 "R_MIPS_LITERAL", /* name */
948 FALSE, /* partial_inplace */
949 0, /* src_mask */
950 0x0000ffff, /* dst_mask */
951 FALSE), /* pcrel_offset */
953 /* Reference to global offset table. */
954 HOWTO (R_MIPS_GOT16, /* type */
955 0, /* rightshift */
956 2, /* size (0 = byte, 1 = short, 2 = long) */
957 16, /* bitsize */
958 FALSE, /* pc_relative */
959 0, /* bitpos */
960 complain_overflow_signed, /* complain_on_overflow */
961 _bfd_mips_elf_generic_reloc, /* special_function */
962 "R_MIPS_GOT16", /* name */
963 FALSE, /* partial_inplace */
964 0, /* src_mask */
965 0x0000ffff, /* dst_mask */
966 FALSE), /* pcrel_offset */
968 /* 16 bit PC relative reference. Note that the ABI document has a typo
969 and claims R_MIPS_PC16 to be not rightshifted, rendering it useless.
970 We do the right thing here. */
971 HOWTO (R_MIPS_PC16, /* type */
972 2, /* rightshift */
973 2, /* size (0 = byte, 1 = short, 2 = long) */
974 16, /* bitsize */
975 TRUE, /* pc_relative */
976 0, /* bitpos */
977 complain_overflow_signed, /* complain_on_overflow */
978 _bfd_mips_elf_generic_reloc, /* special_function */
979 "R_MIPS_PC16", /* name */
980 FALSE, /* partial_inplace */
981 0, /* src_mask */
982 0x0000ffff, /* dst_mask */
983 TRUE), /* pcrel_offset */
985 /* 16 bit call through global offset table. */
986 HOWTO (R_MIPS_CALL16, /* type */
987 0, /* rightshift */
988 2, /* size (0 = byte, 1 = short, 2 = long) */
989 16, /* bitsize */
990 FALSE, /* pc_relative */
991 0, /* bitpos */
992 complain_overflow_signed, /* complain_on_overflow */
993 _bfd_mips_elf_generic_reloc, /* special_function */
994 "R_MIPS_CALL16", /* name */
995 FALSE, /* partial_inplace */
996 0, /* src_mask */
997 0x0000ffff, /* dst_mask */
998 FALSE), /* pcrel_offset */
1000 /* 32 bit GP relative reference. */
1001 HOWTO (R_MIPS_GPREL32, /* type */
1002 0, /* rightshift */
1003 2, /* size (0 = byte, 1 = short, 2 = long) */
1004 32, /* bitsize */
1005 FALSE, /* pc_relative */
1006 0, /* bitpos */
1007 complain_overflow_dont, /* complain_on_overflow */
1008 mips_elf64_gprel32_reloc, /* special_function */
1009 "R_MIPS_GPREL32", /* name */
1010 FALSE, /* partial_inplace */
1011 0, /* src_mask */
1012 0xffffffff, /* dst_mask */
1013 FALSE), /* pcrel_offset */
1015 EMPTY_HOWTO (13),
1016 EMPTY_HOWTO (14),
1017 EMPTY_HOWTO (15),
1019 /* A 5 bit shift field. */
1020 HOWTO (R_MIPS_SHIFT5, /* type */
1021 0, /* rightshift */
1022 2, /* size (0 = byte, 1 = short, 2 = long) */
1023 5, /* bitsize */
1024 FALSE, /* pc_relative */
1025 6, /* bitpos */
1026 complain_overflow_bitfield, /* complain_on_overflow */
1027 _bfd_mips_elf_generic_reloc, /* special_function */
1028 "R_MIPS_SHIFT5", /* name */
1029 FALSE, /* partial_inplace */
1030 0, /* src_mask */
1031 0x000007c0, /* dst_mask */
1032 FALSE), /* pcrel_offset */
1034 /* A 6 bit shift field. */
1035 HOWTO (R_MIPS_SHIFT6, /* type */
1036 0, /* rightshift */
1037 2, /* size (0 = byte, 1 = short, 2 = long) */
1038 6, /* bitsize */
1039 FALSE, /* pc_relative */
1040 6, /* bitpos */
1041 complain_overflow_bitfield, /* complain_on_overflow */
1042 mips_elf64_shift6_reloc, /* special_function */
1043 "R_MIPS_SHIFT6", /* name */
1044 FALSE, /* partial_inplace */
1045 0, /* src_mask */
1046 0x000007c4, /* dst_mask */
1047 FALSE), /* pcrel_offset */
1049 /* 64 bit relocation. */
1050 HOWTO (R_MIPS_64, /* type */
1051 0, /* rightshift */
1052 4, /* size (0 = byte, 1 = short, 2 = long) */
1053 64, /* bitsize */
1054 FALSE, /* pc_relative */
1055 0, /* bitpos */
1056 complain_overflow_dont, /* complain_on_overflow */
1057 _bfd_mips_elf_generic_reloc, /* special_function */
1058 "R_MIPS_64", /* name */
1059 FALSE, /* partial_inplace */
1060 0, /* src_mask */
1061 MINUS_ONE, /* dst_mask */
1062 FALSE), /* pcrel_offset */
1064 /* Displacement in the global offset table. */
1065 HOWTO (R_MIPS_GOT_DISP, /* type */
1066 0, /* rightshift */
1067 2, /* size (0 = byte, 1 = short, 2 = long) */
1068 16, /* bitsize */
1069 FALSE, /* pc_relative */
1070 0, /* bitpos */
1071 complain_overflow_signed, /* complain_on_overflow */
1072 _bfd_mips_elf_generic_reloc, /* special_function */
1073 "R_MIPS_GOT_DISP", /* name */
1074 FALSE, /* partial_inplace */
1075 0, /* src_mask */
1076 0x0000ffff, /* dst_mask */
1077 FALSE), /* pcrel_offset */
1079 /* Displacement to page pointer in the global offset table. */
1080 HOWTO (R_MIPS_GOT_PAGE, /* type */
1081 0, /* rightshift */
1082 2, /* size (0 = byte, 1 = short, 2 = long) */
1083 16, /* bitsize */
1084 FALSE, /* pc_relative */
1085 0, /* bitpos */
1086 complain_overflow_signed, /* complain_on_overflow */
1087 _bfd_mips_elf_generic_reloc, /* special_function */
1088 "R_MIPS_GOT_PAGE", /* name */
1089 FALSE, /* partial_inplace */
1090 0, /* src_mask */
1091 0x0000ffff, /* dst_mask */
1092 FALSE), /* pcrel_offset */
1094 /* Offset from page pointer in the global offset table. */
1095 HOWTO (R_MIPS_GOT_OFST, /* type */
1096 0, /* rightshift */
1097 2, /* size (0 = byte, 1 = short, 2 = long) */
1098 16, /* bitsize */
1099 FALSE, /* pc_relative */
1100 0, /* bitpos */
1101 complain_overflow_signed, /* complain_on_overflow */
1102 _bfd_mips_elf_generic_reloc, /* special_function */
1103 "R_MIPS_GOT_OFST", /* name */
1104 FALSE, /* partial_inplace */
1105 0, /* src_mask */
1106 0x0000ffff, /* dst_mask */
1107 FALSE), /* pcrel_offset */
1109 /* High 16 bits of displacement in global offset table. */
1110 HOWTO (R_MIPS_GOT_HI16, /* type */
1111 0, /* rightshift */
1112 2, /* size (0 = byte, 1 = short, 2 = long) */
1113 16, /* bitsize */
1114 FALSE, /* pc_relative */
1115 0, /* bitpos */
1116 complain_overflow_dont, /* complain_on_overflow */
1117 _bfd_mips_elf_generic_reloc, /* special_function */
1118 "R_MIPS_GOT_HI16", /* name */
1119 FALSE, /* partial_inplace */
1120 0, /* src_mask */
1121 0x0000ffff, /* dst_mask */
1122 FALSE), /* pcrel_offset */
1124 /* Low 16 bits of displacement in global offset table. */
1125 HOWTO (R_MIPS_GOT_LO16, /* type */
1126 0, /* rightshift */
1127 2, /* size (0 = byte, 1 = short, 2 = long) */
1128 16, /* bitsize */
1129 FALSE, /* pc_relative */
1130 0, /* bitpos */
1131 complain_overflow_dont, /* complain_on_overflow */
1132 _bfd_mips_elf_generic_reloc, /* special_function */
1133 "R_MIPS_GOT_LO16", /* name */
1134 FALSE, /* partial_inplace */
1135 0, /* src_mask */
1136 0x0000ffff, /* dst_mask */
1137 FALSE), /* pcrel_offset */
1139 /* 64 bit subtraction. */
1140 HOWTO (R_MIPS_SUB, /* type */
1141 0, /* rightshift */
1142 4, /* size (0 = byte, 1 = short, 2 = long) */
1143 64, /* bitsize */
1144 FALSE, /* pc_relative */
1145 0, /* bitpos */
1146 complain_overflow_dont, /* complain_on_overflow */
1147 _bfd_mips_elf_generic_reloc, /* special_function */
1148 "R_MIPS_SUB", /* name */
1149 FALSE, /* partial_inplace */
1150 0, /* src_mask */
1151 MINUS_ONE, /* dst_mask */
1152 FALSE), /* pcrel_offset */
1154 /* Insert the addend as an instruction. */
1155 /* FIXME: Not handled correctly. */
1156 HOWTO (R_MIPS_INSERT_A, /* type */
1157 0, /* rightshift */
1158 2, /* size (0 = byte, 1 = short, 2 = long) */
1159 32, /* bitsize */
1160 FALSE, /* pc_relative */
1161 0, /* bitpos */
1162 complain_overflow_dont, /* complain_on_overflow */
1163 _bfd_mips_elf_generic_reloc, /* special_function */
1164 "R_MIPS_INSERT_A", /* name */
1165 FALSE, /* partial_inplace */
1166 0, /* src_mask */
1167 0xffffffff, /* dst_mask */
1168 FALSE), /* pcrel_offset */
1170 /* Insert the addend as an instruction, and change all relocations
1171 to refer to the old instruction at the address. */
1172 /* FIXME: Not handled correctly. */
1173 HOWTO (R_MIPS_INSERT_B, /* type */
1174 0, /* rightshift */
1175 2, /* size (0 = byte, 1 = short, 2 = long) */
1176 32, /* bitsize */
1177 FALSE, /* pc_relative */
1178 0, /* bitpos */
1179 complain_overflow_dont, /* complain_on_overflow */
1180 _bfd_mips_elf_generic_reloc, /* special_function */
1181 "R_MIPS_INSERT_B", /* name */
1182 FALSE, /* partial_inplace */
1183 0, /* src_mask */
1184 0xffffffff, /* dst_mask */
1185 FALSE), /* pcrel_offset */
1187 /* Delete a 32 bit instruction. */
1188 /* FIXME: Not handled correctly. */
1189 HOWTO (R_MIPS_DELETE, /* type */
1190 0, /* rightshift */
1191 2, /* size (0 = byte, 1 = short, 2 = long) */
1192 32, /* bitsize */
1193 FALSE, /* pc_relative */
1194 0, /* bitpos */
1195 complain_overflow_dont, /* complain_on_overflow */
1196 _bfd_mips_elf_generic_reloc, /* special_function */
1197 "R_MIPS_DELETE", /* name */
1198 FALSE, /* partial_inplace */
1199 0, /* src_mask */
1200 0xffffffff, /* dst_mask */
1201 FALSE), /* pcrel_offset */
1203 /* Get the higher value of a 64 bit addend. */
1204 HOWTO (R_MIPS_HIGHER, /* type */
1205 0, /* rightshift */
1206 2, /* size (0 = byte, 1 = short, 2 = long) */
1207 16, /* bitsize */
1208 FALSE, /* pc_relative */
1209 0, /* bitpos */
1210 complain_overflow_dont, /* complain_on_overflow */
1211 _bfd_mips_elf_generic_reloc, /* special_function */
1212 "R_MIPS_HIGHER", /* name */
1213 FALSE, /* partial_inplace */
1214 0, /* src_mask */
1215 0x0000ffff, /* dst_mask */
1216 FALSE), /* pcrel_offset */
1218 /* Get the highest value of a 64 bit addend. */
1219 HOWTO (R_MIPS_HIGHEST, /* type */
1220 0, /* rightshift */
1221 2, /* size (0 = byte, 1 = short, 2 = long) */
1222 16, /* bitsize */
1223 FALSE, /* pc_relative */
1224 0, /* bitpos */
1225 complain_overflow_dont, /* complain_on_overflow */
1226 _bfd_mips_elf_generic_reloc, /* special_function */
1227 "R_MIPS_HIGHEST", /* name */
1228 FALSE, /* partial_inplace */
1229 0, /* src_mask */
1230 0x0000ffff, /* dst_mask */
1231 FALSE), /* pcrel_offset */
1233 /* High 16 bits of displacement in global offset table. */
1234 HOWTO (R_MIPS_CALL_HI16, /* type */
1235 0, /* rightshift */
1236 2, /* size (0 = byte, 1 = short, 2 = long) */
1237 16, /* bitsize */
1238 FALSE, /* pc_relative */
1239 0, /* bitpos */
1240 complain_overflow_dont, /* complain_on_overflow */
1241 _bfd_mips_elf_generic_reloc, /* special_function */
1242 "R_MIPS_CALL_HI16", /* name */
1243 FALSE, /* partial_inplace */
1244 0, /* src_mask */
1245 0x0000ffff, /* dst_mask */
1246 FALSE), /* pcrel_offset */
1248 /* Low 16 bits of displacement in global offset table. */
1249 HOWTO (R_MIPS_CALL_LO16, /* type */
1250 0, /* rightshift */
1251 2, /* size (0 = byte, 1 = short, 2 = long) */
1252 16, /* bitsize */
1253 FALSE, /* pc_relative */
1254 0, /* bitpos */
1255 complain_overflow_dont, /* complain_on_overflow */
1256 _bfd_mips_elf_generic_reloc, /* special_function */
1257 "R_MIPS_CALL_LO16", /* name */
1258 FALSE, /* partial_inplace */
1259 0, /* src_mask */
1260 0x0000ffff, /* dst_mask */
1261 FALSE), /* pcrel_offset */
1263 /* Section displacement, used by an associated event location section. */
1264 HOWTO (R_MIPS_SCN_DISP, /* type */
1265 0, /* rightshift */
1266 2, /* size (0 = byte, 1 = short, 2 = long) */
1267 32, /* bitsize */
1268 FALSE, /* pc_relative */
1269 0, /* bitpos */
1270 complain_overflow_dont, /* complain_on_overflow */
1271 _bfd_mips_elf_generic_reloc, /* special_function */
1272 "R_MIPS_SCN_DISP", /* name */
1273 FALSE, /* partial_inplace */
1274 0, /* src_mask */
1275 0xffffffff, /* dst_mask */
1276 FALSE), /* pcrel_offset */
1278 HOWTO (R_MIPS_REL16, /* type */
1279 0, /* rightshift */
1280 1, /* size (0 = byte, 1 = short, 2 = long) */
1281 16, /* bitsize */
1282 FALSE, /* pc_relative */
1283 0, /* bitpos */
1284 complain_overflow_signed, /* complain_on_overflow */
1285 _bfd_mips_elf_generic_reloc, /* special_function */
1286 "R_MIPS_REL16", /* name */
1287 FALSE, /* partial_inplace */
1288 0, /* src_mask */
1289 0xffff, /* dst_mask */
1290 FALSE), /* pcrel_offset */
1292 /* These two are obsolete. */
1293 EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
1294 EMPTY_HOWTO (R_MIPS_PJUMP),
1296 /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
1297 It must be used for multigot GOT's (and only there). */
1298 HOWTO (R_MIPS_RELGOT, /* type */
1299 0, /* rightshift */
1300 2, /* size (0 = byte, 1 = short, 2 = long) */
1301 32, /* bitsize */
1302 FALSE, /* pc_relative */
1303 0, /* bitpos */
1304 complain_overflow_dont, /* complain_on_overflow */
1305 _bfd_mips_elf_generic_reloc, /* special_function */
1306 "R_MIPS_RELGOT", /* name */
1307 FALSE, /* partial_inplace */
1308 0, /* src_mask */
1309 0xffffffff, /* dst_mask */
1310 FALSE), /* pcrel_offset */
1312 /* Protected jump conversion. This is an optimization hint. No
1313 relocation is required for correctness. */
1314 HOWTO (R_MIPS_JALR, /* type */
1315 0, /* rightshift */
1316 2, /* size (0 = byte, 1 = short, 2 = long) */
1317 32, /* bitsize */
1318 FALSE, /* pc_relative */
1319 0, /* bitpos */
1320 complain_overflow_dont, /* complain_on_overflow */
1321 _bfd_mips_elf_generic_reloc, /* special_function */
1322 "R_MIPS_JALR", /* name */
1323 FALSE, /* partial_inplace */
1324 0, /* src_mask */
1325 0x00000000, /* dst_mask */
1326 FALSE), /* pcrel_offset */
1328 /* TLS relocations. */
1329 EMPTY_HOWTO (R_MIPS_TLS_DTPMOD32),
1330 EMPTY_HOWTO (R_MIPS_TLS_DTPREL32),
1331 EMPTY_HOWTO (R_MIPS_TLS_DTPMOD64),
1333 HOWTO (R_MIPS_TLS_DTPREL64, /* type */
1334 0, /* rightshift */
1335 4, /* size (0 = byte, 1 = short, 2 = long) */
1336 64, /* bitsize */
1337 FALSE, /* pc_relative */
1338 0, /* bitpos */
1339 complain_overflow_dont, /* complain_on_overflow */
1340 _bfd_mips_elf_generic_reloc, /* special_function */
1341 "R_MIPS_TLS_DTPREL64", /* name */
1342 TRUE, /* partial_inplace */
1343 MINUS_ONE, /* src_mask */
1344 MINUS_ONE, /* dst_mask */
1345 FALSE), /* pcrel_offset */
1347 /* TLS general dynamic variable reference. */
1348 HOWTO (R_MIPS_TLS_GD, /* type */
1349 0, /* rightshift */
1350 2, /* size (0 = byte, 1 = short, 2 = long) */
1351 16, /* bitsize */
1352 FALSE, /* pc_relative */
1353 0, /* bitpos */
1354 complain_overflow_signed, /* complain_on_overflow */
1355 _bfd_mips_elf_generic_reloc, /* special_function */
1356 "R_MIPS_TLS_GD", /* name */
1357 TRUE, /* partial_inplace */
1358 0x0000ffff, /* src_mask */
1359 0x0000ffff, /* dst_mask */
1360 FALSE), /* pcrel_offset */
1362 /* TLS local dynamic variable reference. */
1363 HOWTO (R_MIPS_TLS_LDM, /* type */
1364 0, /* rightshift */
1365 2, /* size (0 = byte, 1 = short, 2 = long) */
1366 16, /* bitsize */
1367 FALSE, /* pc_relative */
1368 0, /* bitpos */
1369 complain_overflow_signed, /* complain_on_overflow */
1370 _bfd_mips_elf_generic_reloc, /* special_function */
1371 "R_MIPS_TLS_LDM", /* name */
1372 TRUE, /* partial_inplace */
1373 0x0000ffff, /* src_mask */
1374 0x0000ffff, /* dst_mask */
1375 FALSE), /* pcrel_offset */
1377 /* TLS local dynamic offset. */
1378 HOWTO (R_MIPS_TLS_DTPREL_HI16, /* type */
1379 0, /* rightshift */
1380 2, /* size (0 = byte, 1 = short, 2 = long) */
1381 16, /* bitsize */
1382 FALSE, /* pc_relative */
1383 0, /* bitpos */
1384 complain_overflow_signed, /* complain_on_overflow */
1385 _bfd_mips_elf_generic_reloc, /* special_function */
1386 "R_MIPS_TLS_DTPREL_HI16", /* name */
1387 TRUE, /* partial_inplace */
1388 0x0000ffff, /* src_mask */
1389 0x0000ffff, /* dst_mask */
1390 FALSE), /* pcrel_offset */
1392 /* TLS local dynamic offset. */
1393 HOWTO (R_MIPS_TLS_DTPREL_LO16, /* type */
1394 0, /* rightshift */
1395 2, /* size (0 = byte, 1 = short, 2 = long) */
1396 16, /* bitsize */
1397 FALSE, /* pc_relative */
1398 0, /* bitpos */
1399 complain_overflow_signed, /* complain_on_overflow */
1400 _bfd_mips_elf_generic_reloc, /* special_function */
1401 "R_MIPS_TLS_DTPREL_LO16", /* name */
1402 TRUE, /* partial_inplace */
1403 0x0000ffff, /* src_mask */
1404 0x0000ffff, /* dst_mask */
1405 FALSE), /* pcrel_offset */
1407 /* TLS thread pointer offset. */
1408 HOWTO (R_MIPS_TLS_GOTTPREL, /* type */
1409 0, /* rightshift */
1410 2, /* size (0 = byte, 1 = short, 2 = long) */
1411 16, /* bitsize */
1412 FALSE, /* pc_relative */
1413 0, /* bitpos */
1414 complain_overflow_signed, /* complain_on_overflow */
1415 _bfd_mips_elf_generic_reloc, /* special_function */
1416 "R_MIPS_TLS_GOTTPREL", /* name */
1417 TRUE, /* partial_inplace */
1418 0x0000ffff, /* src_mask */
1419 0x0000ffff, /* dst_mask */
1420 FALSE), /* pcrel_offset */
1422 EMPTY_HOWTO (R_MIPS_TLS_TPREL32),
1423 EMPTY_HOWTO (R_MIPS_TLS_TPREL64),
1425 /* TLS thread pointer offset. */
1426 HOWTO (R_MIPS_TLS_TPREL_HI16, /* type */
1427 0, /* rightshift */
1428 2, /* size (0 = byte, 1 = short, 2 = long) */
1429 16, /* bitsize */
1430 FALSE, /* pc_relative */
1431 0, /* bitpos */
1432 complain_overflow_signed, /* complain_on_overflow */
1433 _bfd_mips_elf_generic_reloc, /* special_function */
1434 "R_MIPS_TLS_TPREL_HI16", /* name */
1435 TRUE, /* partial_inplace */
1436 0x0000ffff, /* src_mask */
1437 0x0000ffff, /* dst_mask */
1438 FALSE), /* pcrel_offset */
1440 /* TLS thread pointer offset. */
1441 HOWTO (R_MIPS_TLS_TPREL_LO16, /* type */
1442 0, /* rightshift */
1443 2, /* size (0 = byte, 1 = short, 2 = long) */
1444 16, /* bitsize */
1445 FALSE, /* pc_relative */
1446 0, /* bitpos */
1447 complain_overflow_signed, /* complain_on_overflow */
1448 _bfd_mips_elf_generic_reloc, /* special_function */
1449 "R_MIPS_TLS_TPREL_LO16", /* name */
1450 TRUE, /* partial_inplace */
1451 0x0000ffff, /* src_mask */
1452 0x0000ffff, /* dst_mask */
1453 FALSE), /* pcrel_offset */
1455 /* 32 bit relocation with no addend. */
1456 HOWTO (R_MIPS_GLOB_DAT, /* type */
1457 0, /* rightshift */
1458 2, /* size (0 = byte, 1 = short, 2 = long) */
1459 32, /* bitsize */
1460 FALSE, /* pc_relative */
1461 0, /* bitpos */
1462 complain_overflow_dont, /* complain_on_overflow */
1463 _bfd_mips_elf_generic_reloc, /* special_function */
1464 "R_MIPS_GLOB_DAT", /* name */
1465 FALSE, /* partial_inplace */
1466 0x0, /* src_mask */
1467 0xffffffff, /* dst_mask */
1468 FALSE), /* pcrel_offset */
1471 static reloc_howto_type mips16_elf64_howto_table_rel[] =
1473 /* The reloc used for the mips16 jump instruction. */
1474 HOWTO (R_MIPS16_26, /* type */
1475 2, /* rightshift */
1476 2, /* size (0 = byte, 1 = short, 2 = long) */
1477 26, /* bitsize */
1478 FALSE, /* pc_relative */
1479 0, /* bitpos */
1480 complain_overflow_dont, /* complain_on_overflow */
1481 /* This needs complex overflow
1482 detection, because the upper four
1483 bits must match the PC. */
1484 _bfd_mips_elf_generic_reloc, /* special_function */
1485 "R_MIPS16_26", /* name */
1486 TRUE, /* partial_inplace */
1487 0x3ffffff, /* src_mask */
1488 0x3ffffff, /* dst_mask */
1489 FALSE), /* pcrel_offset */
1491 /* The reloc used for the mips16 gprel instruction. */
1492 HOWTO (R_MIPS16_GPREL, /* type */
1493 0, /* rightshift */
1494 2, /* size (0 = byte, 1 = short, 2 = long) */
1495 16, /* bitsize */
1496 FALSE, /* pc_relative */
1497 0, /* bitpos */
1498 complain_overflow_signed, /* complain_on_overflow */
1499 mips16_gprel_reloc, /* special_function */
1500 "R_MIPS16_GPREL", /* name */
1501 TRUE, /* partial_inplace */
1502 0x0000ffff, /* src_mask */
1503 0x0000ffff, /* dst_mask */
1504 FALSE), /* pcrel_offset */
1506 /* A MIPS16 reference to the global offset table. */
1507 HOWTO (R_MIPS16_GOT16, /* type */
1508 0, /* rightshift */
1509 2, /* size (0 = byte, 1 = short, 2 = long) */
1510 16, /* bitsize */
1511 FALSE, /* pc_relative */
1512 0, /* bitpos */
1513 complain_overflow_dont, /* complain_on_overflow */
1514 _bfd_mips_elf_got16_reloc, /* special_function */
1515 "R_MIPS16_GOT16", /* name */
1516 TRUE, /* partial_inplace */
1517 0x0000ffff, /* src_mask */
1518 0x0000ffff, /* dst_mask */
1519 FALSE), /* pcrel_offset */
1521 /* A MIPS16 call through the global offset table. */
1522 HOWTO (R_MIPS16_CALL16, /* type */
1523 0, /* rightshift */
1524 2, /* size (0 = byte, 1 = short, 2 = long) */
1525 16, /* bitsize */
1526 FALSE, /* pc_relative */
1527 0, /* bitpos */
1528 complain_overflow_dont, /* complain_on_overflow */
1529 _bfd_mips_elf_generic_reloc, /* special_function */
1530 "R_MIPS16_CALL16", /* name */
1531 TRUE, /* partial_inplace */
1532 0x0000ffff, /* src_mask */
1533 0x0000ffff, /* dst_mask */
1534 FALSE), /* pcrel_offset */
1536 /* MIPS16 high 16 bits of symbol value. */
1537 HOWTO (R_MIPS16_HI16, /* type */
1538 16, /* rightshift */
1539 2, /* size (0 = byte, 1 = short, 2 = long) */
1540 16, /* bitsize */
1541 FALSE, /* pc_relative */
1542 0, /* bitpos */
1543 complain_overflow_dont, /* complain_on_overflow */
1544 _bfd_mips_elf_hi16_reloc, /* special_function */
1545 "R_MIPS16_HI16", /* name */
1546 TRUE, /* partial_inplace */
1547 0x0000ffff, /* src_mask */
1548 0x0000ffff, /* dst_mask */
1549 FALSE), /* pcrel_offset */
1551 /* MIPS16 low 16 bits of symbol value. */
1552 HOWTO (R_MIPS16_LO16, /* type */
1553 0, /* rightshift */
1554 2, /* size (0 = byte, 1 = short, 2 = long) */
1555 16, /* bitsize */
1556 FALSE, /* pc_relative */
1557 0, /* bitpos */
1558 complain_overflow_dont, /* complain_on_overflow */
1559 _bfd_mips_elf_lo16_reloc, /* special_function */
1560 "R_MIPS16_LO16", /* name */
1561 TRUE, /* partial_inplace */
1562 0x0000ffff, /* src_mask */
1563 0x0000ffff, /* dst_mask */
1564 FALSE), /* pcrel_offset */
1567 static reloc_howto_type mips16_elf64_howto_table_rela[] =
1569 /* The reloc used for the mips16 jump instruction. */
1570 HOWTO (R_MIPS16_26, /* type */
1571 2, /* rightshift */
1572 2, /* size (0 = byte, 1 = short, 2 = long) */
1573 26, /* bitsize */
1574 FALSE, /* pc_relative */
1575 0, /* bitpos */
1576 complain_overflow_dont, /* complain_on_overflow */
1577 /* This needs complex overflow
1578 detection, because the upper four
1579 bits must match the PC. */
1580 _bfd_mips_elf_generic_reloc, /* special_function */
1581 "R_MIPS16_26", /* name */
1582 FALSE, /* partial_inplace */
1583 0x3ffffff, /* src_mask */
1584 0x3ffffff, /* dst_mask */
1585 FALSE), /* pcrel_offset */
1587 /* The reloc used for the mips16 gprel instruction. */
1588 HOWTO (R_MIPS16_GPREL, /* type */
1589 0, /* rightshift */
1590 2, /* size (0 = byte, 1 = short, 2 = long) */
1591 16, /* bitsize */
1592 FALSE, /* pc_relative */
1593 0, /* bitpos */
1594 complain_overflow_signed, /* complain_on_overflow */
1595 mips16_gprel_reloc, /* special_function */
1596 "R_MIPS16_GPREL", /* name */
1597 FALSE, /* partial_inplace */
1598 0x0000ffff, /* src_mask */
1599 0x0000ffff, /* dst_mask */
1600 FALSE), /* pcrel_offset */
1602 /* A MIPS16 reference to the global offset table. */
1603 HOWTO (R_MIPS16_GOT16, /* type */
1604 0, /* rightshift */
1605 2, /* size (0 = byte, 1 = short, 2 = long) */
1606 16, /* bitsize */
1607 FALSE, /* pc_relative */
1608 0, /* bitpos */
1609 complain_overflow_dont, /* complain_on_overflow */
1610 _bfd_mips_elf_got16_reloc, /* special_function */
1611 "R_MIPS16_GOT16", /* name */
1612 FALSE, /* partial_inplace */
1613 0x0000ffff, /* src_mask */
1614 0x0000ffff, /* dst_mask */
1615 FALSE), /* pcrel_offset */
1617 /* A MIPS16 call through the global offset table. */
1618 HOWTO (R_MIPS16_CALL16, /* type */
1619 0, /* rightshift */
1620 2, /* size (0 = byte, 1 = short, 2 = long) */
1621 16, /* bitsize */
1622 FALSE, /* pc_relative */
1623 0, /* bitpos */
1624 complain_overflow_dont, /* complain_on_overflow */
1625 _bfd_mips_elf_generic_reloc, /* special_function */
1626 "R_MIPS16_CALL16", /* name */
1627 FALSE, /* partial_inplace */
1628 0x0000ffff, /* src_mask */
1629 0x0000ffff, /* dst_mask */
1630 FALSE), /* pcrel_offset */
1632 /* MIPS16 high 16 bits of symbol value. */
1633 HOWTO (R_MIPS16_HI16, /* type */
1634 16, /* rightshift */
1635 2, /* size (0 = byte, 1 = short, 2 = long) */
1636 16, /* bitsize */
1637 FALSE, /* pc_relative */
1638 0, /* bitpos */
1639 complain_overflow_dont, /* complain_on_overflow */
1640 _bfd_mips_elf_hi16_reloc, /* special_function */
1641 "R_MIPS16_HI16", /* name */
1642 FALSE, /* partial_inplace */
1643 0x0000ffff, /* src_mask */
1644 0x0000ffff, /* dst_mask */
1645 FALSE), /* pcrel_offset */
1647 /* MIPS16 low 16 bits of symbol value. */
1648 HOWTO (R_MIPS16_LO16, /* type */
1649 0, /* rightshift */
1650 2, /* size (0 = byte, 1 = short, 2 = long) */
1651 16, /* bitsize */
1652 FALSE, /* pc_relative */
1653 0, /* bitpos */
1654 complain_overflow_dont, /* complain_on_overflow */
1655 _bfd_mips_elf_lo16_reloc, /* special_function */
1656 "R_MIPS16_LO16", /* name */
1657 FALSE, /* partial_inplace */
1658 0x0000ffff, /* src_mask */
1659 0x0000ffff, /* dst_mask */
1660 FALSE), /* pcrel_offset */
1663 /* GNU extension to record C++ vtable hierarchy */
1664 static reloc_howto_type elf_mips_gnu_vtinherit_howto =
1665 HOWTO (R_MIPS_GNU_VTINHERIT, /* type */
1666 0, /* rightshift */
1667 2, /* size (0 = byte, 1 = short, 2 = long) */
1668 0, /* bitsize */
1669 FALSE, /* pc_relative */
1670 0, /* bitpos */
1671 complain_overflow_dont, /* complain_on_overflow */
1672 NULL, /* special_function */
1673 "R_MIPS_GNU_VTINHERIT", /* name */
1674 FALSE, /* partial_inplace */
1675 0, /* src_mask */
1676 0, /* dst_mask */
1677 FALSE); /* pcrel_offset */
1679 /* GNU extension to record C++ vtable member usage */
1680 static reloc_howto_type elf_mips_gnu_vtentry_howto =
1681 HOWTO (R_MIPS_GNU_VTENTRY, /* type */
1682 0, /* rightshift */
1683 2, /* size (0 = byte, 1 = short, 2 = long) */
1684 0, /* bitsize */
1685 FALSE, /* pc_relative */
1686 0, /* bitpos */
1687 complain_overflow_dont, /* complain_on_overflow */
1688 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
1689 "R_MIPS_GNU_VTENTRY", /* name */
1690 FALSE, /* partial_inplace */
1691 0, /* src_mask */
1692 0, /* dst_mask */
1693 FALSE); /* pcrel_offset */
1695 /* 16 bit offset for pc-relative branches. */
1696 static reloc_howto_type elf_mips_gnu_rel16_s2 =
1697 HOWTO (R_MIPS_GNU_REL16_S2, /* type */
1698 2, /* rightshift */
1699 2, /* size (0 = byte, 1 = short, 2 = long) */
1700 16, /* bitsize */
1701 TRUE, /* pc_relative */
1702 0, /* bitpos */
1703 complain_overflow_signed, /* complain_on_overflow */
1704 _bfd_mips_elf_generic_reloc, /* special_function */
1705 "R_MIPS_GNU_REL16_S2", /* name */
1706 TRUE, /* partial_inplace */
1707 0x0000ffff, /* src_mask */
1708 0x0000ffff, /* dst_mask */
1709 TRUE); /* pcrel_offset */
1711 /* 16 bit offset for pc-relative branches. */
1712 static reloc_howto_type elf_mips_gnu_rela16_s2 =
1713 HOWTO (R_MIPS_GNU_REL16_S2, /* type */
1714 2, /* rightshift */
1715 2, /* size (0 = byte, 1 = short, 2 = long) */
1716 16, /* bitsize */
1717 TRUE, /* pc_relative */
1718 0, /* bitpos */
1719 complain_overflow_signed, /* complain_on_overflow */
1720 _bfd_mips_elf_generic_reloc, /* special_function */
1721 "R_MIPS_GNU_REL16_S2", /* name */
1722 FALSE, /* partial_inplace */
1723 0, /* src_mask */
1724 0x0000ffff, /* dst_mask */
1725 TRUE); /* pcrel_offset */
1727 /* Originally a VxWorks extension, but now used for other systems too. */
1728 static reloc_howto_type elf_mips_copy_howto =
1729 HOWTO (R_MIPS_COPY, /* type */
1730 0, /* rightshift */
1731 0, /* this one is variable size */
1732 0, /* bitsize */
1733 FALSE, /* pc_relative */
1734 0, /* bitpos */
1735 complain_overflow_bitfield, /* complain_on_overflow */
1736 bfd_elf_generic_reloc, /* special_function */
1737 "R_MIPS_COPY", /* name */
1738 FALSE, /* partial_inplace */
1739 0x0, /* src_mask */
1740 0x0, /* dst_mask */
1741 FALSE); /* pcrel_offset */
1743 /* Originally a VxWorks extension, but now used for other systems too. */
1744 static reloc_howto_type elf_mips_jump_slot_howto =
1745 HOWTO (R_MIPS_JUMP_SLOT, /* type */
1746 0, /* rightshift */
1747 4, /* size (0 = byte, 1 = short, 2 = long) */
1748 64, /* bitsize */
1749 FALSE, /* pc_relative */
1750 0, /* bitpos */
1751 complain_overflow_bitfield, /* complain_on_overflow */
1752 bfd_elf_generic_reloc, /* special_function */
1753 "R_MIPS_JUMP_SLOT", /* name */
1754 FALSE, /* partial_inplace */
1755 0x0, /* src_mask */
1756 0x0, /* dst_mask */
1757 FALSE); /* pcrel_offset */
1759 /* Swap in a MIPS 64-bit Rel reloc. */
1761 static void
1762 mips_elf64_swap_reloc_in (bfd *abfd, const Elf64_Mips_External_Rel *src,
1763 Elf64_Mips_Internal_Rela *dst)
1765 dst->r_offset = H_GET_64 (abfd, src->r_offset);
1766 dst->r_sym = H_GET_32 (abfd, src->r_sym);
1767 dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1768 dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1769 dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1770 dst->r_type = H_GET_8 (abfd, src->r_type);
1771 dst->r_addend = 0;
1774 /* Swap in a MIPS 64-bit Rela reloc. */
1776 static void
1777 mips_elf64_swap_reloca_in (bfd *abfd, const Elf64_Mips_External_Rela *src,
1778 Elf64_Mips_Internal_Rela *dst)
1780 dst->r_offset = H_GET_64 (abfd, src->r_offset);
1781 dst->r_sym = H_GET_32 (abfd, src->r_sym);
1782 dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1783 dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1784 dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1785 dst->r_type = H_GET_8 (abfd, src->r_type);
1786 dst->r_addend = H_GET_S64 (abfd, src->r_addend);
1789 /* Swap out a MIPS 64-bit Rel reloc. */
1791 static void
1792 mips_elf64_swap_reloc_out (bfd *abfd, const Elf64_Mips_Internal_Rela *src,
1793 Elf64_Mips_External_Rel *dst)
1795 H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1796 H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1797 H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1798 H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1799 H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1800 H_PUT_8 (abfd, src->r_type, dst->r_type);
1803 /* Swap out a MIPS 64-bit Rela reloc. */
1805 static void
1806 mips_elf64_swap_reloca_out (bfd *abfd, const Elf64_Mips_Internal_Rela *src,
1807 Elf64_Mips_External_Rela *dst)
1809 H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1810 H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1811 H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1812 H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1813 H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1814 H_PUT_8 (abfd, src->r_type, dst->r_type);
1815 H_PUT_S64 (abfd, src->r_addend, dst->r_addend);
1818 /* Swap in a MIPS 64-bit Rel reloc. */
1820 static void
1821 mips_elf64_be_swap_reloc_in (bfd *abfd, const bfd_byte *src,
1822 Elf_Internal_Rela *dst)
1824 Elf64_Mips_Internal_Rela mirel;
1826 mips_elf64_swap_reloc_in (abfd,
1827 (const Elf64_Mips_External_Rel *) src,
1828 &mirel);
1830 dst[0].r_offset = mirel.r_offset;
1831 dst[0].r_info = ELF64_R_INFO (mirel.r_sym, mirel.r_type);
1832 dst[0].r_addend = 0;
1833 dst[1].r_offset = mirel.r_offset;
1834 dst[1].r_info = ELF64_R_INFO (mirel.r_ssym, mirel.r_type2);
1835 dst[1].r_addend = 0;
1836 dst[2].r_offset = mirel.r_offset;
1837 dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirel.r_type3);
1838 dst[2].r_addend = 0;
1841 /* Swap in a MIPS 64-bit Rela reloc. */
1843 static void
1844 mips_elf64_be_swap_reloca_in (bfd *abfd, const bfd_byte *src,
1845 Elf_Internal_Rela *dst)
1847 Elf64_Mips_Internal_Rela mirela;
1849 mips_elf64_swap_reloca_in (abfd,
1850 (const Elf64_Mips_External_Rela *) src,
1851 &mirela);
1853 dst[0].r_offset = mirela.r_offset;
1854 dst[0].r_info = ELF64_R_INFO (mirela.r_sym, mirela.r_type);
1855 dst[0].r_addend = mirela.r_addend;
1856 dst[1].r_offset = mirela.r_offset;
1857 dst[1].r_info = ELF64_R_INFO (mirela.r_ssym, mirela.r_type2);
1858 dst[1].r_addend = 0;
1859 dst[2].r_offset = mirela.r_offset;
1860 dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirela.r_type3);
1861 dst[2].r_addend = 0;
1864 /* Swap out a MIPS 64-bit Rel reloc. */
1866 static void
1867 mips_elf64_be_swap_reloc_out (bfd *abfd, const Elf_Internal_Rela *src,
1868 bfd_byte *dst)
1870 Elf64_Mips_Internal_Rela mirel;
1872 mirel.r_offset = src[0].r_offset;
1873 BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1875 mirel.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1876 mirel.r_sym = ELF64_R_SYM (src[0].r_info);
1877 mirel.r_type2 = ELF64_MIPS_R_TYPE (src[1].r_info);
1878 mirel.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1879 mirel.r_type3 = ELF64_MIPS_R_TYPE (src[2].r_info);
1881 mips_elf64_swap_reloc_out (abfd, &mirel,
1882 (Elf64_Mips_External_Rel *) dst);
1885 /* Swap out a MIPS 64-bit Rela reloc. */
1887 static void
1888 mips_elf64_be_swap_reloca_out (bfd *abfd, const Elf_Internal_Rela *src,
1889 bfd_byte *dst)
1891 Elf64_Mips_Internal_Rela mirela;
1893 mirela.r_offset = src[0].r_offset;
1894 BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1895 BFD_ASSERT(src[0].r_offset == src[2].r_offset);
1897 mirela.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1898 mirela.r_sym = ELF64_R_SYM (src[0].r_info);
1899 mirela.r_addend = src[0].r_addend;
1900 BFD_ASSERT(src[1].r_addend == 0);
1901 BFD_ASSERT(src[2].r_addend == 0);
1903 mirela.r_type2 = ELF64_MIPS_R_TYPE (src[1].r_info);
1904 mirela.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1905 mirela.r_type3 = ELF64_MIPS_R_TYPE (src[2].r_info);
1907 mips_elf64_swap_reloca_out (abfd, &mirela,
1908 (Elf64_Mips_External_Rela *) dst);
1911 /* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a
1912 dangerous relocation. */
1914 static bfd_boolean
1915 mips_elf64_assign_gp (bfd *output_bfd, bfd_vma *pgp)
1917 unsigned int count;
1918 asymbol **sym;
1919 unsigned int i;
1921 /* If we've already figured out what GP will be, just return it. */
1922 *pgp = _bfd_get_gp_value (output_bfd);
1923 if (*pgp)
1924 return TRUE;
1926 count = bfd_get_symcount (output_bfd);
1927 sym = bfd_get_outsymbols (output_bfd);
1929 /* The linker script will have created a symbol named `_gp' with the
1930 appropriate value. */
1931 if (sym == NULL)
1932 i = count;
1933 else
1935 for (i = 0; i < count; i++, sym++)
1937 register const char *name;
1939 name = bfd_asymbol_name (*sym);
1940 if (*name == '_' && strcmp (name, "_gp") == 0)
1942 *pgp = bfd_asymbol_value (*sym);
1943 _bfd_set_gp_value (output_bfd, *pgp);
1944 break;
1949 if (i >= count)
1951 /* Only get the error once. */
1952 *pgp = 4;
1953 _bfd_set_gp_value (output_bfd, *pgp);
1954 return FALSE;
1957 return TRUE;
1960 /* We have to figure out the gp value, so that we can adjust the
1961 symbol value correctly. We look up the symbol _gp in the output
1962 BFD. If we can't find it, we're stuck. We cache it in the ELF
1963 target data. We don't need to adjust the symbol value for an
1964 external symbol if we are producing relocatable output. */
1966 static bfd_reloc_status_type
1967 mips_elf64_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable,
1968 char **error_message, bfd_vma *pgp)
1970 if (bfd_is_und_section (symbol->section)
1971 && ! relocatable)
1973 *pgp = 0;
1974 return bfd_reloc_undefined;
1977 *pgp = _bfd_get_gp_value (output_bfd);
1978 if (*pgp == 0
1979 && (! relocatable
1980 || (symbol->flags & BSF_SECTION_SYM) != 0))
1982 if (relocatable)
1984 /* Make up a value. */
1985 *pgp = symbol->section->output_section->vma /*+ 0x4000*/;
1986 _bfd_set_gp_value (output_bfd, *pgp);
1988 else if (!mips_elf64_assign_gp (output_bfd, pgp))
1990 *error_message =
1991 (char *) _("GP relative relocation when _gp not defined");
1992 return bfd_reloc_dangerous;
1996 return bfd_reloc_ok;
1999 /* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must
2000 become the offset from the gp register. */
2002 static bfd_reloc_status_type
2003 mips_elf64_gprel16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2004 void *data, asection *input_section, bfd *output_bfd,
2005 char **error_message)
2007 bfd_boolean relocatable;
2008 bfd_reloc_status_type ret;
2009 bfd_vma gp;
2011 /* If we're relocating, and this is an external symbol, we don't want
2012 to change anything. */
2013 if (output_bfd != NULL
2014 && (symbol->flags & BSF_SECTION_SYM) == 0
2015 && (symbol->flags & BSF_LOCAL) != 0)
2017 reloc_entry->address += input_section->output_offset;
2018 return bfd_reloc_ok;
2021 if (output_bfd != NULL)
2022 relocatable = TRUE;
2023 else
2025 relocatable = FALSE;
2026 output_bfd = symbol->section->output_section->owner;
2029 ret = mips_elf64_final_gp (output_bfd, symbol, relocatable, error_message,
2030 &gp);
2031 if (ret != bfd_reloc_ok)
2032 return ret;
2034 return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
2035 input_section, relocatable,
2036 data, gp);
2039 /* Do a R_MIPS_LITERAL relocation. */
2041 static bfd_reloc_status_type
2042 mips_elf64_literal_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2043 void *data, asection *input_section, bfd *output_bfd,
2044 char **error_message)
2046 bfd_boolean relocatable;
2047 bfd_reloc_status_type ret;
2048 bfd_vma gp;
2050 /* R_MIPS_LITERAL relocations are defined for local symbols only. */
2051 if (output_bfd != NULL
2052 && (symbol->flags & BSF_SECTION_SYM) == 0
2053 && (symbol->flags & BSF_LOCAL) != 0)
2055 *error_message = (char *)
2056 _("literal relocation occurs for an external symbol");
2057 return bfd_reloc_outofrange;
2060 /* FIXME: The entries in the .lit8 and .lit4 sections should be merged. */
2061 if (output_bfd != NULL)
2062 relocatable = TRUE;
2063 else
2065 relocatable = FALSE;
2066 output_bfd = symbol->section->output_section->owner;
2069 ret = mips_elf64_final_gp (output_bfd, symbol, relocatable, error_message,
2070 &gp);
2071 if (ret != bfd_reloc_ok)
2072 return ret;
2074 return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
2075 input_section, relocatable,
2076 data, gp);
2079 /* Do a R_MIPS_GPREL32 relocation. This is a 32 bit value which must
2080 become the offset from the gp register. */
2082 static bfd_reloc_status_type
2083 mips_elf64_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2084 void *data, asection *input_section, bfd *output_bfd,
2085 char **error_message)
2087 bfd_boolean relocatable;
2088 bfd_reloc_status_type ret;
2089 bfd_vma gp;
2090 bfd_vma relocation;
2091 bfd_vma val;
2093 /* R_MIPS_GPREL32 relocations are defined for local symbols only. */
2094 if (output_bfd != NULL
2095 && (symbol->flags & BSF_SECTION_SYM) == 0
2096 && (symbol->flags & BSF_LOCAL) != 0)
2098 *error_message = (char *)
2099 _("32bits gp relative relocation occurs for an external symbol");
2100 return bfd_reloc_outofrange;
2103 if (output_bfd != NULL)
2104 relocatable = TRUE;
2105 else
2107 relocatable = FALSE;
2108 output_bfd = symbol->section->output_section->owner;
2111 ret = mips_elf64_final_gp (output_bfd, symbol, relocatable,
2112 error_message, &gp);
2113 if (ret != bfd_reloc_ok)
2114 return ret;
2116 if (bfd_is_com_section (symbol->section))
2117 relocation = 0;
2118 else
2119 relocation = symbol->value;
2121 relocation += symbol->section->output_section->vma;
2122 relocation += symbol->section->output_offset;
2124 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
2125 return bfd_reloc_outofrange;
2127 /* Set val to the offset into the section or symbol. */
2128 val = reloc_entry->addend;
2130 if (reloc_entry->howto->partial_inplace)
2131 val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
2133 /* Adjust val for the final section location and GP value. If we
2134 are producing relocatable output, we don't want to do this for
2135 an external symbol. */
2136 if (! relocatable
2137 || (symbol->flags & BSF_SECTION_SYM) != 0)
2138 val += relocation - gp;
2140 if (reloc_entry->howto->partial_inplace)
2141 bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
2142 else
2143 reloc_entry->addend = val;
2145 if (relocatable)
2146 reloc_entry->address += input_section->output_offset;
2148 return bfd_reloc_ok;
2151 /* Do a R_MIPS_SHIFT6 relocation. The MSB of the shift is stored at bit 2,
2152 the rest is at bits 6-10. The bitpos already got right by the howto. */
2154 static bfd_reloc_status_type
2155 mips_elf64_shift6_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2156 void *data, asection *input_section, bfd *output_bfd,
2157 char **error_message)
2159 if (reloc_entry->howto->partial_inplace)
2161 reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
2162 | (reloc_entry->addend & 0x00000800) >> 9);
2165 return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
2166 input_section, output_bfd,
2167 error_message);
2170 /* Handle a mips16 GP relative reloc. */
2172 static bfd_reloc_status_type
2173 mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2174 void *data, asection *input_section, bfd *output_bfd,
2175 char **error_message)
2177 bfd_boolean relocatable;
2178 bfd_reloc_status_type ret;
2179 bfd_byte *location;
2180 bfd_vma gp;
2182 /* If we're relocating, and this is an external symbol, we don't want
2183 to change anything. */
2184 if (output_bfd != NULL
2185 && (symbol->flags & BSF_SECTION_SYM) == 0
2186 && (symbol->flags & BSF_LOCAL) != 0)
2188 reloc_entry->address += input_section->output_offset;
2189 return bfd_reloc_ok;
2192 if (output_bfd != NULL)
2193 relocatable = TRUE;
2194 else
2196 relocatable = FALSE;
2197 output_bfd = symbol->section->output_section->owner;
2200 ret = mips_elf64_final_gp (output_bfd, symbol, relocatable, error_message,
2201 &gp);
2202 if (ret != bfd_reloc_ok)
2203 return ret;
2205 location = (bfd_byte *) data + reloc_entry->address;
2206 _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
2207 location);
2208 ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
2209 input_section, relocatable,
2210 data, gp);
2211 _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, !relocatable,
2212 location);
2214 return ret;
2217 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
2219 struct elf_reloc_map {
2220 bfd_reloc_code_real_type bfd_val;
2221 enum elf_mips_reloc_type elf_val;
2224 static const struct elf_reloc_map mips_reloc_map[] =
2226 { BFD_RELOC_NONE, R_MIPS_NONE },
2227 { BFD_RELOC_16, R_MIPS_16 },
2228 { BFD_RELOC_32, R_MIPS_32 },
2229 /* There is no BFD reloc for R_MIPS_REL32. */
2230 { BFD_RELOC_64, R_MIPS_64 },
2231 { BFD_RELOC_CTOR, R_MIPS_64 },
2232 { BFD_RELOC_16_PCREL_S2, R_MIPS_PC16 },
2233 { BFD_RELOC_HI16_S, R_MIPS_HI16 },
2234 { BFD_RELOC_LO16, R_MIPS_LO16 },
2235 { BFD_RELOC_GPREL16, R_MIPS_GPREL16 },
2236 { BFD_RELOC_GPREL32, R_MIPS_GPREL32 },
2237 { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
2238 { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
2239 { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
2240 { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
2241 { BFD_RELOC_MIPS_SHIFT5, R_MIPS_SHIFT5 },
2242 { BFD_RELOC_MIPS_SHIFT6, R_MIPS_SHIFT6 },
2243 { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP },
2244 { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
2245 { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
2246 { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
2247 { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
2248 { BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
2249 { BFD_RELOC_MIPS_INSERT_A, R_MIPS_INSERT_A },
2250 { BFD_RELOC_MIPS_INSERT_B, R_MIPS_INSERT_B },
2251 { BFD_RELOC_MIPS_DELETE, R_MIPS_DELETE },
2252 { BFD_RELOC_MIPS_HIGHEST, R_MIPS_HIGHEST },
2253 { BFD_RELOC_MIPS_HIGHER, R_MIPS_HIGHER },
2254 { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
2255 { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
2256 { BFD_RELOC_MIPS_SCN_DISP, R_MIPS_SCN_DISP },
2257 { BFD_RELOC_MIPS_REL16, R_MIPS_REL16 },
2258 /* Use of R_MIPS_ADD_IMMEDIATE and R_MIPS_PJUMP is deprecated. */
2259 { BFD_RELOC_MIPS_RELGOT, R_MIPS_RELGOT },
2260 { BFD_RELOC_MIPS_JALR, R_MIPS_JALR },
2261 { BFD_RELOC_MIPS_TLS_DTPMOD32, R_MIPS_TLS_DTPMOD32 },
2262 { BFD_RELOC_MIPS_TLS_DTPREL32, R_MIPS_TLS_DTPREL32 },
2263 { BFD_RELOC_MIPS_TLS_DTPMOD64, R_MIPS_TLS_DTPMOD64 },
2264 { BFD_RELOC_MIPS_TLS_DTPREL64, R_MIPS_TLS_DTPREL64 },
2265 { BFD_RELOC_MIPS_TLS_GD, R_MIPS_TLS_GD },
2266 { BFD_RELOC_MIPS_TLS_LDM, R_MIPS_TLS_LDM },
2267 { BFD_RELOC_MIPS_TLS_DTPREL_HI16, R_MIPS_TLS_DTPREL_HI16 },
2268 { BFD_RELOC_MIPS_TLS_DTPREL_LO16, R_MIPS_TLS_DTPREL_LO16 },
2269 { BFD_RELOC_MIPS_TLS_GOTTPREL, R_MIPS_TLS_GOTTPREL },
2270 { BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 },
2271 { BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 },
2272 { BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 },
2273 { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }
2276 static const struct elf_reloc_map mips16_reloc_map[] =
2278 { BFD_RELOC_MIPS16_JMP, R_MIPS16_26 - R_MIPS16_min },
2279 { BFD_RELOC_MIPS16_GPREL, R_MIPS16_GPREL - R_MIPS16_min },
2280 { BFD_RELOC_MIPS16_GOT16, R_MIPS16_GOT16 - R_MIPS16_min },
2281 { BFD_RELOC_MIPS16_CALL16, R_MIPS16_CALL16 - R_MIPS16_min },
2282 { BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min },
2283 { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min },
2286 /* Given a BFD reloc type, return a howto structure. */
2288 static reloc_howto_type *
2289 bfd_elf64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
2290 bfd_reloc_code_real_type code)
2292 unsigned int i;
2293 /* FIXME: We default to RELA here instead of choosing the right
2294 relocation variant. */
2295 reloc_howto_type *howto_table = mips_elf64_howto_table_rela;
2296 reloc_howto_type *howto16_table = mips16_elf64_howto_table_rela;
2298 for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map);
2299 i++)
2301 if (mips_reloc_map[i].bfd_val == code)
2302 return &howto_table[(int) mips_reloc_map[i].elf_val];
2305 for (i = 0; i < sizeof (mips16_reloc_map) / sizeof (struct elf_reloc_map);
2306 i++)
2308 if (mips16_reloc_map[i].bfd_val == code)
2309 return &howto16_table[(int) mips16_reloc_map[i].elf_val];
2312 switch (code)
2314 case BFD_RELOC_VTABLE_INHERIT:
2315 return &elf_mips_gnu_vtinherit_howto;
2316 case BFD_RELOC_VTABLE_ENTRY:
2317 return &elf_mips_gnu_vtentry_howto;
2318 case BFD_RELOC_MIPS_COPY:
2319 return &elf_mips_copy_howto;
2320 case BFD_RELOC_MIPS_JUMP_SLOT:
2321 return &elf_mips_jump_slot_howto;
2322 default:
2323 bfd_set_error (bfd_error_bad_value);
2324 return NULL;
2328 static reloc_howto_type *
2329 bfd_elf64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
2330 const char *r_name)
2332 unsigned int i;
2334 for (i = 0;
2335 i < (sizeof (mips_elf64_howto_table_rela)
2336 / sizeof (mips_elf64_howto_table_rela[0])); i++)
2337 if (mips_elf64_howto_table_rela[i].name != NULL
2338 && strcasecmp (mips_elf64_howto_table_rela[i].name, r_name) == 0)
2339 return &mips_elf64_howto_table_rela[i];
2341 for (i = 0;
2342 i < (sizeof (mips16_elf64_howto_table_rela)
2343 / sizeof (mips16_elf64_howto_table_rela[0]));
2344 i++)
2345 if (mips16_elf64_howto_table_rela[i].name != NULL
2346 && strcasecmp (mips16_elf64_howto_table_rela[i].name, r_name) == 0)
2347 return &mips16_elf64_howto_table_rela[i];
2349 if (strcasecmp (elf_mips_gnu_vtinherit_howto.name, r_name) == 0)
2350 return &elf_mips_gnu_vtinherit_howto;
2351 if (strcasecmp (elf_mips_gnu_vtentry_howto.name, r_name) == 0)
2352 return &elf_mips_gnu_vtentry_howto;
2353 if (strcasecmp (elf_mips_gnu_rel16_s2.name, r_name) == 0)
2354 return &elf_mips_gnu_rel16_s2;
2355 if (strcasecmp (elf_mips_gnu_rela16_s2.name, r_name) == 0)
2356 return &elf_mips_gnu_rela16_s2;
2357 if (strcasecmp (elf_mips_copy_howto.name, r_name) == 0)
2358 return &elf_mips_copy_howto;
2359 if (strcasecmp (elf_mips_jump_slot_howto.name, r_name) == 0)
2360 return &elf_mips_jump_slot_howto;
2362 return NULL;
2365 /* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */
2367 static reloc_howto_type *
2368 mips_elf64_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p)
2370 switch (r_type)
2372 case R_MIPS_GNU_VTINHERIT:
2373 return &elf_mips_gnu_vtinherit_howto;
2374 case R_MIPS_GNU_VTENTRY:
2375 return &elf_mips_gnu_vtentry_howto;
2376 case R_MIPS_GNU_REL16_S2:
2377 if (rela_p)
2378 return &elf_mips_gnu_rela16_s2;
2379 else
2380 return &elf_mips_gnu_rel16_s2;
2381 case R_MIPS_COPY:
2382 return &elf_mips_copy_howto;
2383 case R_MIPS_JUMP_SLOT:
2384 return &elf_mips_jump_slot_howto;
2385 default:
2386 if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
2388 if (rela_p)
2389 return &mips16_elf64_howto_table_rela[r_type - R_MIPS16_min];
2390 else
2391 return &mips16_elf64_howto_table_rel[r_type - R_MIPS16_min];
2393 BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
2394 if (rela_p)
2395 return &mips_elf64_howto_table_rela[r_type];
2396 else
2397 return &mips_elf64_howto_table_rel[r_type];
2398 break;
2402 /* Prevent relocation handling by bfd for MIPS ELF64. */
2404 static void
2405 mips_elf64_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
2406 arelent *cache_ptr ATTRIBUTE_UNUSED,
2407 Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
2409 BFD_ASSERT (0);
2412 static void
2413 mips_elf64_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
2414 arelent *cache_ptr ATTRIBUTE_UNUSED,
2415 Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
2417 BFD_ASSERT (0);
2420 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
2421 to three relocs, we must tell the user to allocate more space. */
2423 static long
2424 mips_elf64_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
2426 return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
2429 static long
2430 mips_elf64_get_dynamic_reloc_upper_bound (bfd *abfd)
2432 return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 3;
2435 /* We must also copy more relocations than the corresponding functions
2436 in elf.c would, so the two following functions are slightly
2437 modified from elf.c, that multiply the external relocation count by
2438 3 to obtain the internal relocation count. */
2440 static long
2441 mips_elf64_canonicalize_reloc (bfd *abfd, sec_ptr section,
2442 arelent **relptr, asymbol **symbols)
2444 arelent *tblptr;
2445 unsigned int i;
2446 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
2448 if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
2449 return -1;
2451 tblptr = section->relocation;
2452 for (i = 0; i < section->reloc_count * 3; i++)
2453 *relptr++ = tblptr++;
2455 *relptr = NULL;
2457 return section->reloc_count * 3;
2460 static long
2461 mips_elf64_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage,
2462 asymbol **syms)
2464 bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
2465 asection *s;
2466 long ret;
2468 if (elf_dynsymtab (abfd) == 0)
2470 bfd_set_error (bfd_error_invalid_operation);
2471 return -1;
2474 slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
2475 ret = 0;
2476 for (s = abfd->sections; s != NULL; s = s->next)
2478 if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
2479 && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
2480 || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
2482 arelent *p;
2483 long count, i;
2485 if (! (*slurp_relocs) (abfd, s, syms, TRUE))
2486 return -1;
2487 count = s->size / elf_section_data (s)->this_hdr.sh_entsize * 3;
2488 p = s->relocation;
2489 for (i = 0; i < count; i++)
2490 *storage++ = p++;
2491 ret += count;
2495 *storage = NULL;
2497 return ret;
2500 /* Read the relocations from one reloc section. This is mostly copied
2501 from elfcode.h, except for the changes to expand one external
2502 relocation to 3 internal ones. We must unfortunately set
2503 reloc_count to the number of external relocations, because a lot of
2504 generic code seems to depend on this. */
2506 static bfd_boolean
2507 mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
2508 Elf_Internal_Shdr *rel_hdr,
2509 bfd_size_type reloc_count,
2510 arelent *relents, asymbol **symbols,
2511 bfd_boolean dynamic)
2513 void *allocated;
2514 bfd_byte *native_relocs;
2515 arelent *relent;
2516 bfd_vma i;
2517 int entsize;
2518 bfd_boolean rela_p;
2520 allocated = bfd_malloc (rel_hdr->sh_size);
2521 if (allocated == NULL)
2522 return FALSE;
2524 if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
2525 || (bfd_bread (allocated, rel_hdr->sh_size, abfd)
2526 != rel_hdr->sh_size))
2527 goto error_return;
2529 native_relocs = allocated;
2531 entsize = rel_hdr->sh_entsize;
2532 BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
2533 || entsize == sizeof (Elf64_Mips_External_Rela));
2535 if (entsize == sizeof (Elf64_Mips_External_Rel))
2536 rela_p = FALSE;
2537 else
2538 rela_p = TRUE;
2540 for (i = 0, relent = relents;
2541 i < reloc_count;
2542 i++, native_relocs += entsize)
2544 Elf64_Mips_Internal_Rela rela;
2545 bfd_boolean used_sym, used_ssym;
2546 int ir;
2548 if (entsize == sizeof (Elf64_Mips_External_Rela))
2549 mips_elf64_swap_reloca_in (abfd,
2550 (Elf64_Mips_External_Rela *) native_relocs,
2551 &rela);
2552 else
2553 mips_elf64_swap_reloc_in (abfd,
2554 (Elf64_Mips_External_Rel *) native_relocs,
2555 &rela);
2557 /* Each entry represents exactly three actual relocations. */
2559 used_sym = FALSE;
2560 used_ssym = FALSE;
2561 for (ir = 0; ir < 3; ir++)
2563 enum elf_mips_reloc_type type;
2565 switch (ir)
2567 default:
2568 abort ();
2569 case 0:
2570 type = (enum elf_mips_reloc_type) rela.r_type;
2571 break;
2572 case 1:
2573 type = (enum elf_mips_reloc_type) rela.r_type2;
2574 break;
2575 case 2:
2576 type = (enum elf_mips_reloc_type) rela.r_type3;
2577 break;
2580 /* Some types require symbols, whereas some do not. */
2581 switch (type)
2583 case R_MIPS_NONE:
2584 case R_MIPS_LITERAL:
2585 case R_MIPS_INSERT_A:
2586 case R_MIPS_INSERT_B:
2587 case R_MIPS_DELETE:
2588 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2589 break;
2591 default:
2592 if (! used_sym)
2594 if (rela.r_sym == 0)
2595 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2596 else
2598 asymbol **ps, *s;
2600 ps = symbols + rela.r_sym - 1;
2601 s = *ps;
2602 if ((s->flags & BSF_SECTION_SYM) == 0)
2603 relent->sym_ptr_ptr = ps;
2604 else
2605 relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
2608 used_sym = TRUE;
2610 else if (! used_ssym)
2612 switch (rela.r_ssym)
2614 case RSS_UNDEF:
2615 relent->sym_ptr_ptr =
2616 bfd_abs_section_ptr->symbol_ptr_ptr;
2617 break;
2619 case RSS_GP:
2620 case RSS_GP0:
2621 case RSS_LOC:
2622 /* FIXME: I think these need to be handled using
2623 special howto structures. */
2624 BFD_ASSERT (0);
2625 break;
2627 default:
2628 BFD_ASSERT (0);
2629 break;
2632 used_ssym = TRUE;
2634 else
2635 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2637 break;
2640 /* The address of an ELF reloc is section relative for an
2641 object file, and absolute for an executable file or
2642 shared library. The address of a BFD reloc is always
2643 section relative. */
2644 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
2645 relent->address = rela.r_offset;
2646 else
2647 relent->address = rela.r_offset - asect->vma;
2649 relent->addend = rela.r_addend;
2651 relent->howto = mips_elf64_rtype_to_howto (type, rela_p);
2653 ++relent;
2657 asect->reloc_count += (relent - relents) / 3;
2659 if (allocated != NULL)
2660 free (allocated);
2662 return TRUE;
2664 error_return:
2665 if (allocated != NULL)
2666 free (allocated);
2667 return FALSE;
2670 /* Read the relocations. On Irix 6, there can be two reloc sections
2671 associated with a single data section. This is copied from
2672 elfcode.h as well, with changes as small as accounting for 3
2673 internal relocs per external reloc and resetting reloc_count to
2674 zero before processing the relocs of a section. */
2676 static bfd_boolean
2677 mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect,
2678 asymbol **symbols, bfd_boolean dynamic)
2680 struct bfd_elf_section_data * const d = elf_section_data (asect);
2681 Elf_Internal_Shdr *rel_hdr;
2682 Elf_Internal_Shdr *rel_hdr2;
2683 bfd_size_type reloc_count;
2684 bfd_size_type reloc_count2;
2685 arelent *relents;
2686 bfd_size_type amt;
2688 if (asect->relocation != NULL)
2689 return TRUE;
2691 if (! dynamic)
2693 if ((asect->flags & SEC_RELOC) == 0
2694 || asect->reloc_count == 0)
2695 return TRUE;
2697 rel_hdr = &d->rel_hdr;
2698 reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
2699 rel_hdr2 = d->rel_hdr2;
2700 reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0);
2702 BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
2703 BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
2704 || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
2707 else
2709 /* Note that ASECT->RELOC_COUNT tends not to be accurate in this
2710 case because relocations against this section may use the
2711 dynamic symbol table, and in that case bfd_section_from_shdr
2712 in elf.c does not update the RELOC_COUNT. */
2713 if (asect->size == 0)
2714 return TRUE;
2716 rel_hdr = &d->this_hdr;
2717 reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
2718 rel_hdr2 = NULL;
2719 reloc_count2 = 0;
2722 /* Allocate space for 3 arelent structures for each Rel structure. */
2723 amt = (reloc_count + reloc_count2) * 3 * sizeof (arelent);
2724 relents = bfd_alloc (abfd, amt);
2725 if (relents == NULL)
2726 return FALSE;
2728 /* The slurp_one_reloc_table routine increments reloc_count. */
2729 asect->reloc_count = 0;
2731 if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
2732 rel_hdr, reloc_count,
2733 relents,
2734 symbols, dynamic))
2735 return FALSE;
2736 if (d->rel_hdr2 != NULL)
2738 if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
2739 rel_hdr2, reloc_count2,
2740 relents + reloc_count * 3,
2741 symbols, dynamic))
2742 return FALSE;
2745 asect->relocation = relents;
2746 return TRUE;
2749 /* Write out the relocations. */
2751 static void
2752 mips_elf64_write_relocs (bfd *abfd, asection *sec, void *data)
2754 bfd_boolean *failedp = data;
2755 int count;
2756 Elf_Internal_Shdr *rel_hdr;
2757 unsigned int idx;
2759 /* If we have already failed, don't do anything. */
2760 if (*failedp)
2761 return;
2763 if ((sec->flags & SEC_RELOC) == 0)
2764 return;
2766 /* The linker backend writes the relocs out itself, and sets the
2767 reloc_count field to zero to inhibit writing them here. Also,
2768 sometimes the SEC_RELOC flag gets set even when there aren't any
2769 relocs. */
2770 if (sec->reloc_count == 0)
2771 return;
2773 /* We can combine up to three relocs that refer to the same address
2774 if the latter relocs have no associated symbol. */
2775 count = 0;
2776 for (idx = 0; idx < sec->reloc_count; idx++)
2778 bfd_vma addr;
2779 unsigned int i;
2781 ++count;
2783 addr = sec->orelocation[idx]->address;
2784 for (i = 0; i < 2; i++)
2786 arelent *r;
2788 if (idx + 1 >= sec->reloc_count)
2789 break;
2790 r = sec->orelocation[idx + 1];
2791 if (r->address != addr
2792 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2793 || (*r->sym_ptr_ptr)->value != 0)
2794 break;
2796 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2798 ++idx;
2802 rel_hdr = &elf_section_data (sec)->rel_hdr;
2804 /* Do the actual relocation. */
2806 if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rel))
2807 mips_elf64_write_rel (abfd, sec, rel_hdr, &count, data);
2808 else if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rela))
2809 mips_elf64_write_rela (abfd, sec, rel_hdr, &count, data);
2810 else
2811 BFD_ASSERT (0);
2814 static void
2815 mips_elf64_write_rel (bfd *abfd, asection *sec,
2816 Elf_Internal_Shdr *rel_hdr,
2817 int *count, void *data)
2819 bfd_boolean *failedp = data;
2820 Elf64_Mips_External_Rel *ext_rel;
2821 unsigned int idx;
2822 asymbol *last_sym = 0;
2823 int last_sym_idx = 0;
2825 rel_hdr->sh_size = rel_hdr->sh_entsize * *count;
2826 rel_hdr->contents = bfd_alloc (abfd, rel_hdr->sh_size);
2827 if (rel_hdr->contents == NULL)
2829 *failedp = TRUE;
2830 return;
2833 ext_rel = (Elf64_Mips_External_Rel *) rel_hdr->contents;
2834 for (idx = 0; idx < sec->reloc_count; idx++, ext_rel++)
2836 arelent *ptr;
2837 Elf64_Mips_Internal_Rela int_rel;
2838 asymbol *sym;
2839 int n;
2840 unsigned int i;
2842 ptr = sec->orelocation[idx];
2844 /* The address of an ELF reloc is section relative for an object
2845 file, and absolute for an executable file or shared library.
2846 The address of a BFD reloc is always section relative. */
2847 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2848 int_rel.r_offset = ptr->address;
2849 else
2850 int_rel.r_offset = ptr->address + sec->vma;
2852 sym = *ptr->sym_ptr_ptr;
2853 if (sym == last_sym)
2854 n = last_sym_idx;
2855 else if (bfd_is_abs_section (sym->section) && sym->value == 0)
2856 n = STN_UNDEF;
2857 else
2859 last_sym = sym;
2860 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2861 if (n < 0)
2863 *failedp = TRUE;
2864 return;
2866 last_sym_idx = n;
2869 int_rel.r_sym = n;
2870 int_rel.r_ssym = RSS_UNDEF;
2872 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2873 && ! _bfd_elf_validate_reloc (abfd, ptr))
2875 *failedp = TRUE;
2876 return;
2879 int_rel.r_type = ptr->howto->type;
2880 int_rel.r_type2 = (int) R_MIPS_NONE;
2881 int_rel.r_type3 = (int) R_MIPS_NONE;
2883 for (i = 0; i < 2; i++)
2885 arelent *r;
2887 if (idx + 1 >= sec->reloc_count)
2888 break;
2889 r = sec->orelocation[idx + 1];
2890 if (r->address != ptr->address
2891 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2892 || (*r->sym_ptr_ptr)->value != 0)
2893 break;
2895 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2897 if (i == 0)
2898 int_rel.r_type2 = r->howto->type;
2899 else
2900 int_rel.r_type3 = r->howto->type;
2902 ++idx;
2905 mips_elf64_swap_reloc_out (abfd, &int_rel, ext_rel);
2908 BFD_ASSERT (ext_rel - (Elf64_Mips_External_Rel *) rel_hdr->contents
2909 == *count);
2912 static void
2913 mips_elf64_write_rela (bfd *abfd, asection *sec,
2914 Elf_Internal_Shdr *rela_hdr,
2915 int *count, void *data)
2917 bfd_boolean *failedp = data;
2918 Elf64_Mips_External_Rela *ext_rela;
2919 unsigned int idx;
2920 asymbol *last_sym = 0;
2921 int last_sym_idx = 0;
2923 rela_hdr->sh_size = rela_hdr->sh_entsize * *count;
2924 rela_hdr->contents = bfd_alloc (abfd, rela_hdr->sh_size);
2925 if (rela_hdr->contents == NULL)
2927 *failedp = TRUE;
2928 return;
2931 ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
2932 for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
2934 arelent *ptr;
2935 Elf64_Mips_Internal_Rela int_rela;
2936 asymbol *sym;
2937 int n;
2938 unsigned int i;
2940 ptr = sec->orelocation[idx];
2942 /* The address of an ELF reloc is section relative for an object
2943 file, and absolute for an executable file or shared library.
2944 The address of a BFD reloc is always section relative. */
2945 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2946 int_rela.r_offset = ptr->address;
2947 else
2948 int_rela.r_offset = ptr->address + sec->vma;
2950 sym = *ptr->sym_ptr_ptr;
2951 if (sym == last_sym)
2952 n = last_sym_idx;
2953 else if (bfd_is_abs_section (sym->section) && sym->value == 0)
2954 n = STN_UNDEF;
2955 else
2957 last_sym = sym;
2958 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2959 if (n < 0)
2961 *failedp = TRUE;
2962 return;
2964 last_sym_idx = n;
2967 int_rela.r_sym = n;
2968 int_rela.r_addend = ptr->addend;
2969 int_rela.r_ssym = RSS_UNDEF;
2971 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2972 && ! _bfd_elf_validate_reloc (abfd, ptr))
2974 *failedp = TRUE;
2975 return;
2978 int_rela.r_type = ptr->howto->type;
2979 int_rela.r_type2 = (int) R_MIPS_NONE;
2980 int_rela.r_type3 = (int) R_MIPS_NONE;
2982 for (i = 0; i < 2; i++)
2984 arelent *r;
2986 if (idx + 1 >= sec->reloc_count)
2987 break;
2988 r = sec->orelocation[idx + 1];
2989 if (r->address != ptr->address
2990 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2991 || (*r->sym_ptr_ptr)->value != 0)
2992 break;
2994 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2996 if (i == 0)
2997 int_rela.r_type2 = r->howto->type;
2998 else
2999 int_rela.r_type3 = r->howto->type;
3001 ++idx;
3004 mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
3007 BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
3008 == *count);
3011 /* Set the right machine number for a MIPS ELF file. */
3013 static bfd_boolean
3014 mips_elf64_object_p (bfd *abfd)
3016 unsigned long mach;
3018 /* Irix 6 is broken. Object file symbol tables are not always
3019 sorted correctly such that local symbols precede global symbols,
3020 and the sh_info field in the symbol table is not always right. */
3021 if (elf64_mips_irix_compat (abfd) != ict_none)
3022 elf_bad_symtab (abfd) = TRUE;
3024 mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags);
3025 bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach);
3026 return TRUE;
3029 /* Depending on the target vector we generate some version of Irix
3030 executables or "normal" MIPS ELF ABI executables. */
3031 static irix_compat_t
3032 elf64_mips_irix_compat (bfd *abfd)
3034 if ((abfd->xvec == &bfd_elf64_bigmips_vec)
3035 || (abfd->xvec == &bfd_elf64_littlemips_vec))
3036 return ict_irix6;
3037 else
3038 return ict_none;
3041 /* Support for core dump NOTE sections. */
3042 static bfd_boolean
3043 elf64_mips_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
3045 int offset;
3046 unsigned int size;
3048 switch (note->descsz)
3050 default:
3051 return FALSE;
3053 case 480: /* Linux/MIPS - N64 kernel */
3054 /* pr_cursig */
3055 elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
3057 /* pr_pid */
3058 elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 32);
3060 /* pr_reg */
3061 offset = 112;
3062 size = 360;
3064 break;
3067 /* Make a ".reg/999" section. */
3068 return _bfd_elfcore_make_pseudosection (abfd, ".reg",
3069 size, note->descpos + offset);
3072 static bfd_boolean
3073 elf64_mips_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
3075 switch (note->descsz)
3077 default:
3078 return FALSE;
3080 case 136: /* Linux/MIPS - N64 kernel elf_prpsinfo */
3081 elf_tdata (abfd)->core_program
3082 = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
3083 elf_tdata (abfd)->core_command
3084 = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
3087 /* Note that for some reason, a spurious space is tacked
3088 onto the end of the args in some (at least one anyway)
3089 implementations, so strip it off if it exists. */
3092 char *command = elf_tdata (abfd)->core_command;
3093 int n = strlen (command);
3095 if (0 < n && command[n - 1] == ' ')
3096 command[n - 1] = '\0';
3099 return TRUE;
3102 /* ECOFF swapping routines. These are used when dealing with the
3103 .mdebug section, which is in the ECOFF debugging format. */
3104 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
3106 /* Symbol table magic number. */
3107 magicSym2,
3108 /* Alignment of debugging information. E.g., 4. */
3110 /* Sizes of external symbolic information. */
3111 sizeof (struct hdr_ext),
3112 sizeof (struct dnr_ext),
3113 sizeof (struct pdr_ext),
3114 sizeof (struct sym_ext),
3115 sizeof (struct opt_ext),
3116 sizeof (struct fdr_ext),
3117 sizeof (struct rfd_ext),
3118 sizeof (struct ext_ext),
3119 /* Functions to swap in external symbolic data. */
3120 ecoff_swap_hdr_in,
3121 ecoff_swap_dnr_in,
3122 ecoff_swap_pdr_in,
3123 ecoff_swap_sym_in,
3124 ecoff_swap_opt_in,
3125 ecoff_swap_fdr_in,
3126 ecoff_swap_rfd_in,
3127 ecoff_swap_ext_in,
3128 _bfd_ecoff_swap_tir_in,
3129 _bfd_ecoff_swap_rndx_in,
3130 /* Functions to swap out external symbolic data. */
3131 ecoff_swap_hdr_out,
3132 ecoff_swap_dnr_out,
3133 ecoff_swap_pdr_out,
3134 ecoff_swap_sym_out,
3135 ecoff_swap_opt_out,
3136 ecoff_swap_fdr_out,
3137 ecoff_swap_rfd_out,
3138 ecoff_swap_ext_out,
3139 _bfd_ecoff_swap_tir_out,
3140 _bfd_ecoff_swap_rndx_out,
3141 /* Function to read in symbolic data. */
3142 _bfd_mips_elf_read_ecoff_info
3145 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
3146 standard ELF. This structure is used to redirect the relocation
3147 handling routines. */
3149 const struct elf_size_info mips_elf64_size_info =
3151 sizeof (Elf64_External_Ehdr),
3152 sizeof (Elf64_External_Phdr),
3153 sizeof (Elf64_External_Shdr),
3154 sizeof (Elf64_Mips_External_Rel),
3155 sizeof (Elf64_Mips_External_Rela),
3156 sizeof (Elf64_External_Sym),
3157 sizeof (Elf64_External_Dyn),
3158 sizeof (Elf_External_Note),
3159 4, /* hash-table entry size */
3160 3, /* internal relocations per external relocations */
3161 64, /* arch_size */
3162 3, /* log_file_align */
3163 ELFCLASS64,
3164 EV_CURRENT,
3165 bfd_elf64_write_out_phdrs,
3166 bfd_elf64_write_shdrs_and_ehdr,
3167 bfd_elf64_checksum_contents,
3168 mips_elf64_write_relocs,
3169 bfd_elf64_swap_symbol_in,
3170 bfd_elf64_swap_symbol_out,
3171 mips_elf64_slurp_reloc_table,
3172 bfd_elf64_slurp_symbol_table,
3173 bfd_elf64_swap_dyn_in,
3174 bfd_elf64_swap_dyn_out,
3175 mips_elf64_be_swap_reloc_in,
3176 mips_elf64_be_swap_reloc_out,
3177 mips_elf64_be_swap_reloca_in,
3178 mips_elf64_be_swap_reloca_out
3181 #define ELF_ARCH bfd_arch_mips
3182 #define ELF_MACHINE_CODE EM_MIPS
3184 #define elf_backend_collect TRUE
3185 #define elf_backend_type_change_ok TRUE
3186 #define elf_backend_can_gc_sections TRUE
3187 #define elf_info_to_howto mips_elf64_info_to_howto_rela
3188 #define elf_info_to_howto_rel mips_elf64_info_to_howto_rel
3189 #define elf_backend_object_p mips_elf64_object_p
3190 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
3191 #define elf_backend_section_processing _bfd_mips_elf_section_processing
3192 #define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
3193 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
3194 #define elf_backend_section_from_bfd_section \
3195 _bfd_mips_elf_section_from_bfd_section
3196 #define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook
3197 #define elf_backend_link_output_symbol_hook \
3198 _bfd_mips_elf_link_output_symbol_hook
3199 #define elf_backend_create_dynamic_sections \
3200 _bfd_mips_elf_create_dynamic_sections
3201 #define elf_backend_check_relocs _bfd_mips_elf_check_relocs
3202 #define elf_backend_merge_symbol_attribute \
3203 _bfd_mips_elf_merge_symbol_attribute
3204 #define elf_backend_get_target_dtag _bfd_mips_elf_get_target_dtag
3205 #define elf_backend_adjust_dynamic_symbol \
3206 _bfd_mips_elf_adjust_dynamic_symbol
3207 #define elf_backend_always_size_sections \
3208 _bfd_mips_elf_always_size_sections
3209 #define elf_backend_size_dynamic_sections \
3210 _bfd_mips_elf_size_dynamic_sections
3211 #define elf_backend_init_index_section _bfd_elf_init_1_index_section
3212 #define elf_backend_relocate_section _bfd_mips_elf_relocate_section
3213 #define elf_backend_finish_dynamic_symbol \
3214 _bfd_mips_elf_finish_dynamic_symbol
3215 #define elf_backend_finish_dynamic_sections \
3216 _bfd_mips_elf_finish_dynamic_sections
3217 #define elf_backend_final_write_processing \
3218 _bfd_mips_elf_final_write_processing
3219 #define elf_backend_additional_program_headers \
3220 _bfd_mips_elf_additional_program_headers
3221 #define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
3222 #define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook
3223 #define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
3224 #define elf_backend_copy_indirect_symbol \
3225 _bfd_mips_elf_copy_indirect_symbol
3226 #define elf_backend_ignore_discarded_relocs \
3227 _bfd_mips_elf_ignore_discarded_relocs
3228 #define elf_backend_mips_irix_compat elf64_mips_irix_compat
3229 #define elf_backend_mips_rtype_to_howto mips_elf64_rtype_to_howto
3230 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
3231 #define elf_backend_size_info mips_elf64_size_info
3233 #define elf_backend_grok_prstatus elf64_mips_grok_prstatus
3234 #define elf_backend_grok_psinfo elf64_mips_grok_psinfo
3236 #define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
3238 /* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
3239 work better/work only in RELA, so we default to this. */
3240 #define elf_backend_may_use_rel_p 1
3241 #define elf_backend_may_use_rela_p 1
3242 #define elf_backend_default_use_rela_p 1
3243 #define elf_backend_rela_plts_and_copies_p 0
3244 #define elf_backend_plt_readonly 1
3245 #define elf_backend_plt_sym_val _bfd_mips_elf_plt_sym_val
3247 #define elf_backend_sign_extend_vma TRUE
3249 #define elf_backend_write_section _bfd_mips_elf_write_section
3251 /* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit
3252 MIPS-specific function only applies to IRIX5, which had no 64-bit
3253 ABI. */
3254 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
3255 #define bfd_elf64_find_inliner_info _bfd_mips_elf_find_inliner_info
3256 #define bfd_elf64_new_section_hook _bfd_mips_elf_new_section_hook
3257 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
3258 #define bfd_elf64_bfd_get_relocated_section_contents \
3259 _bfd_elf_mips_get_relocated_section_contents
3260 #define bfd_elf64_mkobject _bfd_mips_elf_mkobject
3261 #define bfd_elf64_bfd_link_hash_table_create \
3262 _bfd_mips_elf_link_hash_table_create
3263 #define bfd_elf64_bfd_final_link _bfd_mips_elf_final_link
3264 #define bfd_elf64_bfd_merge_private_bfd_data \
3265 _bfd_mips_elf_merge_private_bfd_data
3266 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
3267 #define bfd_elf64_bfd_print_private_bfd_data \
3268 _bfd_mips_elf_print_private_bfd_data
3270 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
3271 #define bfd_elf64_canonicalize_reloc mips_elf64_canonicalize_reloc
3272 #define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
3273 #define bfd_elf64_canonicalize_dynamic_reloc mips_elf64_canonicalize_dynamic_reloc
3274 #define bfd_elf64_bfd_relax_section _bfd_mips_relax_section
3276 /* MIPS ELF64 archive functions. */
3277 #define bfd_elf64_archive_functions
3278 extern bfd_boolean bfd_elf64_archive_slurp_armap
3279 (bfd *);
3280 extern bfd_boolean bfd_elf64_archive_write_armap
3281 (bfd *, unsigned int, struct orl *, unsigned int, int);
3282 #define bfd_elf64_archive_slurp_extended_name_table \
3283 _bfd_archive_coff_slurp_extended_name_table
3284 #define bfd_elf64_archive_construct_extended_name_table \
3285 _bfd_archive_coff_construct_extended_name_table
3286 #define bfd_elf64_archive_truncate_arname \
3287 _bfd_archive_coff_truncate_arname
3288 #define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
3289 #define bfd_elf64_archive_openr_next_archived_file \
3290 _bfd_archive_coff_openr_next_archived_file
3291 #define bfd_elf64_archive_get_elt_at_index \
3292 _bfd_archive_coff_get_elt_at_index
3293 #define bfd_elf64_archive_generic_stat_arch_elt \
3294 _bfd_archive_coff_generic_stat_arch_elt
3295 #define bfd_elf64_archive_update_armap_timestamp \
3296 _bfd_archive_coff_update_armap_timestamp
3298 /* The SGI style (n)64 NewABI. */
3299 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
3300 #define TARGET_LITTLE_NAME "elf64-littlemips"
3301 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
3302 #define TARGET_BIG_NAME "elf64-bigmips"
3304 #define ELF_MAXPAGESIZE 0x10000
3305 #define ELF_COMMONPAGESIZE 0x1000
3307 #include "elf64-target.h"
3309 /* The SYSV-style 'traditional' (n)64 NewABI. */
3310 #undef TARGET_LITTLE_SYM
3311 #undef TARGET_LITTLE_NAME
3312 #undef TARGET_BIG_SYM
3313 #undef TARGET_BIG_NAME
3315 #undef ELF_MAXPAGESIZE
3316 #undef ELF_COMMONPAGESIZE
3318 #define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
3319 #define TARGET_LITTLE_NAME "elf64-tradlittlemips"
3320 #define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
3321 #define TARGET_BIG_NAME "elf64-tradbigmips"
3323 #define ELF_MAXPAGESIZE 0x10000
3324 #define ELF_COMMONPAGESIZE 0x1000
3325 #define elf64_bed elf64_tradbed
3327 /* Include the target file again for this target. */
3328 #include "elf64-target.h"