ae444aa36b878a1e0374093e1cce827c35a72cd3
[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 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "bfdlink.h"
25 #include "genlink.h"
26 #include "elf-bfd.h"
27 #include "elf/mips.h"
28
29 /* This file supports the 64-bit MIPS ELF ABI.
30
31 The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
32 overrides the usual ELF reloc handling, and handles reading and
33 writing the relocations here. */
34
35 static void mips_elf64_swap_reloc_in
36 PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
37 Elf64_Mips_Internal_Rel *));
38 static void mips_elf64_swap_reloca_in
39 PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
40 Elf64_Mips_Internal_Rela *));
41 static void mips_elf64_swap_reloc_out
42 PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
43 Elf64_Mips_External_Rel *));
44 static void mips_elf64_swap_reloca_out
45 PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
46 Elf64_Mips_External_Rela *));
47 static reloc_howto_type *mips_elf64_reloc_type_lookup
48 PARAMS ((bfd *, bfd_reloc_code_real_type));
49 static boolean mips_elf64_slurp_one_reloc_table
50 PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
51 static boolean mips_elf64_slurp_reloc_table
52 PARAMS ((bfd *, asection *, asymbol **));
53 static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
54 static boolean mips_elf64_section_from_shdr
55 PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
56
57 /* The relocation types. */
58
59 enum mips_elf64_reloc_type
60 {
61 R_MIPS_NONE = 0,
62 R_MIPS_16 = 1,
63 R_MIPS_32 = 2,
64 R_MIPS_ADD = 2,
65 R_MIPS_REL32 = 3,
66 R_MIPS_REL = 3,
67 R_MIPS_26 = 4,
68 R_MIPS_HI16 = 5,
69 R_MIPS_LO16 = 6,
70 R_MIPS_GPREL16 = 7,
71 R_MIPS_GPREL = 7,
72 R_MIPS_LITERAL = 8,
73 R_MIPS_GOT16 = 9,
74 R_MIPS_GOT = 9,
75 R_MIPS_PC16 = 10,
76 R_MIPS_CALL16 = 11,
77 R_MIPS_CALL = 11,
78 R_MIPS_GPREL32 = 12,
79 R_MIPS_SHIFT5 = 16,
80 R_MIPS_SHIFT6 = 17,
81 R_MIPS_64 = 18,
82 R_MIPS_GOT_DISP = 19,
83 R_MIPS_GOT_PAGE = 20,
84 R_MIPS_GOT_OFST = 21,
85 R_MIPS_GOT_HI16 = 22,
86 R_MIPS_GOT_LO16 = 23,
87 R_MIPS_SUB = 24,
88 R_MIPS_INSERT_A = 25,
89 R_MIPS_INSERT_B = 26,
90 R_MIPS_DELETE = 27,
91 R_MIPS_HIGHER = 28,
92 R_MIPS_HIGHEST = 29,
93 R_MIPS_CALL_HI16 = 30,
94 R_MIPS_CALL_LO16 = 31,
95 R_MIPS_SCN_DISP = 32,
96 R_MIPS_REL16 = 33,
97 R_MIPS_ADD_IMMEDIATE = 34
98 };
99
100 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
101 from smaller values. Start with zero, widen, *then* decrement. */
102 #define MINUS_ONE (((bfd_vma)0) - 1)
103
104 /* FIXME: These need to be rewritten, or we need to use the versions
105 in elf32-mips.c. */
106 #define mips_elf_hi16_reloc bfd_elf_generic_reloc
107 #define mips_elf_lo16_reloc bfd_elf_generic_reloc
108 #define mips_elf_gprel16_reloc bfd_elf_generic_reloc
109 #define mips_elf_got16_reloc bfd_elf_generic_reloc
110 #define mips_elf_gprel32_reloc bfd_elf_generic_reloc
111
112 /* The relocation table used for SHT_REL sections. */
113
114 static reloc_howto_type mips_elf64_howto_table_rel[] =
115 {
116 /* No relocation. */
117 HOWTO (R_MIPS_NONE, /* type */
118 0, /* rightshift */
119 0, /* size (0 = byte, 1 = short, 2 = long) */
120 0, /* bitsize */
121 false, /* pc_relative */
122 0, /* bitpos */
123 complain_overflow_dont, /* complain_on_overflow */
124 bfd_elf_generic_reloc, /* special_function */
125 "R_MIPS_NONE", /* name */
126 false, /* partial_inplace */
127 0, /* src_mask */
128 0, /* dst_mask */
129 false), /* pcrel_offset */
130
131 /* 16 bit relocation. */
132 HOWTO (R_MIPS_16, /* type */
133 0, /* rightshift */
134 1, /* size (0 = byte, 1 = short, 2 = long) */
135 16, /* bitsize */
136 false, /* pc_relative */
137 0, /* bitpos */
138 complain_overflow_bitfield, /* complain_on_overflow */
139 bfd_elf_generic_reloc, /* special_function */
140 "R_MIPS_16", /* name */
141 true, /* partial_inplace */
142 0xffff, /* src_mask */
143 0xffff, /* dst_mask */
144 false), /* pcrel_offset */
145
146 /* 32 bit relocation. */
147 HOWTO (R_MIPS_32, /* type */
148 0, /* rightshift */
149 2, /* size (0 = byte, 1 = short, 2 = long) */
150 32, /* bitsize */
151 false, /* pc_relative */
152 0, /* bitpos */
153 complain_overflow_bitfield, /* complain_on_overflow */
154 bfd_elf_generic_reloc, /* special_function */
155 "R_MIPS_32", /* name */
156 true, /* partial_inplace */
157 0xffffffff, /* src_mask */
158 0xffffffff, /* dst_mask */
159 false), /* pcrel_offset */
160
161 /* 32 bit symbol relative relocation. */
162 HOWTO (R_MIPS_REL32, /* type */
163 0, /* rightshift */
164 2, /* size (0 = byte, 1 = short, 2 = long) */
165 32, /* bitsize */
166 false, /* pc_relative */
167 0, /* bitpos */
168 complain_overflow_bitfield, /* complain_on_overflow */
169 bfd_elf_generic_reloc, /* special_function */
170 "R_MIPS_REL32", /* name */
171 true, /* partial_inplace */
172 0xffffffff, /* src_mask */
173 0xffffffff, /* dst_mask */
174 false), /* pcrel_offset */
175
176 /* 26 bit branch address. */
177 HOWTO (R_MIPS_26, /* type */
178 2, /* rightshift */
179 2, /* size (0 = byte, 1 = short, 2 = long) */
180 26, /* bitsize */
181 false, /* pc_relative */
182 0, /* bitpos */
183 complain_overflow_dont, /* complain_on_overflow */
184 /* This needs complex overflow
185 detection, because the upper four
186 bits must match the PC. */
187 bfd_elf_generic_reloc, /* special_function */
188 "R_MIPS_26", /* name */
189 true, /* partial_inplace */
190 0x3ffffff, /* src_mask */
191 0x3ffffff, /* dst_mask */
192 false), /* pcrel_offset */
193
194 /* High 16 bits of symbol value. */
195 HOWTO (R_MIPS_HI16, /* type */
196 0, /* rightshift */
197 2, /* size (0 = byte, 1 = short, 2 = long) */
198 16, /* bitsize */
199 false, /* pc_relative */
200 0, /* bitpos */
201 complain_overflow_dont, /* complain_on_overflow */
202 mips_elf_hi16_reloc, /* special_function */
203 "R_MIPS_HI16", /* name */
204 true, /* partial_inplace */
205 0xffff, /* src_mask */
206 0xffff, /* dst_mask */
207 false), /* pcrel_offset */
208
209 /* Low 16 bits of symbol value. */
210 HOWTO (R_MIPS_LO16, /* type */
211 0, /* rightshift */
212 2, /* size (0 = byte, 1 = short, 2 = long) */
213 16, /* bitsize */
214 false, /* pc_relative */
215 0, /* bitpos */
216 complain_overflow_dont, /* complain_on_overflow */
217 mips_elf_lo16_reloc, /* special_function */
218 "R_MIPS_LO16", /* name */
219 true, /* partial_inplace */
220 0xffff, /* src_mask */
221 0xffff, /* dst_mask */
222 false), /* pcrel_offset */
223
224 /* GP relative reference. */
225 HOWTO (R_MIPS_GPREL16, /* type */
226 0, /* rightshift */
227 2, /* size (0 = byte, 1 = short, 2 = long) */
228 16, /* bitsize */
229 false, /* pc_relative */
230 0, /* bitpos */
231 complain_overflow_signed, /* complain_on_overflow */
232 mips_elf_gprel16_reloc, /* special_function */
233 "R_MIPS_GPREL16", /* name */
234 true, /* partial_inplace */
235 0xffff, /* src_mask */
236 0xffff, /* dst_mask */
237 false), /* pcrel_offset */
238
239 /* Reference to literal section. */
240 HOWTO (R_MIPS_LITERAL, /* type */
241 0, /* rightshift */
242 2, /* size (0 = byte, 1 = short, 2 = long) */
243 16, /* bitsize */
244 false, /* pc_relative */
245 0, /* bitpos */
246 complain_overflow_signed, /* complain_on_overflow */
247 mips_elf_gprel16_reloc, /* special_function */
248 "R_MIPS_LITERAL", /* name */
249 true, /* partial_inplace */
250 0xffff, /* src_mask */
251 0xffff, /* dst_mask */
252 false), /* pcrel_offset */
253
254 /* Reference to global offset table. */
255 HOWTO (R_MIPS_GOT16, /* type */
256 0, /* rightshift */
257 2, /* size (0 = byte, 1 = short, 2 = long) */
258 16, /* bitsize */
259 false, /* pc_relative */
260 0, /* bitpos */
261 complain_overflow_signed, /* complain_on_overflow */
262 mips_elf_got16_reloc, /* special_function */
263 "R_MIPS_GOT16", /* name */
264 false, /* partial_inplace */
265 0, /* src_mask */
266 0xffff, /* dst_mask */
267 false), /* pcrel_offset */
268
269 /* 16 bit PC relative reference. */
270 HOWTO (R_MIPS_PC16, /* type */
271 0, /* rightshift */
272 2, /* size (0 = byte, 1 = short, 2 = long) */
273 16, /* bitsize */
274 true, /* pc_relative */
275 0, /* bitpos */
276 complain_overflow_signed, /* complain_on_overflow */
277 bfd_elf_generic_reloc, /* special_function */
278 "R_MIPS_PC16", /* name */
279 true, /* partial_inplace */
280 0xffff, /* src_mask */
281 0xffff, /* dst_mask */
282 false), /* pcrel_offset */
283
284 /* 16 bit call through global offset table. */
285 /* FIXME: This is not handled correctly. */
286 HOWTO (R_MIPS_CALL16, /* type */
287 0, /* rightshift */
288 2, /* size (0 = byte, 1 = short, 2 = long) */
289 16, /* bitsize */
290 false, /* pc_relative */
291 0, /* bitpos */
292 complain_overflow_signed, /* complain_on_overflow */
293 bfd_elf_generic_reloc, /* special_function */
294 "R_MIPS_CALL16", /* name */
295 false, /* partial_inplace */
296 0, /* src_mask */
297 0xffff, /* dst_mask */
298 false), /* pcrel_offset */
299
300 /* 32 bit GP relative reference. */
301 HOWTO (R_MIPS_GPREL32, /* type */
302 0, /* rightshift */
303 2, /* size (0 = byte, 1 = short, 2 = long) */
304 32, /* bitsize */
305 false, /* pc_relative */
306 0, /* bitpos */
307 complain_overflow_bitfield, /* complain_on_overflow */
308 mips_elf_gprel32_reloc, /* special_function */
309 "R_MIPS_GPREL32", /* name */
310 true, /* partial_inplace */
311 0xffffffff, /* src_mask */
312 0xffffffff, /* dst_mask */
313 false), /* pcrel_offset */
314
315 { 13 },
316 { 14 },
317 { 15 },
318
319 /* A 5 bit shift field. */
320 HOWTO (R_MIPS_SHIFT5, /* type */
321 0, /* rightshift */
322 2, /* size (0 = byte, 1 = short, 2 = long) */
323 5, /* bitsize */
324 false, /* pc_relative */
325 6, /* bitpos */
326 complain_overflow_bitfield, /* complain_on_overflow */
327 bfd_elf_generic_reloc, /* special_function */
328 "R_MIPS_SHIFT5", /* name */
329 true, /* partial_inplace */
330 0x000007c0, /* src_mask */
331 0x000007c0, /* dst_mask */
332 false), /* pcrel_offset */
333
334 /* A 6 bit shift field. */
335 /* FIXME: This is not handled correctly; a special function is
336 needed to put the most significant bit in the right place. */
337 HOWTO (R_MIPS_SHIFT6, /* type */
338 0, /* rightshift */
339 2, /* size (0 = byte, 1 = short, 2 = long) */
340 6, /* bitsize */
341 false, /* pc_relative */
342 6, /* bitpos */
343 complain_overflow_bitfield, /* complain_on_overflow */
344 bfd_elf_generic_reloc, /* special_function */
345 "R_MIPS_SHIFT6", /* name */
346 true, /* partial_inplace */
347 0x000007c4, /* src_mask */
348 0x000007c4, /* dst_mask */
349 false), /* pcrel_offset */
350
351 /* 64 bit relocation. */
352 HOWTO (R_MIPS_64, /* type */
353 0, /* rightshift */
354 4, /* size (0 = byte, 1 = short, 2 = long) */
355 64, /* bitsize */
356 false, /* pc_relative */
357 0, /* bitpos */
358 complain_overflow_bitfield, /* complain_on_overflow */
359 bfd_elf_generic_reloc, /* special_function */
360 "R_MIPS_64", /* name */
361 true, /* partial_inplace */
362 MINUS_ONE, /* src_mask */
363 MINUS_ONE, /* dst_mask */
364 false), /* pcrel_offset */
365
366 /* Displacement in the global offset table. */
367 /* FIXME: Not handled correctly. */
368 HOWTO (R_MIPS_GOT_DISP, /* type */
369 0, /* rightshift */
370 2, /* size (0 = byte, 1 = short, 2 = long) */
371 16, /* bitsize */
372 false, /* pc_relative */
373 0, /* bitpos */
374 complain_overflow_bitfield, /* complain_on_overflow */
375 bfd_elf_generic_reloc, /* special_function */
376 "R_MIPS_GOT_DISP", /* name */
377 true, /* partial_inplace */
378 0x0000ffff, /* src_mask */
379 0x0000ffff, /* dst_mask */
380 false), /* pcrel_offset */
381
382 /* Displacement to page pointer in the global offset table. */
383 /* FIXME: Not handled correctly. */
384 HOWTO (R_MIPS_GOT_PAGE, /* type */
385 0, /* rightshift */
386 2, /* size (0 = byte, 1 = short, 2 = long) */
387 16, /* bitsize */
388 false, /* pc_relative */
389 0, /* bitpos */
390 complain_overflow_bitfield, /* complain_on_overflow */
391 bfd_elf_generic_reloc, /* special_function */
392 "R_MIPS_GOT_PAGE", /* name */
393 true, /* partial_inplace */
394 0x0000ffff, /* src_mask */
395 0x0000ffff, /* dst_mask */
396 false), /* pcrel_offset */
397
398 /* Offset from page pointer in the global offset table. */
399 /* FIXME: Not handled correctly. */
400 HOWTO (R_MIPS_GOT_OFST, /* type */
401 0, /* rightshift */
402 2, /* size (0 = byte, 1 = short, 2 = long) */
403 16, /* bitsize */
404 false, /* pc_relative */
405 0, /* bitpos */
406 complain_overflow_bitfield, /* complain_on_overflow */
407 bfd_elf_generic_reloc, /* special_function */
408 "R_MIPS_GOT_OFST", /* name */
409 true, /* partial_inplace */
410 0x0000ffff, /* src_mask */
411 0x0000ffff, /* dst_mask */
412 false), /* pcrel_offset */
413
414 /* High 16 bits of displacement in global offset table. */
415 /* FIXME: Not handled correctly. */
416 HOWTO (R_MIPS_GOT_HI16, /* type */
417 0, /* rightshift */
418 2, /* size (0 = byte, 1 = short, 2 = long) */
419 16, /* bitsize */
420 false, /* pc_relative */
421 0, /* bitpos */
422 complain_overflow_dont, /* complain_on_overflow */
423 bfd_elf_generic_reloc, /* special_function */
424 "R_MIPS_GOT_HI16", /* name */
425 true, /* partial_inplace */
426 0x0000ffff, /* src_mask */
427 0x0000ffff, /* dst_mask */
428 false), /* pcrel_offset */
429
430 /* Low 16 bits of displacement in global offset table. */
431 /* FIXME: Not handled correctly. */
432 HOWTO (R_MIPS_GOT_LO16, /* type */
433 0, /* rightshift */
434 2, /* size (0 = byte, 1 = short, 2 = long) */
435 16, /* bitsize */
436 false, /* pc_relative */
437 0, /* bitpos */
438 complain_overflow_dont, /* complain_on_overflow */
439 bfd_elf_generic_reloc, /* special_function */
440 "R_MIPS_GOT_LO16", /* name */
441 true, /* partial_inplace */
442 0x0000ffff, /* src_mask */
443 0x0000ffff, /* dst_mask */
444 false), /* pcrel_offset */
445
446 /* 64 bit substraction. */
447 /* FIXME: Not handled correctly. */
448 HOWTO (R_MIPS_SUB, /* type */
449 0, /* rightshift */
450 4, /* size (0 = byte, 1 = short, 2 = long) */
451 64, /* bitsize */
452 false, /* pc_relative */
453 0, /* bitpos */
454 complain_overflow_bitfield, /* complain_on_overflow */
455 bfd_elf_generic_reloc, /* special_function */
456 "R_MIPS_SUB", /* name */
457 true, /* partial_inplace */
458 MINUS_ONE, /* src_mask */
459 MINUS_ONE, /* dst_mask */
460 false), /* pcrel_offset */
461
462 /* Insert the addend as an instruction. */
463 /* FIXME: Not handled correctly. */
464 HOWTO (R_MIPS_INSERT_A, /* type */
465 0, /* rightshift */
466 0, /* size (0 = byte, 1 = short, 2 = long) */
467 0, /* bitsize */
468 false, /* pc_relative */
469 0, /* bitpos */
470 complain_overflow_dont, /* complain_on_overflow */
471 bfd_elf_generic_reloc, /* special_function */
472 "R_MIPS_INSERT_A", /* name */
473 false, /* partial_inplace */
474 0, /* src_mask */
475 0, /* dst_mask */
476 false), /* pcrel_offset */
477
478 /* Insert the addend as an instruction, and change all relocations
479 to refer to the old instruction at the address. */
480 /* FIXME: Not handled correctly. */
481 HOWTO (R_MIPS_INSERT_B, /* type */
482 0, /* rightshift */
483 0, /* size (0 = byte, 1 = short, 2 = long) */
484 0, /* bitsize */
485 false, /* pc_relative */
486 0, /* bitpos */
487 complain_overflow_dont, /* complain_on_overflow */
488 bfd_elf_generic_reloc, /* special_function */
489 "R_MIPS_INSERT_B", /* name */
490 false, /* partial_inplace */
491 0, /* src_mask */
492 0, /* dst_mask */
493 false), /* pcrel_offset */
494
495 /* Delete a 32 bit instruction. */
496 /* FIXME: Not handled correctly. */
497 HOWTO (R_MIPS_DELETE, /* type */
498 0, /* rightshift */
499 0, /* size (0 = byte, 1 = short, 2 = long) */
500 0, /* bitsize */
501 false, /* pc_relative */
502 0, /* bitpos */
503 complain_overflow_dont, /* complain_on_overflow */
504 bfd_elf_generic_reloc, /* special_function */
505 "R_MIPS_DELETE", /* name */
506 false, /* partial_inplace */
507 0, /* src_mask */
508 0, /* dst_mask */
509 false), /* pcrel_offset */
510
511 /* Get the higher value of a 64 bit addend. */
512 /* FIXME: Not handled correctly. */
513 HOWTO (R_MIPS_HIGHER, /* type */
514 0, /* rightshift */
515 2, /* size (0 = byte, 1 = short, 2 = long) */
516 16, /* bitsize */
517 false, /* pc_relative */
518 0, /* bitpos */
519 complain_overflow_dont, /* complain_on_overflow */
520 bfd_elf_generic_reloc, /* special_function */
521 "R_MIPS_HIGHER", /* name */
522 true, /* partial_inplace */
523 0xffff, /* src_mask */
524 0xffff, /* dst_mask */
525 false), /* pcrel_offset */
526
527 /* Get the highest value of a 64 bit addend. */
528 /* FIXME: Not handled correctly. */
529 HOWTO (R_MIPS_HIGHEST, /* type */
530 0, /* rightshift */
531 2, /* size (0 = byte, 1 = short, 2 = long) */
532 16, /* bitsize */
533 false, /* pc_relative */
534 0, /* bitpos */
535 complain_overflow_dont, /* complain_on_overflow */
536 bfd_elf_generic_reloc, /* special_function */
537 "R_MIPS_HIGHEST", /* name */
538 true, /* partial_inplace */
539 0xffff, /* src_mask */
540 0xffff, /* dst_mask */
541 false), /* pcrel_offset */
542
543 /* High 16 bits of displacement in global offset table. */
544 /* FIXME: Not handled correctly. */
545 HOWTO (R_MIPS_CALL_HI16, /* type */
546 0, /* rightshift */
547 2, /* size (0 = byte, 1 = short, 2 = long) */
548 16, /* bitsize */
549 false, /* pc_relative */
550 0, /* bitpos */
551 complain_overflow_dont, /* complain_on_overflow */
552 bfd_elf_generic_reloc, /* special_function */
553 "R_MIPS_CALL_HI16", /* name */
554 true, /* partial_inplace */
555 0x0000ffff, /* src_mask */
556 0x0000ffff, /* dst_mask */
557 false), /* pcrel_offset */
558
559 /* Low 16 bits of displacement in global offset table. */
560 /* FIXME: Not handled correctly. */
561 HOWTO (R_MIPS_CALL_LO16, /* type */
562 0, /* rightshift */
563 2, /* size (0 = byte, 1 = short, 2 = long) */
564 16, /* bitsize */
565 false, /* pc_relative */
566 0, /* bitpos */
567 complain_overflow_dont, /* complain_on_overflow */
568 bfd_elf_generic_reloc, /* special_function */
569 "R_MIPS_CALL_LO16", /* name */
570 true, /* partial_inplace */
571 0x0000ffff, /* src_mask */
572 0x0000ffff, /* dst_mask */
573 false), /* pcrel_offset */
574
575 /* I'm not sure what the remaining relocs are, but they are defined
576 on Irix 6. */
577
578 HOWTO (R_MIPS_SCN_DISP, /* type */
579 0, /* rightshift */
580 0, /* size (0 = byte, 1 = short, 2 = long) */
581 0, /* bitsize */
582 false, /* pc_relative */
583 0, /* bitpos */
584 complain_overflow_dont, /* complain_on_overflow */
585 bfd_elf_generic_reloc, /* special_function */
586 "R_MIPS_SCN_DISP", /* name */
587 false, /* partial_inplace */
588 0, /* src_mask */
589 0, /* dst_mask */
590 false), /* pcrel_offset */
591
592 HOWTO (R_MIPS_REL16, /* type */
593 0, /* rightshift */
594 0, /* size (0 = byte, 1 = short, 2 = long) */
595 0, /* bitsize */
596 false, /* pc_relative */
597 0, /* bitpos */
598 complain_overflow_dont, /* complain_on_overflow */
599 bfd_elf_generic_reloc, /* special_function */
600 "R_MIPS_REL16", /* name */
601 false, /* partial_inplace */
602 0, /* src_mask */
603 0, /* dst_mask */
604 false), /* pcrel_offset */
605
606 HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
607 0, /* rightshift */
608 0, /* size (0 = byte, 1 = short, 2 = long) */
609 0, /* bitsize */
610 false, /* pc_relative */
611 0, /* bitpos */
612 complain_overflow_dont, /* complain_on_overflow */
613 bfd_elf_generic_reloc, /* special_function */
614 "R_MIPS_ADD_IMMEDIATE", /* name */
615 false, /* partial_inplace */
616 0, /* src_mask */
617 0, /* dst_mask */
618 false) /* pcrel_offset */
619 };
620
621 /* The relocation table used for SHT_RELA sections. */
622
623 static reloc_howto_type mips_elf64_howto_table_rela[] =
624 {
625 /* No relocation. */
626 HOWTO (R_MIPS_NONE, /* type */
627 0, /* rightshift */
628 0, /* size (0 = byte, 1 = short, 2 = long) */
629 0, /* bitsize */
630 false, /* pc_relative */
631 0, /* bitpos */
632 complain_overflow_dont, /* complain_on_overflow */
633 bfd_elf_generic_reloc, /* special_function */
634 "R_MIPS_NONE", /* name */
635 false, /* partial_inplace */
636 0, /* src_mask */
637 0, /* dst_mask */
638 false), /* pcrel_offset */
639
640 /* 16 bit relocation. */
641 HOWTO (R_MIPS_16, /* type */
642 0, /* rightshift */
643 1, /* size (0 = byte, 1 = short, 2 = long) */
644 16, /* bitsize */
645 false, /* pc_relative */
646 0, /* bitpos */
647 complain_overflow_bitfield, /* complain_on_overflow */
648 bfd_elf_generic_reloc, /* special_function */
649 "R_MIPS_16", /* name */
650 true, /* partial_inplace */
651 0, /* src_mask */
652 0xffff, /* dst_mask */
653 false), /* pcrel_offset */
654
655 /* 32 bit relocation. */
656 HOWTO (R_MIPS_32, /* type */
657 0, /* rightshift */
658 2, /* size (0 = byte, 1 = short, 2 = long) */
659 32, /* bitsize */
660 false, /* pc_relative */
661 0, /* bitpos */
662 complain_overflow_bitfield, /* complain_on_overflow */
663 bfd_elf_generic_reloc, /* special_function */
664 "R_MIPS_32", /* name */
665 true, /* partial_inplace */
666 0, /* src_mask */
667 0xffffffff, /* dst_mask */
668 false), /* pcrel_offset */
669
670 /* 32 bit symbol relative relocation. */
671 HOWTO (R_MIPS_REL32, /* type */
672 0, /* rightshift */
673 2, /* size (0 = byte, 1 = short, 2 = long) */
674 32, /* bitsize */
675 false, /* pc_relative */
676 0, /* bitpos */
677 complain_overflow_bitfield, /* complain_on_overflow */
678 bfd_elf_generic_reloc, /* special_function */
679 "R_MIPS_REL32", /* name */
680 true, /* partial_inplace */
681 0, /* src_mask */
682 0xffffffff, /* dst_mask */
683 false), /* pcrel_offset */
684
685 /* 26 bit branch address. */
686 HOWTO (R_MIPS_26, /* type */
687 2, /* rightshift */
688 2, /* size (0 = byte, 1 = short, 2 = long) */
689 26, /* bitsize */
690 false, /* pc_relative */
691 0, /* bitpos */
692 complain_overflow_dont, /* complain_on_overflow */
693 /* This needs complex overflow
694 detection, because the upper four
695 bits must match the PC. */
696 bfd_elf_generic_reloc, /* special_function */
697 "R_MIPS_26", /* name */
698 true, /* partial_inplace */
699 0, /* src_mask */
700 0x3ffffff, /* dst_mask */
701 false), /* pcrel_offset */
702
703 /* High 16 bits of symbol value. */
704 HOWTO (R_MIPS_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_dont, /* complain_on_overflow */
711 bfd_elf_generic_reloc, /* special_function */
712 "R_MIPS_HI16", /* name */
713 true, /* partial_inplace */
714 0, /* src_mask */
715 0xffff, /* dst_mask */
716 false), /* pcrel_offset */
717
718 /* Low 16 bits of symbol value. */
719 HOWTO (R_MIPS_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_dont, /* complain_on_overflow */
726 bfd_elf_generic_reloc, /* special_function */
727 "R_MIPS_LO16", /* name */
728 true, /* partial_inplace */
729 0, /* src_mask */
730 0xffff, /* dst_mask */
731 false), /* pcrel_offset */
732
733 /* GP relative reference. */
734 HOWTO (R_MIPS_GPREL16, /* 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 mips_elf_gprel16_reloc, /* special_function */
742 "R_MIPS_GPREL16", /* name */
743 true, /* partial_inplace */
744 0, /* src_mask */
745 0xffff, /* dst_mask */
746 false), /* pcrel_offset */
747
748 /* Reference to literal section. */
749 HOWTO (R_MIPS_LITERAL, /* type */
750 0, /* rightshift */
751 2, /* size (0 = byte, 1 = short, 2 = long) */
752 16, /* bitsize */
753 false, /* pc_relative */
754 0, /* bitpos */
755 complain_overflow_signed, /* complain_on_overflow */
756 mips_elf_gprel16_reloc, /* special_function */
757 "R_MIPS_LITERAL", /* name */
758 true, /* partial_inplace */
759 0, /* src_mask */
760 0xffff, /* dst_mask */
761 false), /* pcrel_offset */
762
763 /* Reference to global offset table. */
764 HOWTO (R_MIPS_GOT16, /* type */
765 0, /* rightshift */
766 2, /* size (0 = byte, 1 = short, 2 = long) */
767 16, /* bitsize */
768 false, /* pc_relative */
769 0, /* bitpos */
770 complain_overflow_signed, /* complain_on_overflow */
771 mips_elf_got16_reloc, /* special_function */
772 "R_MIPS_GOT16", /* name */
773 false, /* partial_inplace */
774 0, /* src_mask */
775 0xffff, /* dst_mask */
776 false), /* pcrel_offset */
777
778 /* 16 bit PC relative reference. */
779 HOWTO (R_MIPS_PC16, /* type */
780 0, /* rightshift */
781 2, /* size (0 = byte, 1 = short, 2 = long) */
782 16, /* bitsize */
783 true, /* pc_relative */
784 0, /* bitpos */
785 complain_overflow_signed, /* complain_on_overflow */
786 bfd_elf_generic_reloc, /* special_function */
787 "R_MIPS_PC16", /* name */
788 true, /* partial_inplace */
789 0, /* src_mask */
790 0xffff, /* dst_mask */
791 false), /* pcrel_offset */
792
793 /* 16 bit call through global offset table. */
794 /* FIXME: This is not handled correctly. */
795 HOWTO (R_MIPS_CALL16, /* type */
796 0, /* rightshift */
797 2, /* size (0 = byte, 1 = short, 2 = long) */
798 16, /* bitsize */
799 false, /* pc_relative */
800 0, /* bitpos */
801 complain_overflow_signed, /* complain_on_overflow */
802 bfd_elf_generic_reloc, /* special_function */
803 "R_MIPS_CALL16", /* name */
804 false, /* partial_inplace */
805 0, /* src_mask */
806 0xffff, /* dst_mask */
807 false), /* pcrel_offset */
808
809 /* 32 bit GP relative reference. */
810 HOWTO (R_MIPS_GPREL32, /* type */
811 0, /* rightshift */
812 2, /* size (0 = byte, 1 = short, 2 = long) */
813 32, /* bitsize */
814 false, /* pc_relative */
815 0, /* bitpos */
816 complain_overflow_bitfield, /* complain_on_overflow */
817 mips_elf_gprel32_reloc, /* special_function */
818 "R_MIPS_GPREL32", /* name */
819 true, /* partial_inplace */
820 0, /* src_mask */
821 0xffffffff, /* dst_mask */
822 false), /* pcrel_offset */
823
824 { 13 },
825 { 14 },
826 { 15 },
827
828 /* A 5 bit shift field. */
829 HOWTO (R_MIPS_SHIFT5, /* type */
830 0, /* rightshift */
831 2, /* size (0 = byte, 1 = short, 2 = long) */
832 5, /* bitsize */
833 false, /* pc_relative */
834 6, /* bitpos */
835 complain_overflow_bitfield, /* complain_on_overflow */
836 bfd_elf_generic_reloc, /* special_function */
837 "R_MIPS_SHIFT5", /* name */
838 true, /* partial_inplace */
839 0, /* src_mask */
840 0x000007c0, /* dst_mask */
841 false), /* pcrel_offset */
842
843 /* A 6 bit shift field. */
844 /* FIXME: This is not handled correctly; a special function is
845 needed to put the most significant bit in the right place. */
846 HOWTO (R_MIPS_SHIFT6, /* type */
847 0, /* rightshift */
848 2, /* size (0 = byte, 1 = short, 2 = long) */
849 6, /* bitsize */
850 false, /* pc_relative */
851 6, /* bitpos */
852 complain_overflow_bitfield, /* complain_on_overflow */
853 bfd_elf_generic_reloc, /* special_function */
854 "R_MIPS_SHIFT6", /* name */
855 true, /* partial_inplace */
856 0, /* src_mask */
857 0x000007c4, /* dst_mask */
858 false), /* pcrel_offset */
859
860 /* 64 bit relocation. */
861 HOWTO (R_MIPS_64, /* type */
862 0, /* rightshift */
863 4, /* size (0 = byte, 1 = short, 2 = long) */
864 64, /* bitsize */
865 false, /* pc_relative */
866 0, /* bitpos */
867 complain_overflow_bitfield, /* complain_on_overflow */
868 bfd_elf_generic_reloc, /* special_function */
869 "R_MIPS_64", /* name */
870 true, /* partial_inplace */
871 0, /* src_mask */
872 MINUS_ONE, /* dst_mask */
873 false), /* pcrel_offset */
874
875 /* Displacement in the global offset table. */
876 /* FIXME: Not handled correctly. */
877 HOWTO (R_MIPS_GOT_DISP, /* type */
878 0, /* rightshift */
879 2, /* size (0 = byte, 1 = short, 2 = long) */
880 16, /* bitsize */
881 false, /* pc_relative */
882 0, /* bitpos */
883 complain_overflow_bitfield, /* complain_on_overflow */
884 bfd_elf_generic_reloc, /* special_function */
885 "R_MIPS_GOT_DISP", /* name */
886 true, /* partial_inplace */
887 0, /* src_mask */
888 0x0000ffff, /* dst_mask */
889 false), /* pcrel_offset */
890
891 /* Displacement to page pointer in the global offset table. */
892 /* FIXME: Not handled correctly. */
893 HOWTO (R_MIPS_GOT_PAGE, /* type */
894 0, /* rightshift */
895 2, /* size (0 = byte, 1 = short, 2 = long) */
896 16, /* bitsize */
897 false, /* pc_relative */
898 0, /* bitpos */
899 complain_overflow_bitfield, /* complain_on_overflow */
900 bfd_elf_generic_reloc, /* special_function */
901 "R_MIPS_GOT_PAGE", /* name */
902 true, /* partial_inplace */
903 0, /* src_mask */
904 0x0000ffff, /* dst_mask */
905 false), /* pcrel_offset */
906
907 /* Offset from page pointer in the global offset table. */
908 /* FIXME: Not handled correctly. */
909 HOWTO (R_MIPS_GOT_OFST, /* 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_bitfield, /* complain_on_overflow */
916 bfd_elf_generic_reloc, /* special_function */
917 "R_MIPS_GOT_OFST", /* name */
918 true, /* partial_inplace */
919 0, /* src_mask */
920 0x0000ffff, /* dst_mask */
921 false), /* pcrel_offset */
922
923 /* High 16 bits of displacement in global offset table. */
924 /* FIXME: Not handled correctly. */
925 HOWTO (R_MIPS_GOT_HI16, /* type */
926 0, /* rightshift */
927 2, /* size (0 = byte, 1 = short, 2 = long) */
928 16, /* bitsize */
929 false, /* pc_relative */
930 0, /* bitpos */
931 complain_overflow_dont, /* complain_on_overflow */
932 bfd_elf_generic_reloc, /* special_function */
933 "R_MIPS_GOT_HI16", /* name */
934 true, /* partial_inplace */
935 0, /* src_mask */
936 0x0000ffff, /* dst_mask */
937 false), /* pcrel_offset */
938
939 /* Low 16 bits of displacement in global offset table. */
940 /* FIXME: Not handled correctly. */
941 HOWTO (R_MIPS_GOT_LO16, /* type */
942 0, /* rightshift */
943 2, /* size (0 = byte, 1 = short, 2 = long) */
944 16, /* bitsize */
945 false, /* pc_relative */
946 0, /* bitpos */
947 complain_overflow_dont, /* complain_on_overflow */
948 bfd_elf_generic_reloc, /* special_function */
949 "R_MIPS_GOT_LO16", /* name */
950 true, /* partial_inplace */
951 0, /* src_mask */
952 0x0000ffff, /* dst_mask */
953 false), /* pcrel_offset */
954
955 /* 64 bit substraction. */
956 /* FIXME: Not handled correctly. */
957 HOWTO (R_MIPS_SUB, /* type */
958 0, /* rightshift */
959 4, /* size (0 = byte, 1 = short, 2 = long) */
960 64, /* bitsize */
961 false, /* pc_relative */
962 0, /* bitpos */
963 complain_overflow_bitfield, /* complain_on_overflow */
964 bfd_elf_generic_reloc, /* special_function */
965 "R_MIPS_SUB", /* name */
966 true, /* partial_inplace */
967 0, /* src_mask */
968 MINUS_ONE, /* dst_mask */
969 false), /* pcrel_offset */
970
971 /* Insert the addend as an instruction. */
972 /* FIXME: Not handled correctly. */
973 HOWTO (R_MIPS_INSERT_A, /* type */
974 0, /* rightshift */
975 0, /* size (0 = byte, 1 = short, 2 = long) */
976 0, /* bitsize */
977 false, /* pc_relative */
978 0, /* bitpos */
979 complain_overflow_dont, /* complain_on_overflow */
980 bfd_elf_generic_reloc, /* special_function */
981 "R_MIPS_INSERT_A", /* name */
982 false, /* partial_inplace */
983 0, /* src_mask */
984 0, /* dst_mask */
985 false), /* pcrel_offset */
986
987 /* Insert the addend as an instruction, and change all relocations
988 to refer to the old instruction at the address. */
989 /* FIXME: Not handled correctly. */
990 HOWTO (R_MIPS_INSERT_B, /* type */
991 0, /* rightshift */
992 0, /* size (0 = byte, 1 = short, 2 = long) */
993 0, /* bitsize */
994 false, /* pc_relative */
995 0, /* bitpos */
996 complain_overflow_dont, /* complain_on_overflow */
997 bfd_elf_generic_reloc, /* special_function */
998 "R_MIPS_INSERT_B", /* name */
999 false, /* partial_inplace */
1000 0, /* src_mask */
1001 0, /* dst_mask */
1002 false), /* pcrel_offset */
1003
1004 /* Delete a 32 bit instruction. */
1005 /* FIXME: Not handled correctly. */
1006 HOWTO (R_MIPS_DELETE, /* type */
1007 0, /* rightshift */
1008 0, /* size (0 = byte, 1 = short, 2 = long) */
1009 0, /* bitsize */
1010 false, /* pc_relative */
1011 0, /* bitpos */
1012 complain_overflow_dont, /* complain_on_overflow */
1013 bfd_elf_generic_reloc, /* special_function */
1014 "R_MIPS_DELETE", /* name */
1015 false, /* partial_inplace */
1016 0, /* src_mask */
1017 0, /* dst_mask */
1018 false), /* pcrel_offset */
1019
1020 /* Get the higher value of a 64 bit addend. */
1021 /* FIXME: Not handled correctly. */
1022 HOWTO (R_MIPS_HIGHER, /* type */
1023 0, /* rightshift */
1024 2, /* size (0 = byte, 1 = short, 2 = long) */
1025 16, /* bitsize */
1026 false, /* pc_relative */
1027 0, /* bitpos */
1028 complain_overflow_dont, /* complain_on_overflow */
1029 bfd_elf_generic_reloc, /* special_function */
1030 "R_MIPS_HIGHER", /* name */
1031 true, /* partial_inplace */
1032 0, /* src_mask */
1033 0xffff, /* dst_mask */
1034 false), /* pcrel_offset */
1035
1036 /* Get the highest value of a 64 bit addend. */
1037 /* FIXME: Not handled correctly. */
1038 HOWTO (R_MIPS_HIGHEST, /* type */
1039 0, /* rightshift */
1040 2, /* size (0 = byte, 1 = short, 2 = long) */
1041 16, /* bitsize */
1042 false, /* pc_relative */
1043 0, /* bitpos */
1044 complain_overflow_dont, /* complain_on_overflow */
1045 bfd_elf_generic_reloc, /* special_function */
1046 "R_MIPS_HIGHEST", /* name */
1047 true, /* partial_inplace */
1048 0, /* src_mask */
1049 0xffff, /* dst_mask */
1050 false), /* pcrel_offset */
1051
1052 /* High 16 bits of displacement in global offset table. */
1053 /* FIXME: Not handled correctly. */
1054 HOWTO (R_MIPS_CALL_HI16, /* type */
1055 0, /* rightshift */
1056 2, /* size (0 = byte, 1 = short, 2 = long) */
1057 16, /* bitsize */
1058 false, /* pc_relative */
1059 0, /* bitpos */
1060 complain_overflow_dont, /* complain_on_overflow */
1061 bfd_elf_generic_reloc, /* special_function */
1062 "R_MIPS_CALL_HI16", /* name */
1063 true, /* partial_inplace */
1064 0, /* src_mask */
1065 0x0000ffff, /* dst_mask */
1066 false), /* pcrel_offset */
1067
1068 /* Low 16 bits of displacement in global offset table. */
1069 /* FIXME: Not handled correctly. */
1070 HOWTO (R_MIPS_CALL_LO16, /* type */
1071 0, /* rightshift */
1072 2, /* size (0 = byte, 1 = short, 2 = long) */
1073 16, /* bitsize */
1074 false, /* pc_relative */
1075 0, /* bitpos */
1076 complain_overflow_dont, /* complain_on_overflow */
1077 bfd_elf_generic_reloc, /* special_function */
1078 "R_MIPS_CALL_LO16", /* name */
1079 true, /* partial_inplace */
1080 0, /* src_mask */
1081 0x0000ffff, /* dst_mask */
1082 false), /* pcrel_offset */
1083
1084 /* I'm not sure what the remaining relocs are, but they are defined
1085 on Irix 6. */
1086
1087 HOWTO (R_MIPS_SCN_DISP, /* type */
1088 0, /* rightshift */
1089 0, /* size (0 = byte, 1 = short, 2 = long) */
1090 0, /* bitsize */
1091 false, /* pc_relative */
1092 0, /* bitpos */
1093 complain_overflow_dont, /* complain_on_overflow */
1094 bfd_elf_generic_reloc, /* special_function */
1095 "R_MIPS_SCN_DISP", /* name */
1096 false, /* partial_inplace */
1097 0, /* src_mask */
1098 0, /* dst_mask */
1099 false), /* pcrel_offset */
1100
1101 HOWTO (R_MIPS_REL16, /* type */
1102 0, /* rightshift */
1103 0, /* size (0 = byte, 1 = short, 2 = long) */
1104 0, /* bitsize */
1105 false, /* pc_relative */
1106 0, /* bitpos */
1107 complain_overflow_dont, /* complain_on_overflow */
1108 bfd_elf_generic_reloc, /* special_function */
1109 "R_MIPS_REL16", /* name */
1110 false, /* partial_inplace */
1111 0, /* src_mask */
1112 0, /* dst_mask */
1113 false), /* pcrel_offset */
1114
1115 HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
1116 0, /* rightshift */
1117 0, /* size (0 = byte, 1 = short, 2 = long) */
1118 0, /* bitsize */
1119 false, /* pc_relative */
1120 0, /* bitpos */
1121 complain_overflow_dont, /* complain_on_overflow */
1122 bfd_elf_generic_reloc, /* special_function */
1123 "R_MIPS_ADD_IMMEDIATE", /* name */
1124 false, /* partial_inplace */
1125 0, /* src_mask */
1126 0, /* dst_mask */
1127 false) /* pcrel_offset */
1128 };
1129
1130 /* Swap in a MIPS 64-bit Rel reloc. */
1131
1132 static void
1133 mips_elf64_swap_reloc_in (abfd, src, dst)
1134 bfd *abfd;
1135 const Elf64_Mips_External_Rel *src;
1136 Elf64_Mips_Internal_Rel *dst;
1137 {
1138 dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
1139 dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
1140 dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
1141 dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
1142 dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
1143 dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
1144 }
1145
1146 /* Swap in a MIPS 64-bit Rela reloc. */
1147
1148 static void
1149 mips_elf64_swap_reloca_in (abfd, src, dst)
1150 bfd *abfd;
1151 const Elf64_Mips_External_Rela *src;
1152 Elf64_Mips_Internal_Rela *dst;
1153 {
1154 dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
1155 dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
1156 dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
1157 dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
1158 dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
1159 dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
1160 dst->r_addend = bfd_h_get_64 (abfd, (bfd_byte *) src->r_addend);
1161 }
1162
1163 /* Swap out a MIPS 64-bit Rel reloc. */
1164
1165 static void
1166 mips_elf64_swap_reloc_out (abfd, src, dst)
1167 bfd *abfd;
1168 const Elf64_Mips_Internal_Rel *src;
1169 Elf64_Mips_External_Rel *dst;
1170 {
1171 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1172 bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
1173 bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
1174 bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
1175 bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
1176 bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
1177 }
1178
1179 /* Swap out a MIPS 64-bit Rela reloc. */
1180
1181 static void
1182 mips_elf64_swap_reloca_out (abfd, src, dst)
1183 bfd *abfd;
1184 const Elf64_Mips_Internal_Rela *src;
1185 Elf64_Mips_External_Rela *dst;
1186 {
1187 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1188 bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
1189 bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
1190 bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
1191 bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
1192 bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
1193 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1194 }
1195
1196 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1197
1198 struct elf_reloc_map
1199 {
1200 bfd_reloc_code_real_type bfd_reloc_val;
1201 enum mips_elf64_reloc_type elf_reloc_val;
1202 };
1203
1204 static CONST struct elf_reloc_map mips_reloc_map[] =
1205 {
1206 { BFD_RELOC_NONE, R_MIPS_NONE, },
1207 { BFD_RELOC_16, R_MIPS_16 },
1208 { BFD_RELOC_32, R_MIPS_32 },
1209 { BFD_RELOC_64, R_MIPS_64 },
1210 { BFD_RELOC_CTOR, R_MIPS_64 },
1211 { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
1212 { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
1213 { BFD_RELOC_HI16_S, R_MIPS_HI16 },
1214 { BFD_RELOC_LO16, R_MIPS_LO16 },
1215 { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 },
1216 { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
1217 { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
1218 { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
1219 { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
1220 { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 },
1221 { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
1222 { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
1223 { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
1224 { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }
1225 };
1226
1227 /* Given a BFD reloc type, return a howto structure. */
1228
1229 static reloc_howto_type *
1230 mips_elf64_reloc_type_lookup (abfd, code)
1231 bfd *abfd;
1232 bfd_reloc_code_real_type code;
1233 {
1234 unsigned int i;
1235
1236 for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
1237 {
1238 if (mips_reloc_map[i].bfd_reloc_val == code)
1239 {
1240 int v;
1241
1242 v = (int) mips_reloc_map[i].elf_reloc_val;
1243 return &mips_elf64_howto_table_rel[v];
1244 }
1245 }
1246
1247 return NULL;
1248 }
1249
1250 /* Read the relocations from one reloc section. */
1251
1252 static boolean
1253 mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
1254 bfd *abfd;
1255 asection *asect;
1256 asymbol **symbols;
1257 const Elf_Internal_Shdr *rel_hdr;
1258 {
1259 PTR allocated = NULL;
1260 bfd_byte *native_relocs;
1261 arelent *relents;
1262 arelent *relent;
1263 unsigned int count;
1264 unsigned int i;
1265 int entsize;
1266 reloc_howto_type *howto_table;
1267
1268 allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
1269 if (allocated == NULL)
1270 goto error_return;
1271
1272 if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
1273 || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
1274 goto error_return;
1275
1276 native_relocs = (bfd_byte *) allocated;
1277
1278 relents = asect->relocation + asect->reloc_count;
1279
1280 entsize = rel_hdr->sh_entsize;
1281 BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
1282 || entsize == sizeof (Elf64_Mips_External_Rela));
1283
1284 count = rel_hdr->sh_size / entsize;
1285
1286 if (entsize == sizeof (Elf64_Mips_External_Rel))
1287 howto_table = mips_elf64_howto_table_rel;
1288 else
1289 howto_table = mips_elf64_howto_table_rela;
1290
1291 relent = relents;
1292 for (i = 0; i < count; i++, native_relocs += entsize)
1293 {
1294 Elf64_Mips_Internal_Rela rela;
1295 boolean used_sym, used_ssym;
1296 int ir;
1297
1298 if (entsize == sizeof (Elf64_Mips_External_Rela))
1299 mips_elf64_swap_reloca_in (abfd,
1300 (Elf64_Mips_External_Rela *) native_relocs,
1301 &rela);
1302 else
1303 {
1304 Elf64_Mips_Internal_Rel rel;
1305
1306 mips_elf64_swap_reloc_in (abfd,
1307 (Elf64_Mips_External_Rel *) native_relocs,
1308 &rel);
1309 rela.r_offset = rel.r_offset;
1310 rela.r_sym = rel.r_sym;
1311 rela.r_ssym = rel.r_ssym;
1312 rela.r_type3 = rel.r_type3;
1313 rela.r_type2 = rel.r_type2;
1314 rela.r_type = rel.r_type;
1315 rela.r_addend = 0;
1316 }
1317
1318 /* Each entry represents up to three actual relocations. */
1319
1320 used_sym = false;
1321 used_ssym = false;
1322 for (ir = 0; ir < 3; ir++)
1323 {
1324 enum mips_elf64_reloc_type type;
1325
1326 switch (ir)
1327 {
1328 default:
1329 abort ();
1330 case 0:
1331 type = (enum mips_elf64_reloc_type) rela.r_type;
1332 break;
1333 case 1:
1334 type = (enum mips_elf64_reloc_type) rela.r_type2;
1335 break;
1336 case 2:
1337 type = (enum mips_elf64_reloc_type) rela.r_type3;
1338 break;
1339 }
1340
1341 if (type == R_MIPS_NONE)
1342 {
1343 /* There are no more relocations in this entry. If this
1344 is the first entry, we need to generate a dummy
1345 relocation so that the generic linker knows that
1346 there has been a break in the sequence of relocations
1347 applying to a particular address. */
1348 if (ir == 0)
1349 {
1350 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1351 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1352 relent->address = rela.r_offset;
1353 else
1354 relent->address = rela.r_offset - asect->vma;
1355 relent->addend = 0;
1356 relent->howto = &howto_table[(int) R_MIPS_NONE];
1357 ++relent;
1358 }
1359 break;
1360 }
1361
1362 /* Some types require symbols, whereas some do not. */
1363 switch (type)
1364 {
1365 case R_MIPS_NONE:
1366 case R_MIPS_LITERAL:
1367 case R_MIPS_INSERT_A:
1368 case R_MIPS_INSERT_B:
1369 case R_MIPS_DELETE:
1370 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1371 break;
1372
1373 default:
1374 if (! used_sym)
1375 {
1376 if (rela.r_sym == 0)
1377 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1378 else
1379 {
1380 asymbol **ps, *s;
1381
1382 ps = symbols + rela.r_sym - 1;
1383 s = *ps;
1384 if ((s->flags & BSF_SECTION_SYM) == 0)
1385 relent->sym_ptr_ptr = ps;
1386 else
1387 relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
1388 }
1389
1390 used_sym = true;
1391 }
1392 else if (! used_ssym)
1393 {
1394 switch (rela.r_ssym)
1395 {
1396 case RSS_UNDEF:
1397 relent->sym_ptr_ptr =
1398 bfd_abs_section_ptr->symbol_ptr_ptr;
1399 break;
1400
1401 case RSS_GP:
1402 case RSS_GP0:
1403 case RSS_LOC:
1404 /* FIXME: I think these need to be handled using
1405 special howto structures. */
1406 BFD_ASSERT (0);
1407 break;
1408
1409 default:
1410 BFD_ASSERT (0);
1411 break;
1412 }
1413
1414 used_ssym = true;
1415 }
1416 else
1417 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1418
1419 break;
1420 }
1421
1422 /* The address of an ELF reloc is section relative for an
1423 object file, and absolute for an executable file or
1424 shared library. The address of a BFD reloc is always
1425 section relative. */
1426 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1427 relent->address = rela.r_offset;
1428 else
1429 relent->address = rela.r_offset - asect->vma;
1430
1431 relent->addend = rela.r_addend;
1432
1433 relent->howto = &howto_table[(int) type];
1434
1435 ++relent;
1436 }
1437 }
1438
1439 asect->reloc_count += relent - relents;
1440
1441 if (allocated != NULL)
1442 free (allocated);
1443
1444 return true;
1445
1446 error_return:
1447 if (allocated != NULL)
1448 free (allocated);
1449 return false;
1450 }
1451
1452 /* Read the relocations. On Irix 6, there can be two reloc sections
1453 associated with a single data section. */
1454
1455 static boolean
1456 mips_elf64_slurp_reloc_table (abfd, asect, symbols)
1457 bfd *abfd;
1458 asection *asect;
1459 asymbol **symbols;
1460 {
1461 struct bfd_elf_section_data * const d = elf_section_data (asect);
1462
1463 if (asect->relocation != NULL
1464 || (asect->flags & SEC_RELOC) == 0
1465 || asect->reloc_count == 0)
1466 return true;
1467
1468 /* Allocate space for 3 arelent structures for each Rel structure. */
1469 asect->relocation = ((arelent *)
1470 bfd_alloc (abfd,
1471 asect->reloc_count * 3 * sizeof (arelent)));
1472 if (asect->relocation == NULL)
1473 return false;
1474
1475 /* The slurp_one_reloc_table routine increments reloc_count. */
1476 asect->reloc_count = 0;
1477
1478 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
1479 return false;
1480 if (d->rel_hdr2 != NULL)
1481 {
1482 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
1483 d->rel_hdr2))
1484 return false;
1485 }
1486
1487 return true;
1488 }
1489
1490 /* Write out the relocations. */
1491
1492 static void
1493 mips_elf64_write_relocs (abfd, sec, data)
1494 bfd *abfd;
1495 asection *sec;
1496 PTR data;
1497 {
1498 /* FIXME. */
1499 abort ();
1500 }
1501 \f
1502 /* Handle a 64-bit MIPS ELF specific section. */
1503
1504 static boolean
1505 mips_elf64_section_from_shdr (abfd, hdr, name)
1506 bfd *abfd;
1507 Elf_Internal_Shdr *hdr;
1508 char *name;
1509 {
1510 if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
1511 return false;
1512
1513 return true;
1514 }
1515
1516 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
1517 standard ELF. This structure is used to redirect the relocation
1518 handling routines. */
1519
1520 const struct elf_size_info mips_elf64_size_info =
1521 {
1522 sizeof (Elf64_External_Ehdr),
1523 sizeof (Elf64_External_Phdr),
1524 sizeof (Elf64_External_Shdr),
1525 sizeof (Elf64_Mips_External_Rel),
1526 sizeof (Elf64_Mips_External_Rela),
1527 sizeof (Elf64_External_Sym),
1528 sizeof (Elf64_External_Dyn),
1529 sizeof (Elf_External_Note),
1530 64, /* arch_size */
1531 8, /* file_align */
1532 ELFCLASS64,
1533 EV_CURRENT,
1534 bfd_elf64_write_out_phdrs,
1535 bfd_elf64_write_shdrs_and_ehdr,
1536 mips_elf64_write_relocs,
1537 bfd_elf64_swap_symbol_out,
1538 mips_elf64_slurp_reloc_table,
1539 bfd_elf64_slurp_symbol_table,
1540 bfd_elf64_swap_dyn_in
1541 };
1542
1543 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
1544 #define TARGET_LITTLE_NAME "elf64-littlemips"
1545 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
1546 #define TARGET_BIG_NAME "elf64-bigmips"
1547 #define ELF_ARCH bfd_arch_mips
1548 #define ELF_MACHINE_CODE EM_MIPS
1549 #define ELF_MAXPAGESIZE 0x1000
1550 #define elf_backend_size_info mips_elf64_size_info
1551 #define elf_backend_section_from_shdr mips_elf64_section_from_shdr
1552 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
1553
1554 #include "elf64-target.h"