* elf64-mips.c: Improve reloc special_functions and handling of
[deliverable/binutils-gdb.git] / bfd / elf64-mips.c
1 /* MIPS-specific support for 64-bit ELF
2 Copyright 1996 Free Software Foundation, Inc.
3 Ian Lance Taylor, Cygnus Support
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 /* This file supports the 64-bit MIPS ELF ABI.
22
23 The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
24 overrides the usual ELF reloc handling, and handles reading and
25 writing the relocations here. */
26
27 #include "bfd.h"
28 #include "sysdep.h"
29 #include "libbfd.h"
30 #include "bfdlink.h"
31 #include "genlink.h"
32 #include "elf-bfd.h"
33 #include "elf/mips.h"
34
35 /* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
36 use ECOFF. However, we support it anyhow for an easier changeover. */
37 #include "coff/sym.h"
38 #include "coff/symconst.h"
39 #include "coff/internal.h"
40 #include "coff/ecoff.h"
41 /* The 64 bit versions of the mdebug data structures are in alpha.h. */
42 #include "coff/alpha.h"
43 #define ECOFF_64
44 #include "ecoffswap.h"
45
46 static void mips_elf64_swap_reloc_in
47 PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
48 Elf64_Mips_Internal_Rel *));
49 static void mips_elf64_swap_reloca_in
50 PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
51 Elf64_Mips_Internal_Rela *));
52 #if 0
53 static void mips_elf64_swap_reloc_out
54 PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
55 Elf64_Mips_External_Rel *));
56 #endif
57 static void mips_elf64_swap_reloca_out
58 PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
59 Elf64_Mips_External_Rela *));
60 static reloc_howto_type *mips_elf64_reloc_type_lookup
61 PARAMS ((bfd *, bfd_reloc_code_real_type));
62 static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
63 static boolean mips_elf64_slurp_one_reloc_table
64 PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
65 static boolean mips_elf64_slurp_reloc_table
66 PARAMS ((bfd *, asection *, asymbol **));
67 static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
68 static boolean mips_elf64_section_from_shdr
69 PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
70 static boolean mips_elf64_section_processing
71 PARAMS ((bfd *, Elf_Internal_Shdr *));
72
73 /* The relocation types. */
74
75 enum mips_elf64_reloc_type
76 {
77 R_MIPS_NONE = 0,
78 R_MIPS_16 = 1,
79 R_MIPS_32 = 2,
80 R_MIPS_ADD = 2,
81 R_MIPS_REL32 = 3,
82 R_MIPS_REL = 3,
83 R_MIPS_26 = 4,
84 R_MIPS_HI16 = 5,
85 R_MIPS_LO16 = 6,
86 R_MIPS_GPREL16 = 7,
87 R_MIPS_GPREL = 7,
88 R_MIPS_LITERAL = 8,
89 R_MIPS_GOT16 = 9,
90 R_MIPS_GOT = 9,
91 R_MIPS_PC16 = 10,
92 R_MIPS_CALL16 = 11,
93 R_MIPS_CALL = 11,
94 R_MIPS_GPREL32 = 12,
95 R_MIPS_SHIFT5 = 16,
96 R_MIPS_SHIFT6 = 17,
97 R_MIPS_64 = 18,
98 R_MIPS_GOT_DISP = 19,
99 R_MIPS_GOT_PAGE = 20,
100 R_MIPS_GOT_OFST = 21,
101 R_MIPS_GOT_HI16 = 22,
102 R_MIPS_GOT_LO16 = 23,
103 R_MIPS_SUB = 24,
104 R_MIPS_INSERT_A = 25,
105 R_MIPS_INSERT_B = 26,
106 R_MIPS_DELETE = 27,
107 R_MIPS_HIGHER = 28,
108 R_MIPS_HIGHEST = 29,
109 R_MIPS_CALL_HI16 = 30,
110 R_MIPS_CALL_LO16 = 31,
111 R_MIPS_SCN_DISP = 32,
112 R_MIPS_REL16 = 33,
113 R_MIPS_ADD_IMMEDIATE = 34,
114 R_MIPS_PJUMP = 35,
115 R_MIPS_RELGOT = 36
116 };
117
118 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
119 from smaller values. Start with zero, widen, *then* decrement. */
120 #define MINUS_ONE (((bfd_vma)0) - 1)
121
122 /* The relocation table used for SHT_REL sections. */
123
124 static reloc_howto_type mips_elf64_howto_table_rel[] =
125 {
126 /* No relocation. */
127 HOWTO (R_MIPS_NONE, /* type */
128 0, /* rightshift */
129 0, /* size (0 = byte, 1 = short, 2 = long) */
130 0, /* bitsize */
131 false, /* pc_relative */
132 0, /* bitpos */
133 complain_overflow_dont, /* complain_on_overflow */
134 bfd_elf_generic_reloc, /* special_function */
135 "R_MIPS_NONE", /* name */
136 false, /* partial_inplace */
137 0, /* src_mask */
138 0, /* dst_mask */
139 false), /* pcrel_offset */
140
141 /* 16 bit relocation. */
142 HOWTO (R_MIPS_16, /* type */
143 0, /* rightshift */
144 1, /* size (0 = byte, 1 = short, 2 = long) */
145 16, /* bitsize */
146 false, /* pc_relative */
147 0, /* bitpos */
148 complain_overflow_bitfield, /* complain_on_overflow */
149 bfd_elf_generic_reloc, /* special_function */
150 "R_MIPS_16", /* name */
151 true, /* partial_inplace */
152 0xffff, /* src_mask */
153 0xffff, /* dst_mask */
154 false), /* pcrel_offset */
155
156 /* 32 bit relocation. */
157 HOWTO (R_MIPS_32, /* type */
158 0, /* rightshift */
159 2, /* size (0 = byte, 1 = short, 2 = long) */
160 32, /* bitsize */
161 false, /* pc_relative */
162 0, /* bitpos */
163 complain_overflow_bitfield, /* complain_on_overflow */
164 bfd_elf_generic_reloc, /* special_function */
165 "R_MIPS_32", /* name */
166 true, /* partial_inplace */
167 0xffffffff, /* src_mask */
168 0xffffffff, /* dst_mask */
169 false), /* pcrel_offset */
170
171 /* 32 bit symbol relative relocation. */
172 HOWTO (R_MIPS_REL32, /* type */
173 0, /* rightshift */
174 2, /* size (0 = byte, 1 = short, 2 = long) */
175 32, /* bitsize */
176 false, /* pc_relative */
177 0, /* bitpos */
178 complain_overflow_bitfield, /* complain_on_overflow */
179 bfd_elf_generic_reloc, /* special_function */
180 "R_MIPS_REL32", /* name */
181 true, /* partial_inplace */
182 0xffffffff, /* src_mask */
183 0xffffffff, /* dst_mask */
184 false), /* pcrel_offset */
185
186 /* 26 bit branch address. */
187 HOWTO (R_MIPS_26, /* type */
188 2, /* rightshift */
189 2, /* size (0 = byte, 1 = short, 2 = long) */
190 26, /* bitsize */
191 false, /* pc_relative */
192 0, /* bitpos */
193 complain_overflow_dont, /* complain_on_overflow */
194 /* This needs complex overflow
195 detection, because the upper four
196 bits must match the PC. */
197 bfd_elf_generic_reloc, /* special_function */
198 "R_MIPS_26", /* name */
199 true, /* partial_inplace */
200 0x3ffffff, /* src_mask */
201 0x3ffffff, /* dst_mask */
202 false), /* pcrel_offset */
203
204 /* High 16 bits of symbol value. */
205 HOWTO (R_MIPS_HI16, /* type */
206 0, /* rightshift */
207 2, /* size (0 = byte, 1 = short, 2 = long) */
208 16, /* bitsize */
209 false, /* pc_relative */
210 0, /* bitpos */
211 complain_overflow_dont, /* complain_on_overflow */
212 _bfd_mips_elf_hi16_reloc, /* special_function */
213 "R_MIPS_HI16", /* name */
214 true, /* partial_inplace */
215 0xffff, /* src_mask */
216 0xffff, /* dst_mask */
217 false), /* pcrel_offset */
218
219 /* Low 16 bits of symbol value. */
220 HOWTO (R_MIPS_LO16, /* type */
221 0, /* rightshift */
222 2, /* size (0 = byte, 1 = short, 2 = long) */
223 16, /* bitsize */
224 false, /* pc_relative */
225 0, /* bitpos */
226 complain_overflow_dont, /* complain_on_overflow */
227 _bfd_mips_elf_lo16_reloc, /* special_function */
228 "R_MIPS_LO16", /* name */
229 true, /* partial_inplace */
230 0xffff, /* src_mask */
231 0xffff, /* dst_mask */
232 false), /* pcrel_offset */
233
234 /* GP relative reference. */
235 HOWTO (R_MIPS_GPREL16, /* type */
236 0, /* rightshift */
237 2, /* size (0 = byte, 1 = short, 2 = long) */
238 16, /* bitsize */
239 false, /* pc_relative */
240 0, /* bitpos */
241 complain_overflow_signed, /* complain_on_overflow */
242 _bfd_mips_elf_gprel16_reloc, /* special_function */
243 "R_MIPS_GPREL16", /* name */
244 true, /* partial_inplace */
245 0xffff, /* src_mask */
246 0xffff, /* dst_mask */
247 false), /* pcrel_offset */
248
249 /* Reference to literal section. */
250 HOWTO (R_MIPS_LITERAL, /* type */
251 0, /* rightshift */
252 2, /* size (0 = byte, 1 = short, 2 = long) */
253 16, /* bitsize */
254 false, /* pc_relative */
255 0, /* bitpos */
256 complain_overflow_signed, /* complain_on_overflow */
257 _bfd_mips_elf_gprel16_reloc, /* special_function */
258 "R_MIPS_LITERAL", /* name */
259 true, /* partial_inplace */
260 0xffff, /* src_mask */
261 0xffff, /* dst_mask */
262 false), /* pcrel_offset */
263
264 /* Reference to global offset table. */
265 HOWTO (R_MIPS_GOT16, /* type */
266 0, /* rightshift */
267 2, /* size (0 = byte, 1 = short, 2 = long) */
268 16, /* bitsize */
269 false, /* pc_relative */
270 0, /* bitpos */
271 complain_overflow_signed, /* complain_on_overflow */
272 _bfd_mips_elf_got16_reloc, /* special_function */
273 "R_MIPS_GOT16", /* name */
274 false, /* partial_inplace */
275 0, /* src_mask */
276 0xffff, /* dst_mask */
277 false), /* pcrel_offset */
278
279 /* 16 bit PC relative reference. */
280 HOWTO (R_MIPS_PC16, /* type */
281 0, /* rightshift */
282 2, /* size (0 = byte, 1 = short, 2 = long) */
283 16, /* bitsize */
284 true, /* pc_relative */
285 0, /* bitpos */
286 complain_overflow_signed, /* complain_on_overflow */
287 bfd_elf_generic_reloc, /* special_function */
288 "R_MIPS_PC16", /* name */
289 true, /* partial_inplace */
290 0xffff, /* src_mask */
291 0xffff, /* dst_mask */
292 false), /* pcrel_offset */
293
294 /* 16 bit call through global offset table. */
295 /* FIXME: This is not handled correctly. */
296 HOWTO (R_MIPS_CALL16, /* type */
297 0, /* rightshift */
298 2, /* size (0 = byte, 1 = short, 2 = long) */
299 16, /* bitsize */
300 false, /* pc_relative */
301 0, /* bitpos */
302 complain_overflow_signed, /* complain_on_overflow */
303 bfd_elf_generic_reloc, /* special_function */
304 "R_MIPS_CALL16", /* name */
305 false, /* partial_inplace */
306 0, /* src_mask */
307 0xffff, /* dst_mask */
308 false), /* pcrel_offset */
309
310 /* 32 bit GP relative reference. */
311 HOWTO (R_MIPS_GPREL32, /* type */
312 0, /* rightshift */
313 2, /* size (0 = byte, 1 = short, 2 = long) */
314 32, /* bitsize */
315 false, /* pc_relative */
316 0, /* bitpos */
317 complain_overflow_bitfield, /* complain_on_overflow */
318 _bfd_mips_elf_gprel32_reloc, /* special_function */
319 "R_MIPS_GPREL32", /* name */
320 true, /* partial_inplace */
321 0xffffffff, /* src_mask */
322 0xffffffff, /* dst_mask */
323 false), /* pcrel_offset */
324
325 { 13 },
326 { 14 },
327 { 15 },
328
329 /* A 5 bit shift field. */
330 HOWTO (R_MIPS_SHIFT5, /* type */
331 0, /* rightshift */
332 2, /* size (0 = byte, 1 = short, 2 = long) */
333 5, /* bitsize */
334 false, /* pc_relative */
335 6, /* bitpos */
336 complain_overflow_bitfield, /* complain_on_overflow */
337 bfd_elf_generic_reloc, /* special_function */
338 "R_MIPS_SHIFT5", /* name */
339 true, /* partial_inplace */
340 0x000007c0, /* src_mask */
341 0x000007c0, /* dst_mask */
342 false), /* pcrel_offset */
343
344 /* A 6 bit shift field. */
345 /* FIXME: This is not handled correctly; a special function is
346 needed to put the most significant bit in the right place. */
347 HOWTO (R_MIPS_SHIFT6, /* type */
348 0, /* rightshift */
349 2, /* size (0 = byte, 1 = short, 2 = long) */
350 6, /* bitsize */
351 false, /* pc_relative */
352 6, /* bitpos */
353 complain_overflow_bitfield, /* complain_on_overflow */
354 bfd_elf_generic_reloc, /* special_function */
355 "R_MIPS_SHIFT6", /* name */
356 true, /* partial_inplace */
357 0x000007c4, /* src_mask */
358 0x000007c4, /* dst_mask */
359 false), /* pcrel_offset */
360
361 /* 64 bit relocation. */
362 HOWTO (R_MIPS_64, /* type */
363 0, /* rightshift */
364 4, /* size (0 = byte, 1 = short, 2 = long) */
365 64, /* bitsize */
366 false, /* pc_relative */
367 0, /* bitpos */
368 complain_overflow_bitfield, /* complain_on_overflow */
369 bfd_elf_generic_reloc, /* special_function */
370 "R_MIPS_64", /* name */
371 true, /* partial_inplace */
372 MINUS_ONE, /* src_mask */
373 MINUS_ONE, /* dst_mask */
374 false), /* pcrel_offset */
375
376 /* Displacement in the global offset table. */
377 /* FIXME: Not handled correctly. */
378 HOWTO (R_MIPS_GOT_DISP, /* type */
379 0, /* rightshift */
380 2, /* size (0 = byte, 1 = short, 2 = long) */
381 16, /* bitsize */
382 false, /* pc_relative */
383 0, /* bitpos */
384 complain_overflow_bitfield, /* complain_on_overflow */
385 bfd_elf_generic_reloc, /* special_function */
386 "R_MIPS_GOT_DISP", /* name */
387 true, /* partial_inplace */
388 0x0000ffff, /* src_mask */
389 0x0000ffff, /* dst_mask */
390 false), /* pcrel_offset */
391
392 /* Displacement to page pointer in the global offset table. */
393 /* FIXME: Not handled correctly. */
394 HOWTO (R_MIPS_GOT_PAGE, /* type */
395 0, /* rightshift */
396 2, /* size (0 = byte, 1 = short, 2 = long) */
397 16, /* bitsize */
398 false, /* pc_relative */
399 0, /* bitpos */
400 complain_overflow_bitfield, /* complain_on_overflow */
401 bfd_elf_generic_reloc, /* special_function */
402 "R_MIPS_GOT_PAGE", /* name */
403 true, /* partial_inplace */
404 0x0000ffff, /* src_mask */
405 0x0000ffff, /* dst_mask */
406 false), /* pcrel_offset */
407
408 /* Offset from page pointer in the global offset table. */
409 /* FIXME: Not handled correctly. */
410 HOWTO (R_MIPS_GOT_OFST, /* type */
411 0, /* rightshift */
412 2, /* size (0 = byte, 1 = short, 2 = long) */
413 16, /* bitsize */
414 false, /* pc_relative */
415 0, /* bitpos */
416 complain_overflow_bitfield, /* complain_on_overflow */
417 bfd_elf_generic_reloc, /* special_function */
418 "R_MIPS_GOT_OFST", /* name */
419 true, /* partial_inplace */
420 0x0000ffff, /* src_mask */
421 0x0000ffff, /* dst_mask */
422 false), /* pcrel_offset */
423
424 /* High 16 bits of displacement in global offset table. */
425 /* FIXME: Not handled correctly. */
426 HOWTO (R_MIPS_GOT_HI16, /* type */
427 0, /* rightshift */
428 2, /* size (0 = byte, 1 = short, 2 = long) */
429 16, /* bitsize */
430 false, /* pc_relative */
431 0, /* bitpos */
432 complain_overflow_dont, /* complain_on_overflow */
433 bfd_elf_generic_reloc, /* special_function */
434 "R_MIPS_GOT_HI16", /* name */
435 true, /* partial_inplace */
436 0x0000ffff, /* src_mask */
437 0x0000ffff, /* dst_mask */
438 false), /* pcrel_offset */
439
440 /* Low 16 bits of displacement in global offset table. */
441 /* FIXME: Not handled correctly. */
442 HOWTO (R_MIPS_GOT_LO16, /* type */
443 0, /* rightshift */
444 2, /* size (0 = byte, 1 = short, 2 = long) */
445 16, /* bitsize */
446 false, /* pc_relative */
447 0, /* bitpos */
448 complain_overflow_dont, /* complain_on_overflow */
449 bfd_elf_generic_reloc, /* special_function */
450 "R_MIPS_GOT_LO16", /* name */
451 true, /* partial_inplace */
452 0x0000ffff, /* src_mask */
453 0x0000ffff, /* dst_mask */
454 false), /* pcrel_offset */
455
456 /* 64 bit substraction. */
457 /* FIXME: Not handled correctly. */
458 HOWTO (R_MIPS_SUB, /* type */
459 0, /* rightshift */
460 4, /* size (0 = byte, 1 = short, 2 = long) */
461 64, /* bitsize */
462 false, /* pc_relative */
463 0, /* bitpos */
464 complain_overflow_bitfield, /* complain_on_overflow */
465 bfd_elf_generic_reloc, /* special_function */
466 "R_MIPS_SUB", /* name */
467 true, /* partial_inplace */
468 MINUS_ONE, /* src_mask */
469 MINUS_ONE, /* dst_mask */
470 false), /* pcrel_offset */
471
472 /* Insert the addend as an instruction. */
473 /* FIXME: Not handled correctly. */
474 HOWTO (R_MIPS_INSERT_A, /* type */
475 0, /* rightshift */
476 0, /* size (0 = byte, 1 = short, 2 = long) */
477 0, /* bitsize */
478 false, /* pc_relative */
479 0, /* bitpos */
480 complain_overflow_dont, /* complain_on_overflow */
481 bfd_elf_generic_reloc, /* special_function */
482 "R_MIPS_INSERT_A", /* name */
483 false, /* partial_inplace */
484 0, /* src_mask */
485 0, /* dst_mask */
486 false), /* pcrel_offset */
487
488 /* Insert the addend as an instruction, and change all relocations
489 to refer to the old instruction at the address. */
490 /* FIXME: Not handled correctly. */
491 HOWTO (R_MIPS_INSERT_B, /* type */
492 0, /* rightshift */
493 0, /* size (0 = byte, 1 = short, 2 = long) */
494 0, /* bitsize */
495 false, /* pc_relative */
496 0, /* bitpos */
497 complain_overflow_dont, /* complain_on_overflow */
498 bfd_elf_generic_reloc, /* special_function */
499 "R_MIPS_INSERT_B", /* name */
500 false, /* partial_inplace */
501 0, /* src_mask */
502 0, /* dst_mask */
503 false), /* pcrel_offset */
504
505 /* Delete a 32 bit instruction. */
506 /* FIXME: Not handled correctly. */
507 HOWTO (R_MIPS_DELETE, /* type */
508 0, /* rightshift */
509 0, /* size (0 = byte, 1 = short, 2 = long) */
510 0, /* bitsize */
511 false, /* pc_relative */
512 0, /* bitpos */
513 complain_overflow_dont, /* complain_on_overflow */
514 bfd_elf_generic_reloc, /* special_function */
515 "R_MIPS_DELETE", /* name */
516 false, /* partial_inplace */
517 0, /* src_mask */
518 0, /* dst_mask */
519 false), /* pcrel_offset */
520
521 /* Get the higher value of a 64 bit addend. */
522 /* FIXME: Not handled correctly. */
523 HOWTO (R_MIPS_HIGHER, /* type */
524 0, /* rightshift */
525 2, /* size (0 = byte, 1 = short, 2 = long) */
526 16, /* bitsize */
527 false, /* pc_relative */
528 0, /* bitpos */
529 complain_overflow_dont, /* complain_on_overflow */
530 bfd_elf_generic_reloc, /* special_function */
531 "R_MIPS_HIGHER", /* name */
532 true, /* partial_inplace */
533 0xffff, /* src_mask */
534 0xffff, /* dst_mask */
535 false), /* pcrel_offset */
536
537 /* Get the highest value of a 64 bit addend. */
538 /* FIXME: Not handled correctly. */
539 HOWTO (R_MIPS_HIGHEST, /* type */
540 0, /* rightshift */
541 2, /* size (0 = byte, 1 = short, 2 = long) */
542 16, /* bitsize */
543 false, /* pc_relative */
544 0, /* bitpos */
545 complain_overflow_dont, /* complain_on_overflow */
546 bfd_elf_generic_reloc, /* special_function */
547 "R_MIPS_HIGHEST", /* name */
548 true, /* partial_inplace */
549 0xffff, /* src_mask */
550 0xffff, /* dst_mask */
551 false), /* pcrel_offset */
552
553 /* High 16 bits of displacement in global offset table. */
554 /* FIXME: Not handled correctly. */
555 HOWTO (R_MIPS_CALL_HI16, /* type */
556 0, /* rightshift */
557 2, /* size (0 = byte, 1 = short, 2 = long) */
558 16, /* bitsize */
559 false, /* pc_relative */
560 0, /* bitpos */
561 complain_overflow_dont, /* complain_on_overflow */
562 bfd_elf_generic_reloc, /* special_function */
563 "R_MIPS_CALL_HI16", /* name */
564 true, /* partial_inplace */
565 0x0000ffff, /* src_mask */
566 0x0000ffff, /* dst_mask */
567 false), /* pcrel_offset */
568
569 /* Low 16 bits of displacement in global offset table. */
570 /* FIXME: Not handled correctly. */
571 HOWTO (R_MIPS_CALL_LO16, /* type */
572 0, /* rightshift */
573 2, /* size (0 = byte, 1 = short, 2 = long) */
574 16, /* bitsize */
575 false, /* pc_relative */
576 0, /* bitpos */
577 complain_overflow_dont, /* complain_on_overflow */
578 bfd_elf_generic_reloc, /* special_function */
579 "R_MIPS_CALL_LO16", /* name */
580 true, /* partial_inplace */
581 0x0000ffff, /* src_mask */
582 0x0000ffff, /* dst_mask */
583 false), /* pcrel_offset */
584
585 /* I'm not sure what the remaining relocs are, but they are defined
586 on Irix 6. */
587
588 HOWTO (R_MIPS_SCN_DISP, /* type */
589 0, /* rightshift */
590 0, /* size (0 = byte, 1 = short, 2 = long) */
591 0, /* bitsize */
592 false, /* pc_relative */
593 0, /* bitpos */
594 complain_overflow_dont, /* complain_on_overflow */
595 bfd_elf_generic_reloc, /* special_function */
596 "R_MIPS_SCN_DISP", /* name */
597 false, /* partial_inplace */
598 0, /* src_mask */
599 0, /* dst_mask */
600 false), /* pcrel_offset */
601
602 HOWTO (R_MIPS_REL16, /* type */
603 0, /* rightshift */
604 0, /* size (0 = byte, 1 = short, 2 = long) */
605 0, /* bitsize */
606 false, /* pc_relative */
607 0, /* bitpos */
608 complain_overflow_dont, /* complain_on_overflow */
609 bfd_elf_generic_reloc, /* special_function */
610 "R_MIPS_REL16", /* name */
611 false, /* partial_inplace */
612 0, /* src_mask */
613 0, /* dst_mask */
614 false), /* pcrel_offset */
615
616 HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
617 0, /* rightshift */
618 0, /* size (0 = byte, 1 = short, 2 = long) */
619 0, /* bitsize */
620 false, /* pc_relative */
621 0, /* bitpos */
622 complain_overflow_dont, /* complain_on_overflow */
623 bfd_elf_generic_reloc, /* special_function */
624 "R_MIPS_ADD_IMMEDIATE", /* name */
625 false, /* partial_inplace */
626 0, /* src_mask */
627 0, /* dst_mask */
628 false), /* pcrel_offset */
629
630 HOWTO (R_MIPS_PJUMP, /* type */
631 0, /* rightshift */
632 0, /* size (0 = byte, 1 = short, 2 = long) */
633 0, /* bitsize */
634 false, /* pc_relative */
635 0, /* bitpos */
636 complain_overflow_dont, /* complain_on_overflow */
637 bfd_elf_generic_reloc, /* special_function */
638 "R_MIPS_PJUMP", /* name */
639 false, /* partial_inplace */
640 0, /* src_mask */
641 0, /* dst_mask */
642 false), /* pcrel_offset */
643
644 HOWTO (R_MIPS_RELGOT, /* type */
645 0, /* rightshift */
646 0, /* size (0 = byte, 1 = short, 2 = long) */
647 0, /* bitsize */
648 false, /* pc_relative */
649 0, /* bitpos */
650 complain_overflow_dont, /* complain_on_overflow */
651 bfd_elf_generic_reloc, /* special_function */
652 "R_MIPS_RELGOT", /* name */
653 false, /* partial_inplace */
654 0, /* src_mask */
655 0, /* dst_mask */
656 false) /* pcrel_offset */
657 };
658
659 /* The relocation table used for SHT_RELA sections. */
660
661 static reloc_howto_type mips_elf64_howto_table_rela[] =
662 {
663 /* No relocation. */
664 HOWTO (R_MIPS_NONE, /* type */
665 0, /* rightshift */
666 0, /* size (0 = byte, 1 = short, 2 = long) */
667 0, /* bitsize */
668 false, /* pc_relative */
669 0, /* bitpos */
670 complain_overflow_dont, /* complain_on_overflow */
671 bfd_elf_generic_reloc, /* special_function */
672 "R_MIPS_NONE", /* name */
673 false, /* partial_inplace */
674 0, /* src_mask */
675 0, /* dst_mask */
676 false), /* pcrel_offset */
677
678 /* 16 bit relocation. */
679 HOWTO (R_MIPS_16, /* type */
680 0, /* rightshift */
681 1, /* size (0 = byte, 1 = short, 2 = long) */
682 16, /* bitsize */
683 false, /* pc_relative */
684 0, /* bitpos */
685 complain_overflow_bitfield, /* complain_on_overflow */
686 bfd_elf_generic_reloc, /* special_function */
687 "R_MIPS_16", /* name */
688 true, /* partial_inplace */
689 0, /* src_mask */
690 0xffff, /* dst_mask */
691 false), /* pcrel_offset */
692
693 /* 32 bit relocation. */
694 HOWTO (R_MIPS_32, /* type */
695 0, /* rightshift */
696 2, /* size (0 = byte, 1 = short, 2 = long) */
697 32, /* bitsize */
698 false, /* pc_relative */
699 0, /* bitpos */
700 complain_overflow_bitfield, /* complain_on_overflow */
701 bfd_elf_generic_reloc, /* special_function */
702 "R_MIPS_32", /* name */
703 true, /* partial_inplace */
704 0, /* src_mask */
705 0xffffffff, /* dst_mask */
706 false), /* pcrel_offset */
707
708 /* 32 bit symbol relative relocation. */
709 HOWTO (R_MIPS_REL32, /* type */
710 0, /* rightshift */
711 2, /* size (0 = byte, 1 = short, 2 = long) */
712 32, /* bitsize */
713 false, /* pc_relative */
714 0, /* bitpos */
715 complain_overflow_bitfield, /* complain_on_overflow */
716 bfd_elf_generic_reloc, /* special_function */
717 "R_MIPS_REL32", /* name */
718 true, /* partial_inplace */
719 0, /* src_mask */
720 0xffffffff, /* dst_mask */
721 false), /* pcrel_offset */
722
723 /* 26 bit branch address. */
724 HOWTO (R_MIPS_26, /* type */
725 2, /* rightshift */
726 2, /* size (0 = byte, 1 = short, 2 = long) */
727 26, /* bitsize */
728 false, /* pc_relative */
729 0, /* bitpos */
730 complain_overflow_dont, /* complain_on_overflow */
731 /* This needs complex overflow
732 detection, because the upper four
733 bits must match the PC. */
734 bfd_elf_generic_reloc, /* special_function */
735 "R_MIPS_26", /* name */
736 true, /* partial_inplace */
737 0, /* src_mask */
738 0x3ffffff, /* dst_mask */
739 false), /* pcrel_offset */
740
741 /* High 16 bits of symbol value. */
742 HOWTO (R_MIPS_HI16, /* type */
743 0, /* rightshift */
744 2, /* size (0 = byte, 1 = short, 2 = long) */
745 16, /* bitsize */
746 false, /* pc_relative */
747 0, /* bitpos */
748 complain_overflow_dont, /* complain_on_overflow */
749 bfd_elf_generic_reloc, /* special_function */
750 "R_MIPS_HI16", /* name */
751 true, /* partial_inplace */
752 0, /* src_mask */
753 0xffff, /* dst_mask */
754 false), /* pcrel_offset */
755
756 /* Low 16 bits of symbol value. */
757 HOWTO (R_MIPS_LO16, /* type */
758 0, /* rightshift */
759 2, /* size (0 = byte, 1 = short, 2 = long) */
760 16, /* bitsize */
761 false, /* pc_relative */
762 0, /* bitpos */
763 complain_overflow_dont, /* complain_on_overflow */
764 bfd_elf_generic_reloc, /* special_function */
765 "R_MIPS_LO16", /* name */
766 true, /* partial_inplace */
767 0, /* src_mask */
768 0xffff, /* dst_mask */
769 false), /* pcrel_offset */
770
771 /* GP relative reference. */
772 HOWTO (R_MIPS_GPREL16, /* type */
773 0, /* rightshift */
774 2, /* size (0 = byte, 1 = short, 2 = long) */
775 16, /* bitsize */
776 false, /* pc_relative */
777 0, /* bitpos */
778 complain_overflow_signed, /* complain_on_overflow */
779 _bfd_mips_elf_gprel16_reloc, /* special_function */
780 "R_MIPS_GPREL16", /* name */
781 true, /* partial_inplace */
782 0, /* src_mask */
783 0xffff, /* dst_mask */
784 false), /* pcrel_offset */
785
786 /* Reference to literal section. */
787 HOWTO (R_MIPS_LITERAL, /* type */
788 0, /* rightshift */
789 2, /* size (0 = byte, 1 = short, 2 = long) */
790 16, /* bitsize */
791 false, /* pc_relative */
792 0, /* bitpos */
793 complain_overflow_signed, /* complain_on_overflow */
794 _bfd_mips_elf_gprel16_reloc, /* special_function */
795 "R_MIPS_LITERAL", /* name */
796 true, /* partial_inplace */
797 0, /* src_mask */
798 0xffff, /* dst_mask */
799 false), /* pcrel_offset */
800
801 /* Reference to global offset table. */
802 /* FIXME: This is not handled correctly. */
803 HOWTO (R_MIPS_GOT16, /* type */
804 0, /* rightshift */
805 2, /* size (0 = byte, 1 = short, 2 = long) */
806 16, /* bitsize */
807 false, /* pc_relative */
808 0, /* bitpos */
809 complain_overflow_signed, /* complain_on_overflow */
810 bfd_elf_generic_reloc, /* special_function */
811 "R_MIPS_GOT16", /* name */
812 false, /* partial_inplace */
813 0, /* src_mask */
814 0xffff, /* dst_mask */
815 false), /* pcrel_offset */
816
817 /* 16 bit PC relative reference. */
818 HOWTO (R_MIPS_PC16, /* type */
819 0, /* rightshift */
820 2, /* size (0 = byte, 1 = short, 2 = long) */
821 16, /* bitsize */
822 true, /* pc_relative */
823 0, /* bitpos */
824 complain_overflow_signed, /* complain_on_overflow */
825 bfd_elf_generic_reloc, /* special_function */
826 "R_MIPS_PC16", /* name */
827 true, /* partial_inplace */
828 0, /* src_mask */
829 0xffff, /* dst_mask */
830 false), /* pcrel_offset */
831
832 /* 16 bit call through global offset table. */
833 /* FIXME: This is not handled correctly. */
834 HOWTO (R_MIPS_CALL16, /* type */
835 0, /* rightshift */
836 2, /* size (0 = byte, 1 = short, 2 = long) */
837 16, /* bitsize */
838 false, /* pc_relative */
839 0, /* bitpos */
840 complain_overflow_signed, /* complain_on_overflow */
841 bfd_elf_generic_reloc, /* special_function */
842 "R_MIPS_CALL16", /* name */
843 false, /* partial_inplace */
844 0, /* src_mask */
845 0xffff, /* dst_mask */
846 false), /* pcrel_offset */
847
848 /* 32 bit GP relative reference. */
849 HOWTO (R_MIPS_GPREL32, /* type */
850 0, /* rightshift */
851 2, /* size (0 = byte, 1 = short, 2 = long) */
852 32, /* bitsize */
853 false, /* pc_relative */
854 0, /* bitpos */
855 complain_overflow_bitfield, /* complain_on_overflow */
856 _bfd_mips_elf_gprel32_reloc, /* special_function */
857 "R_MIPS_GPREL32", /* name */
858 true, /* partial_inplace */
859 0, /* src_mask */
860 0xffffffff, /* dst_mask */
861 false), /* pcrel_offset */
862
863 { 13 },
864 { 14 },
865 { 15 },
866
867 /* A 5 bit shift field. */
868 HOWTO (R_MIPS_SHIFT5, /* type */
869 0, /* rightshift */
870 2, /* size (0 = byte, 1 = short, 2 = long) */
871 5, /* bitsize */
872 false, /* pc_relative */
873 6, /* bitpos */
874 complain_overflow_bitfield, /* complain_on_overflow */
875 bfd_elf_generic_reloc, /* special_function */
876 "R_MIPS_SHIFT5", /* name */
877 true, /* partial_inplace */
878 0, /* src_mask */
879 0x000007c0, /* dst_mask */
880 false), /* pcrel_offset */
881
882 /* A 6 bit shift field. */
883 /* FIXME: This is not handled correctly; a special function is
884 needed to put the most significant bit in the right place. */
885 HOWTO (R_MIPS_SHIFT6, /* type */
886 0, /* rightshift */
887 2, /* size (0 = byte, 1 = short, 2 = long) */
888 6, /* bitsize */
889 false, /* pc_relative */
890 6, /* bitpos */
891 complain_overflow_bitfield, /* complain_on_overflow */
892 bfd_elf_generic_reloc, /* special_function */
893 "R_MIPS_SHIFT6", /* name */
894 true, /* partial_inplace */
895 0, /* src_mask */
896 0x000007c4, /* dst_mask */
897 false), /* pcrel_offset */
898
899 /* 64 bit relocation. */
900 HOWTO (R_MIPS_64, /* type */
901 0, /* rightshift */
902 4, /* size (0 = byte, 1 = short, 2 = long) */
903 64, /* bitsize */
904 false, /* pc_relative */
905 0, /* bitpos */
906 complain_overflow_bitfield, /* complain_on_overflow */
907 bfd_elf_generic_reloc, /* special_function */
908 "R_MIPS_64", /* name */
909 true, /* partial_inplace */
910 0, /* src_mask */
911 MINUS_ONE, /* dst_mask */
912 false), /* pcrel_offset */
913
914 /* Displacement in the global offset table. */
915 /* FIXME: Not handled correctly. */
916 HOWTO (R_MIPS_GOT_DISP, /* type */
917 0, /* rightshift */
918 2, /* size (0 = byte, 1 = short, 2 = long) */
919 16, /* bitsize */
920 false, /* pc_relative */
921 0, /* bitpos */
922 complain_overflow_bitfield, /* complain_on_overflow */
923 bfd_elf_generic_reloc, /* special_function */
924 "R_MIPS_GOT_DISP", /* name */
925 true, /* partial_inplace */
926 0, /* src_mask */
927 0x0000ffff, /* dst_mask */
928 false), /* pcrel_offset */
929
930 /* Displacement to page pointer in the global offset table. */
931 /* FIXME: Not handled correctly. */
932 HOWTO (R_MIPS_GOT_PAGE, /* type */
933 0, /* rightshift */
934 2, /* size (0 = byte, 1 = short, 2 = long) */
935 16, /* bitsize */
936 false, /* pc_relative */
937 0, /* bitpos */
938 complain_overflow_bitfield, /* complain_on_overflow */
939 bfd_elf_generic_reloc, /* special_function */
940 "R_MIPS_GOT_PAGE", /* name */
941 true, /* partial_inplace */
942 0, /* src_mask */
943 0x0000ffff, /* dst_mask */
944 false), /* pcrel_offset */
945
946 /* Offset from page pointer in the global offset table. */
947 /* FIXME: Not handled correctly. */
948 HOWTO (R_MIPS_GOT_OFST, /* type */
949 0, /* rightshift */
950 2, /* size (0 = byte, 1 = short, 2 = long) */
951 16, /* bitsize */
952 false, /* pc_relative */
953 0, /* bitpos */
954 complain_overflow_bitfield, /* complain_on_overflow */
955 bfd_elf_generic_reloc, /* special_function */
956 "R_MIPS_GOT_OFST", /* name */
957 true, /* partial_inplace */
958 0, /* src_mask */
959 0x0000ffff, /* dst_mask */
960 false), /* pcrel_offset */
961
962 /* High 16 bits of displacement in global offset table. */
963 /* FIXME: Not handled correctly. */
964 HOWTO (R_MIPS_GOT_HI16, /* type */
965 0, /* rightshift */
966 2, /* size (0 = byte, 1 = short, 2 = long) */
967 16, /* bitsize */
968 false, /* pc_relative */
969 0, /* bitpos */
970 complain_overflow_dont, /* complain_on_overflow */
971 bfd_elf_generic_reloc, /* special_function */
972 "R_MIPS_GOT_HI16", /* name */
973 true, /* partial_inplace */
974 0, /* src_mask */
975 0x0000ffff, /* dst_mask */
976 false), /* pcrel_offset */
977
978 /* Low 16 bits of displacement in global offset table. */
979 /* FIXME: Not handled correctly. */
980 HOWTO (R_MIPS_GOT_LO16, /* type */
981 0, /* rightshift */
982 2, /* size (0 = byte, 1 = short, 2 = long) */
983 16, /* bitsize */
984 false, /* pc_relative */
985 0, /* bitpos */
986 complain_overflow_dont, /* complain_on_overflow */
987 bfd_elf_generic_reloc, /* special_function */
988 "R_MIPS_GOT_LO16", /* name */
989 true, /* partial_inplace */
990 0, /* src_mask */
991 0x0000ffff, /* dst_mask */
992 false), /* pcrel_offset */
993
994 /* 64 bit substraction. */
995 /* FIXME: Not handled correctly. */
996 HOWTO (R_MIPS_SUB, /* type */
997 0, /* rightshift */
998 4, /* size (0 = byte, 1 = short, 2 = long) */
999 64, /* bitsize */
1000 false, /* pc_relative */
1001 0, /* bitpos */
1002 complain_overflow_bitfield, /* complain_on_overflow */
1003 bfd_elf_generic_reloc, /* special_function */
1004 "R_MIPS_SUB", /* name */
1005 true, /* partial_inplace */
1006 0, /* src_mask */
1007 MINUS_ONE, /* dst_mask */
1008 false), /* pcrel_offset */
1009
1010 /* Insert the addend as an instruction. */
1011 /* FIXME: Not handled correctly. */
1012 HOWTO (R_MIPS_INSERT_A, /* type */
1013 0, /* rightshift */
1014 0, /* size (0 = byte, 1 = short, 2 = long) */
1015 0, /* bitsize */
1016 false, /* pc_relative */
1017 0, /* bitpos */
1018 complain_overflow_dont, /* complain_on_overflow */
1019 bfd_elf_generic_reloc, /* special_function */
1020 "R_MIPS_INSERT_A", /* name */
1021 false, /* partial_inplace */
1022 0, /* src_mask */
1023 0, /* dst_mask */
1024 false), /* pcrel_offset */
1025
1026 /* Insert the addend as an instruction, and change all relocations
1027 to refer to the old instruction at the address. */
1028 /* FIXME: Not handled correctly. */
1029 HOWTO (R_MIPS_INSERT_B, /* type */
1030 0, /* rightshift */
1031 0, /* size (0 = byte, 1 = short, 2 = long) */
1032 0, /* bitsize */
1033 false, /* pc_relative */
1034 0, /* bitpos */
1035 complain_overflow_dont, /* complain_on_overflow */
1036 bfd_elf_generic_reloc, /* special_function */
1037 "R_MIPS_INSERT_B", /* name */
1038 false, /* partial_inplace */
1039 0, /* src_mask */
1040 0, /* dst_mask */
1041 false), /* pcrel_offset */
1042
1043 /* Delete a 32 bit instruction. */
1044 /* FIXME: Not handled correctly. */
1045 HOWTO (R_MIPS_DELETE, /* type */
1046 0, /* rightshift */
1047 0, /* size (0 = byte, 1 = short, 2 = long) */
1048 0, /* bitsize */
1049 false, /* pc_relative */
1050 0, /* bitpos */
1051 complain_overflow_dont, /* complain_on_overflow */
1052 bfd_elf_generic_reloc, /* special_function */
1053 "R_MIPS_DELETE", /* name */
1054 false, /* partial_inplace */
1055 0, /* src_mask */
1056 0, /* dst_mask */
1057 false), /* pcrel_offset */
1058
1059 /* Get the higher value of a 64 bit addend. */
1060 /* FIXME: Not handled correctly. */
1061 HOWTO (R_MIPS_HIGHER, /* type */
1062 0, /* rightshift */
1063 2, /* size (0 = byte, 1 = short, 2 = long) */
1064 16, /* bitsize */
1065 false, /* pc_relative */
1066 0, /* bitpos */
1067 complain_overflow_dont, /* complain_on_overflow */
1068 bfd_elf_generic_reloc, /* special_function */
1069 "R_MIPS_HIGHER", /* name */
1070 true, /* partial_inplace */
1071 0, /* src_mask */
1072 0xffff, /* dst_mask */
1073 false), /* pcrel_offset */
1074
1075 /* Get the highest value of a 64 bit addend. */
1076 /* FIXME: Not handled correctly. */
1077 HOWTO (R_MIPS_HIGHEST, /* type */
1078 0, /* rightshift */
1079 2, /* size (0 = byte, 1 = short, 2 = long) */
1080 16, /* bitsize */
1081 false, /* pc_relative */
1082 0, /* bitpos */
1083 complain_overflow_dont, /* complain_on_overflow */
1084 bfd_elf_generic_reloc, /* special_function */
1085 "R_MIPS_HIGHEST", /* name */
1086 true, /* partial_inplace */
1087 0, /* src_mask */
1088 0xffff, /* dst_mask */
1089 false), /* pcrel_offset */
1090
1091 /* High 16 bits of displacement in global offset table. */
1092 /* FIXME: Not handled correctly. */
1093 HOWTO (R_MIPS_CALL_HI16, /* type */
1094 0, /* rightshift */
1095 2, /* size (0 = byte, 1 = short, 2 = long) */
1096 16, /* bitsize */
1097 false, /* pc_relative */
1098 0, /* bitpos */
1099 complain_overflow_dont, /* complain_on_overflow */
1100 bfd_elf_generic_reloc, /* special_function */
1101 "R_MIPS_CALL_HI16", /* name */
1102 true, /* partial_inplace */
1103 0, /* src_mask */
1104 0x0000ffff, /* dst_mask */
1105 false), /* pcrel_offset */
1106
1107 /* Low 16 bits of displacement in global offset table. */
1108 /* FIXME: Not handled correctly. */
1109 HOWTO (R_MIPS_CALL_LO16, /* type */
1110 0, /* rightshift */
1111 2, /* size (0 = byte, 1 = short, 2 = long) */
1112 16, /* bitsize */
1113 false, /* pc_relative */
1114 0, /* bitpos */
1115 complain_overflow_dont, /* complain_on_overflow */
1116 bfd_elf_generic_reloc, /* special_function */
1117 "R_MIPS_CALL_LO16", /* name */
1118 true, /* partial_inplace */
1119 0, /* src_mask */
1120 0x0000ffff, /* dst_mask */
1121 false), /* pcrel_offset */
1122
1123 /* I'm not sure what the remaining relocs are, but they are defined
1124 on Irix 6. */
1125
1126 HOWTO (R_MIPS_SCN_DISP, /* type */
1127 0, /* rightshift */
1128 0, /* size (0 = byte, 1 = short, 2 = long) */
1129 0, /* bitsize */
1130 false, /* pc_relative */
1131 0, /* bitpos */
1132 complain_overflow_dont, /* complain_on_overflow */
1133 bfd_elf_generic_reloc, /* special_function */
1134 "R_MIPS_SCN_DISP", /* name */
1135 false, /* partial_inplace */
1136 0, /* src_mask */
1137 0, /* dst_mask */
1138 false), /* pcrel_offset */
1139
1140 HOWTO (R_MIPS_REL16, /* type */
1141 0, /* rightshift */
1142 0, /* size (0 = byte, 1 = short, 2 = long) */
1143 0, /* bitsize */
1144 false, /* pc_relative */
1145 0, /* bitpos */
1146 complain_overflow_dont, /* complain_on_overflow */
1147 bfd_elf_generic_reloc, /* special_function */
1148 "R_MIPS_REL16", /* name */
1149 false, /* partial_inplace */
1150 0, /* src_mask */
1151 0, /* dst_mask */
1152 false), /* pcrel_offset */
1153
1154 HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
1155 0, /* rightshift */
1156 0, /* size (0 = byte, 1 = short, 2 = long) */
1157 0, /* bitsize */
1158 false, /* pc_relative */
1159 0, /* bitpos */
1160 complain_overflow_dont, /* complain_on_overflow */
1161 bfd_elf_generic_reloc, /* special_function */
1162 "R_MIPS_ADD_IMMEDIATE", /* name */
1163 false, /* partial_inplace */
1164 0, /* src_mask */
1165 0, /* dst_mask */
1166 false), /* pcrel_offset */
1167
1168 HOWTO (R_MIPS_PJUMP, /* type */
1169 0, /* rightshift */
1170 0, /* size (0 = byte, 1 = short, 2 = long) */
1171 0, /* bitsize */
1172 false, /* pc_relative */
1173 0, /* bitpos */
1174 complain_overflow_dont, /* complain_on_overflow */
1175 bfd_elf_generic_reloc, /* special_function */
1176 "R_MIPS_PJUMP", /* name */
1177 false, /* partial_inplace */
1178 0, /* src_mask */
1179 0, /* dst_mask */
1180 false), /* pcrel_offset */
1181
1182 HOWTO (R_MIPS_RELGOT, /* type */
1183 0, /* rightshift */
1184 0, /* size (0 = byte, 1 = short, 2 = long) */
1185 0, /* bitsize */
1186 false, /* pc_relative */
1187 0, /* bitpos */
1188 complain_overflow_dont, /* complain_on_overflow */
1189 bfd_elf_generic_reloc, /* special_function */
1190 "R_MIPS_RELGOT", /* name */
1191 false, /* partial_inplace */
1192 0, /* src_mask */
1193 0, /* dst_mask */
1194 false) /* pcrel_offset */
1195 };
1196
1197 /* Swap in a MIPS 64-bit Rel reloc. */
1198
1199 static void
1200 mips_elf64_swap_reloc_in (abfd, src, dst)
1201 bfd *abfd;
1202 const Elf64_Mips_External_Rel *src;
1203 Elf64_Mips_Internal_Rel *dst;
1204 {
1205 dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
1206 dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
1207 dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
1208 dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
1209 dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
1210 dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
1211 }
1212
1213 /* Swap in a MIPS 64-bit Rela reloc. */
1214
1215 static void
1216 mips_elf64_swap_reloca_in (abfd, src, dst)
1217 bfd *abfd;
1218 const Elf64_Mips_External_Rela *src;
1219 Elf64_Mips_Internal_Rela *dst;
1220 {
1221 dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
1222 dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
1223 dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
1224 dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
1225 dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
1226 dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
1227 dst->r_addend = bfd_h_get_64 (abfd, (bfd_byte *) src->r_addend);
1228 }
1229
1230 #if 0
1231
1232 /* This is not currently used. */
1233
1234 /* Swap out a MIPS 64-bit Rel reloc. */
1235
1236 static void
1237 mips_elf64_swap_reloc_out (abfd, src, dst)
1238 bfd *abfd;
1239 const Elf64_Mips_Internal_Rel *src;
1240 Elf64_Mips_External_Rel *dst;
1241 {
1242 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1243 bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
1244 bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
1245 bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
1246 bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
1247 bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
1248 }
1249
1250 #endif /* 0 */
1251
1252 /* Swap out a MIPS 64-bit Rela reloc. */
1253
1254 static void
1255 mips_elf64_swap_reloca_out (abfd, src, dst)
1256 bfd *abfd;
1257 const Elf64_Mips_Internal_Rela *src;
1258 Elf64_Mips_External_Rela *dst;
1259 {
1260 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1261 bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
1262 bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
1263 bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
1264 bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
1265 bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
1266 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1267 }
1268
1269 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1270
1271 struct elf_reloc_map
1272 {
1273 bfd_reloc_code_real_type bfd_reloc_val;
1274 enum mips_elf64_reloc_type elf_reloc_val;
1275 };
1276
1277 static CONST struct elf_reloc_map mips_reloc_map[] =
1278 {
1279 { BFD_RELOC_NONE, R_MIPS_NONE, },
1280 { BFD_RELOC_16, R_MIPS_16 },
1281 { BFD_RELOC_32, R_MIPS_32 },
1282 { BFD_RELOC_64, R_MIPS_64 },
1283 { BFD_RELOC_CTOR, R_MIPS_64 },
1284 { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
1285 { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
1286 { BFD_RELOC_HI16_S, R_MIPS_HI16 },
1287 { BFD_RELOC_LO16, R_MIPS_LO16 },
1288 { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 },
1289 { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
1290 { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
1291 { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
1292 { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
1293 { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 },
1294 { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
1295 { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
1296 { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
1297 { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }
1298 };
1299
1300 /* Given a BFD reloc type, return a howto structure. */
1301
1302 static reloc_howto_type *
1303 mips_elf64_reloc_type_lookup (abfd, code)
1304 bfd *abfd;
1305 bfd_reloc_code_real_type code;
1306 {
1307 unsigned int i;
1308
1309 for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
1310 {
1311 if (mips_reloc_map[i].bfd_reloc_val == code)
1312 {
1313 int v;
1314
1315 v = (int) mips_reloc_map[i].elf_reloc_val;
1316 return &mips_elf64_howto_table_rel[v];
1317 }
1318 }
1319
1320 return NULL;
1321 }
1322
1323 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1324 to three relocs, we must tell the user to allocate more space. */
1325
1326 static long
1327 mips_elf64_get_reloc_upper_bound (abfd, sec)
1328 bfd *abfd;
1329 asection *sec;
1330 {
1331 return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
1332 }
1333
1334 /* Read the relocations from one reloc section. */
1335
1336 static boolean
1337 mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
1338 bfd *abfd;
1339 asection *asect;
1340 asymbol **symbols;
1341 const Elf_Internal_Shdr *rel_hdr;
1342 {
1343 PTR allocated = NULL;
1344 bfd_byte *native_relocs;
1345 arelent *relents;
1346 arelent *relent;
1347 unsigned int count;
1348 unsigned int i;
1349 int entsize;
1350 reloc_howto_type *howto_table;
1351
1352 allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
1353 if (allocated == NULL)
1354 goto error_return;
1355
1356 if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
1357 || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
1358 goto error_return;
1359
1360 native_relocs = (bfd_byte *) allocated;
1361
1362 relents = asect->relocation + asect->reloc_count;
1363
1364 entsize = rel_hdr->sh_entsize;
1365 BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
1366 || entsize == sizeof (Elf64_Mips_External_Rela));
1367
1368 count = rel_hdr->sh_size / entsize;
1369
1370 if (entsize == sizeof (Elf64_Mips_External_Rel))
1371 howto_table = mips_elf64_howto_table_rel;
1372 else
1373 howto_table = mips_elf64_howto_table_rela;
1374
1375 relent = relents;
1376 for (i = 0; i < count; i++, native_relocs += entsize)
1377 {
1378 Elf64_Mips_Internal_Rela rela;
1379 boolean used_sym, used_ssym;
1380 int ir;
1381
1382 if (entsize == sizeof (Elf64_Mips_External_Rela))
1383 mips_elf64_swap_reloca_in (abfd,
1384 (Elf64_Mips_External_Rela *) native_relocs,
1385 &rela);
1386 else
1387 {
1388 Elf64_Mips_Internal_Rel rel;
1389
1390 mips_elf64_swap_reloc_in (abfd,
1391 (Elf64_Mips_External_Rel *) native_relocs,
1392 &rel);
1393 rela.r_offset = rel.r_offset;
1394 rela.r_sym = rel.r_sym;
1395 rela.r_ssym = rel.r_ssym;
1396 rela.r_type3 = rel.r_type3;
1397 rela.r_type2 = rel.r_type2;
1398 rela.r_type = rel.r_type;
1399 rela.r_addend = 0;
1400 }
1401
1402 /* Each entry represents up to three actual relocations. */
1403
1404 used_sym = false;
1405 used_ssym = false;
1406 for (ir = 0; ir < 3; ir++)
1407 {
1408 enum mips_elf64_reloc_type type;
1409
1410 switch (ir)
1411 {
1412 default:
1413 abort ();
1414 case 0:
1415 type = (enum mips_elf64_reloc_type) rela.r_type;
1416 break;
1417 case 1:
1418 type = (enum mips_elf64_reloc_type) rela.r_type2;
1419 break;
1420 case 2:
1421 type = (enum mips_elf64_reloc_type) rela.r_type3;
1422 break;
1423 }
1424
1425 if (type == R_MIPS_NONE)
1426 {
1427 /* There are no more relocations in this entry. If this
1428 is the first entry, we need to generate a dummy
1429 relocation so that the generic linker knows that
1430 there has been a break in the sequence of relocations
1431 applying to a particular address. */
1432 if (ir == 0)
1433 {
1434 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1435 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1436 relent->address = rela.r_offset;
1437 else
1438 relent->address = rela.r_offset - asect->vma;
1439 relent->addend = 0;
1440 relent->howto = &howto_table[(int) R_MIPS_NONE];
1441 ++relent;
1442 }
1443 break;
1444 }
1445
1446 /* Some types require symbols, whereas some do not. */
1447 switch (type)
1448 {
1449 case R_MIPS_NONE:
1450 case R_MIPS_LITERAL:
1451 case R_MIPS_INSERT_A:
1452 case R_MIPS_INSERT_B:
1453 case R_MIPS_DELETE:
1454 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1455 break;
1456
1457 default:
1458 if (! used_sym)
1459 {
1460 if (rela.r_sym == 0)
1461 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1462 else
1463 {
1464 asymbol **ps, *s;
1465
1466 ps = symbols + rela.r_sym - 1;
1467 s = *ps;
1468 if ((s->flags & BSF_SECTION_SYM) == 0)
1469 relent->sym_ptr_ptr = ps;
1470 else
1471 relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
1472 }
1473
1474 used_sym = true;
1475 }
1476 else if (! used_ssym)
1477 {
1478 switch (rela.r_ssym)
1479 {
1480 case RSS_UNDEF:
1481 relent->sym_ptr_ptr =
1482 bfd_abs_section_ptr->symbol_ptr_ptr;
1483 break;
1484
1485 case RSS_GP:
1486 case RSS_GP0:
1487 case RSS_LOC:
1488 /* FIXME: I think these need to be handled using
1489 special howto structures. */
1490 BFD_ASSERT (0);
1491 break;
1492
1493 default:
1494 BFD_ASSERT (0);
1495 break;
1496 }
1497
1498 used_ssym = true;
1499 }
1500 else
1501 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1502
1503 break;
1504 }
1505
1506 /* The address of an ELF reloc is section relative for an
1507 object file, and absolute for an executable file or
1508 shared library. The address of a BFD reloc is always
1509 section relative. */
1510 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1511 relent->address = rela.r_offset;
1512 else
1513 relent->address = rela.r_offset - asect->vma;
1514
1515 relent->addend = rela.r_addend;
1516
1517 relent->howto = &howto_table[(int) type];
1518
1519 ++relent;
1520 }
1521 }
1522
1523 asect->reloc_count += relent - relents;
1524
1525 if (allocated != NULL)
1526 free (allocated);
1527
1528 return true;
1529
1530 error_return:
1531 if (allocated != NULL)
1532 free (allocated);
1533 return false;
1534 }
1535
1536 /* Read the relocations. On Irix 6, there can be two reloc sections
1537 associated with a single data section. */
1538
1539 static boolean
1540 mips_elf64_slurp_reloc_table (abfd, asect, symbols)
1541 bfd *abfd;
1542 asection *asect;
1543 asymbol **symbols;
1544 {
1545 struct bfd_elf_section_data * const d = elf_section_data (asect);
1546
1547 if (asect->relocation != NULL
1548 || (asect->flags & SEC_RELOC) == 0
1549 || asect->reloc_count == 0)
1550 return true;
1551
1552 /* Allocate space for 3 arelent structures for each Rel structure. */
1553 asect->relocation = ((arelent *)
1554 bfd_alloc (abfd,
1555 asect->reloc_count * 3 * sizeof (arelent)));
1556 if (asect->relocation == NULL)
1557 return false;
1558
1559 /* The slurp_one_reloc_table routine increments reloc_count. */
1560 asect->reloc_count = 0;
1561
1562 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
1563 return false;
1564 if (d->rel_hdr2 != NULL)
1565 {
1566 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
1567 d->rel_hdr2))
1568 return false;
1569 }
1570
1571 return true;
1572 }
1573
1574 /* Write out the relocations. */
1575
1576 static void
1577 mips_elf64_write_relocs (abfd, sec, data)
1578 bfd *abfd;
1579 asection *sec;
1580 PTR data;
1581 {
1582 boolean *failedp = (boolean *) data;
1583 unsigned int count;
1584 Elf_Internal_Shdr *rela_hdr;
1585 Elf64_Mips_External_Rela *ext_rela;
1586 unsigned int idx;
1587 asymbol *last_sym = 0;
1588 int last_sym_idx = 0;
1589
1590 /* If we have already failed, don't do anything. */
1591 if (*failedp)
1592 return;
1593
1594 if ((sec->flags & SEC_RELOC) == 0)
1595 return;
1596
1597 /* The linker backend writes the relocs out itself, and sets the
1598 reloc_count field to zero to inhibit writing them here. Also,
1599 sometimes the SEC_RELOC flag gets set even when there aren't any
1600 relocs. */
1601 if (sec->reloc_count == 0)
1602 return;
1603
1604 /* We can combine up to three relocs that refer to the same address
1605 if the latter relocs have no associated symbol. */
1606 count = 0;
1607 for (idx = 0; idx < sec->reloc_count; idx++)
1608 {
1609 bfd_vma addr;
1610 unsigned int i;
1611
1612 ++count;
1613
1614 addr = sec->orelocation[idx]->address;
1615 for (i = 0; i < 2; i++)
1616 {
1617 arelent *r;
1618
1619 if (idx + 1 >= sec->reloc_count)
1620 break;
1621 r = sec->orelocation[idx + 1];
1622 if (r->address != addr
1623 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
1624 || (*r->sym_ptr_ptr)->value != 0)
1625 break;
1626
1627 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1628
1629 ++idx;
1630 }
1631 }
1632
1633 rela_hdr = &elf_section_data (sec)->rel_hdr;
1634
1635 rela_hdr->sh_size = rela_hdr->sh_entsize * count;
1636 rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
1637 if (rela_hdr->contents == NULL)
1638 {
1639 *failedp = true;
1640 return;
1641 }
1642
1643 ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
1644 for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
1645 {
1646 arelent *ptr;
1647 Elf64_Mips_Internal_Rela int_rela;
1648 asymbol *sym;
1649 int n;
1650 unsigned int i;
1651
1652 ptr = sec->orelocation[idx];
1653
1654 /* The address of an ELF reloc is section relative for an object
1655 file, and absolute for an executable file or shared library.
1656 The address of a BFD reloc is always section relative. */
1657 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1658 int_rela.r_offset = ptr->address;
1659 else
1660 int_rela.r_offset = ptr->address + sec->vma;
1661
1662 sym = *ptr->sym_ptr_ptr;
1663 if (sym == last_sym)
1664 n = last_sym_idx;
1665 else
1666 {
1667 last_sym = sym;
1668 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
1669 if (n < 0)
1670 {
1671 *failedp = true;
1672 return;
1673 }
1674 last_sym_idx = n;
1675 }
1676
1677 int_rela.r_sym = n;
1678
1679 int_rela.r_addend = ptr->addend;
1680
1681 int_rela.r_ssym = RSS_UNDEF;
1682
1683 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
1684 && ! _bfd_elf_validate_reloc (abfd, ptr))
1685 {
1686 *failedp = true;
1687 return;
1688 }
1689
1690 int_rela.r_type = ptr->howto->type;
1691 int_rela.r_type2 = (int) R_MIPS_NONE;
1692 int_rela.r_type3 = (int) R_MIPS_NONE;
1693
1694 for (i = 0; i < 2; i++)
1695 {
1696 arelent *r;
1697
1698 if (idx + 1 >= sec->reloc_count)
1699 break;
1700 r = sec->orelocation[idx + 1];
1701 if (r->address != ptr->address
1702 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
1703 || (*r->sym_ptr_ptr)->value != 0)
1704 break;
1705
1706 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1707
1708 if (i == 0)
1709 int_rela.r_type2 = r->howto->type;
1710 else
1711 int_rela.r_type3 = r->howto->type;
1712
1713 ++idx;
1714 }
1715
1716 mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
1717 }
1718
1719 BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
1720 == count);
1721 }
1722 \f
1723 /* The .MIPS.options section holds register information in an
1724 Elf64_Reginfo structure. These routines swap them in and out.
1725 They are globally visible because they are used outside of BFD. */
1726
1727 void
1728 bfd_mips_elf64_swap_reginfo_in (abfd, ex, in)
1729 bfd *abfd;
1730 const Elf64_External_RegInfo *ex;
1731 Elf64_Internal_RegInfo *in;
1732 {
1733 in->ri_gprmask = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_gprmask);
1734 in->ri_pad = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_pad);
1735 in->ri_cprmask[0] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[0]);
1736 in->ri_cprmask[1] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[1]);
1737 in->ri_cprmask[2] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[2]);
1738 in->ri_cprmask[3] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[3]);
1739 in->ri_gp_value = bfd_h_get_64 (abfd, (bfd_byte *) ex->ri_gp_value);
1740 }
1741
1742 void
1743 bfd_mips_elf64_swap_reginfo_out (abfd, in, ex)
1744 bfd *abfd;
1745 const Elf64_Internal_RegInfo *in;
1746 Elf64_External_RegInfo *ex;
1747 {
1748 bfd_h_put_32 (abfd, (bfd_vma) in->ri_gprmask,
1749 (bfd_byte *) ex->ri_gprmask);
1750 bfd_h_put_32 (abfd, (bfd_vma) in->ri_pad,
1751 (bfd_byte *) ex->ri_pad);
1752 bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[0],
1753 (bfd_byte *) ex->ri_cprmask[0]);
1754 bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[1],
1755 (bfd_byte *) ex->ri_cprmask[1]);
1756 bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[2],
1757 (bfd_byte *) ex->ri_cprmask[2]);
1758 bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[3],
1759 (bfd_byte *) ex->ri_cprmask[3]);
1760 bfd_h_put_64 (abfd, (bfd_vma) in->ri_gp_value,
1761 (bfd_byte *) ex->ri_gp_value);
1762 }
1763
1764 /* Handle a 64-bit MIPS ELF specific section. */
1765
1766 static boolean
1767 mips_elf64_section_from_shdr (abfd, hdr, name)
1768 bfd *abfd;
1769 Elf_Internal_Shdr *hdr;
1770 char *name;
1771 {
1772 if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
1773 return false;
1774
1775 /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
1776 set the gp value based on what we find. We may see both
1777 SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
1778 they should agree. */
1779 if (hdr->sh_type == SHT_MIPS_OPTIONS)
1780 {
1781 bfd_byte *contents, *l, *lend;
1782
1783 contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
1784 if (contents == NULL)
1785 return false;
1786 if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
1787 (file_ptr) 0, hdr->sh_size))
1788 {
1789 free (contents);
1790 return false;
1791 }
1792 l = contents;
1793 lend = contents + hdr->sh_size;
1794 while (l + sizeof (Elf_External_Options) <= lend)
1795 {
1796 Elf_Internal_Options intopt;
1797
1798 bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
1799 &intopt);
1800 if (intopt.kind == ODK_REGINFO)
1801 {
1802 Elf64_Internal_RegInfo intreg;
1803
1804 bfd_mips_elf64_swap_reginfo_in
1805 (abfd,
1806 ((Elf64_External_RegInfo *)
1807 (l + sizeof (Elf_External_Options))),
1808 &intreg);
1809 elf_gp (abfd) = intreg.ri_gp_value;
1810 }
1811 l += intopt.size;
1812 }
1813 free (contents);
1814 }
1815
1816 return true;
1817 }
1818
1819 /* Work over a section just before writing it out. We update the GP
1820 value in the SHT_MIPS_OPTIONS section based on the value we are
1821 using. */
1822
1823 static boolean
1824 mips_elf64_section_processing (abfd, hdr)
1825 bfd *abfd;
1826 Elf_Internal_Shdr *hdr;
1827 {
1828 if (hdr->sh_type == SHT_MIPS_OPTIONS
1829 && hdr->bfd_section != NULL
1830 && elf_section_data (hdr->bfd_section) != NULL
1831 && elf_section_data (hdr->bfd_section)->tdata != NULL)
1832 {
1833 bfd_byte *contents, *l, *lend;
1834
1835 /* We stored the section contents in the elf_section_data tdata
1836 field in the set_section_contents routine. We save the
1837 section contents so that we don't have to read them again.
1838 At this point we know that elf_gp is set, so we can look
1839 through the section contents to see if there is an
1840 ODK_REGINFO structure. */
1841
1842 contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
1843 l = contents;
1844 lend = contents + hdr->sh_size;
1845 while (l + sizeof (Elf_External_Options) <= lend)
1846 {
1847 Elf_Internal_Options intopt;
1848
1849 bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
1850 &intopt);
1851 if (intopt.kind == ODK_REGINFO)
1852 {
1853 bfd_byte buf[8];
1854
1855 if (bfd_seek (abfd,
1856 (hdr->sh_offset
1857 + (l - contents)
1858 + sizeof (Elf_External_Options)
1859 + (sizeof (Elf64_External_RegInfo) - 8)),
1860 SEEK_SET) == -1)
1861 return false;
1862 bfd_h_put_64 (abfd, elf_gp (abfd), buf);
1863 if (bfd_write (buf, 1, 8, abfd) != 8)
1864 return false;
1865 }
1866 l += intopt.size;
1867 }
1868 }
1869
1870 return _bfd_mips_elf_section_processing (abfd, hdr);
1871 }
1872 \f
1873 /* ECOFF swapping routines. These are used when dealing with the
1874 .mdebug section, which is in the ECOFF debugging format. */
1875 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
1876 {
1877 /* Symbol table magic number. */
1878 magicSym2,
1879 /* Alignment of debugging information. E.g., 4. */
1880 8,
1881 /* Sizes of external symbolic information. */
1882 sizeof (struct hdr_ext),
1883 sizeof (struct dnr_ext),
1884 sizeof (struct pdr_ext),
1885 sizeof (struct sym_ext),
1886 sizeof (struct opt_ext),
1887 sizeof (struct fdr_ext),
1888 sizeof (struct rfd_ext),
1889 sizeof (struct ext_ext),
1890 /* Functions to swap in external symbolic data. */
1891 ecoff_swap_hdr_in,
1892 ecoff_swap_dnr_in,
1893 ecoff_swap_pdr_in,
1894 ecoff_swap_sym_in,
1895 ecoff_swap_opt_in,
1896 ecoff_swap_fdr_in,
1897 ecoff_swap_rfd_in,
1898 ecoff_swap_ext_in,
1899 _bfd_ecoff_swap_tir_in,
1900 _bfd_ecoff_swap_rndx_in,
1901 /* Functions to swap out external symbolic data. */
1902 ecoff_swap_hdr_out,
1903 ecoff_swap_dnr_out,
1904 ecoff_swap_pdr_out,
1905 ecoff_swap_sym_out,
1906 ecoff_swap_opt_out,
1907 ecoff_swap_fdr_out,
1908 ecoff_swap_rfd_out,
1909 ecoff_swap_ext_out,
1910 _bfd_ecoff_swap_tir_out,
1911 _bfd_ecoff_swap_rndx_out,
1912 /* Function to read in symbolic data. */
1913 _bfd_mips_elf_read_ecoff_info
1914 };
1915 \f
1916 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
1917 standard ELF. This structure is used to redirect the relocation
1918 handling routines. */
1919
1920 const struct elf_size_info mips_elf64_size_info =
1921 {
1922 sizeof (Elf64_External_Ehdr),
1923 sizeof (Elf64_External_Phdr),
1924 sizeof (Elf64_External_Shdr),
1925 sizeof (Elf64_Mips_External_Rel),
1926 sizeof (Elf64_Mips_External_Rela),
1927 sizeof (Elf64_External_Sym),
1928 sizeof (Elf64_External_Dyn),
1929 sizeof (Elf_External_Note),
1930 64, /* arch_size */
1931 8, /* file_align */
1932 ELFCLASS64,
1933 EV_CURRENT,
1934 bfd_elf64_write_out_phdrs,
1935 bfd_elf64_write_shdrs_and_ehdr,
1936 mips_elf64_write_relocs,
1937 bfd_elf64_swap_symbol_out,
1938 mips_elf64_slurp_reloc_table,
1939 bfd_elf64_slurp_symbol_table,
1940 bfd_elf64_swap_dyn_in
1941 };
1942
1943 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
1944 #define TARGET_LITTLE_NAME "elf64-littlemips"
1945 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
1946 #define TARGET_BIG_NAME "elf64-bigmips"
1947 #define ELF_ARCH bfd_arch_mips
1948 #define ELF_MACHINE_CODE EM_MIPS
1949 #define ELF_MAXPAGESIZE 0x1000
1950 #define elf_backend_size_info mips_elf64_size_info
1951 #define elf_backend_object_p _bfd_mips_elf_object_p
1952 #define elf_backend_section_from_shdr mips_elf64_section_from_shdr
1953 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
1954 #define elf_backend_section_from_bfd_section \
1955 _bfd_mips_elf_section_from_bfd_section
1956 #define elf_backend_section_processing mips_elf64_section_processing
1957 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
1958 #define elf_backend_final_write_processing \
1959 _bfd_mips_elf_final_write_processing
1960 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
1961
1962 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
1963 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
1964 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
1965 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
1966 #define bfd_elf64_bfd_copy_private_bfd_data \
1967 _bfd_mips_elf_copy_private_bfd_data
1968 #define bfd_elf64_bfd_merge_private_bfd_data \
1969 _bfd_mips_elf_merge_private_bfd_data
1970 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
1971
1972 #include "elf64-target.h"
This page took 0.102287 seconds and 5 git commands to generate.