Add support for storing local symbols in a small structure to save
[binutils.git] / bfd / elf64-mips.c
blob36e607508d1edafc153dde939e9eb163cfefdfb4
1 /* MIPS-specific support for 64-bit ELF
2 Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
3 Ian Lance Taylor, Cygnus Support
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
21 /* This file supports the 64-bit MIPS ELF ABI.
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.
27 The MIPS 64-bit ELF ABI also uses an unusual archive map format. */
29 #include "bfd.h"
30 #include "sysdep.h"
31 #include "libbfd.h"
32 #include "aout/ar.h"
33 #include "bfdlink.h"
34 #include "genlink.h"
35 #include "elf-bfd.h"
36 #include "elf/mips.h"
38 /* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
39 use ECOFF. However, we support it anyhow for an easier changeover. */
40 #include "coff/sym.h"
41 #include "coff/symconst.h"
42 #include "coff/internal.h"
43 #include "coff/ecoff.h"
44 /* The 64 bit versions of the mdebug data structures are in alpha.h. */
45 #include "coff/alpha.h"
46 #define ECOFF_64
47 #include "ecoffswap.h"
49 static void mips_elf64_swap_reloc_in
50 PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
51 Elf64_Mips_Internal_Rel *));
52 static void mips_elf64_swap_reloca_in
53 PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
54 Elf64_Mips_Internal_Rela *));
55 #if 0
56 static void mips_elf64_swap_reloc_out
57 PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
58 Elf64_Mips_External_Rel *));
59 #endif
60 static void mips_elf64_swap_reloca_out
61 PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
62 Elf64_Mips_External_Rela *));
63 static reloc_howto_type *mips_elf64_reloc_type_lookup
64 PARAMS ((bfd *, bfd_reloc_code_real_type));
65 static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
66 static boolean mips_elf64_slurp_one_reloc_table
67 PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
68 static boolean mips_elf64_slurp_reloc_table
69 PARAMS ((bfd *, asection *, asymbol **, boolean));
70 static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
71 static boolean mips_elf64_section_from_shdr
72 PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
73 static boolean mips_elf64_section_processing
74 PARAMS ((bfd *, Elf_Internal_Shdr *));
75 static boolean mips_elf64_slurp_armap PARAMS ((bfd *));
76 static boolean mips_elf64_write_armap
77 PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
79 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
80 from smaller values. Start with zero, widen, *then* decrement. */
81 #define MINUS_ONE (((bfd_vma)0) - 1)
83 /* The relocation table used for SHT_REL sections. */
85 static reloc_howto_type mips_elf64_howto_table_rel[] =
87 /* No relocation. */
88 HOWTO (R_MIPS_NONE, /* type */
89 0, /* rightshift */
90 0, /* size (0 = byte, 1 = short, 2 = long) */
91 0, /* bitsize */
92 false, /* pc_relative */
93 0, /* bitpos */
94 complain_overflow_dont, /* complain_on_overflow */
95 bfd_elf_generic_reloc, /* special_function */
96 "R_MIPS_NONE", /* name */
97 false, /* partial_inplace */
98 0, /* src_mask */
99 0, /* dst_mask */
100 false), /* pcrel_offset */
102 /* 16 bit relocation. */
103 HOWTO (R_MIPS_16, /* type */
104 0, /* rightshift */
105 1, /* size (0 = byte, 1 = short, 2 = long) */
106 16, /* bitsize */
107 false, /* pc_relative */
108 0, /* bitpos */
109 complain_overflow_bitfield, /* complain_on_overflow */
110 bfd_elf_generic_reloc, /* special_function */
111 "R_MIPS_16", /* name */
112 true, /* partial_inplace */
113 0xffff, /* src_mask */
114 0xffff, /* dst_mask */
115 false), /* pcrel_offset */
117 /* 32 bit relocation. */
118 HOWTO (R_MIPS_32, /* type */
119 0, /* rightshift */
120 2, /* size (0 = byte, 1 = short, 2 = long) */
121 32, /* bitsize */
122 false, /* pc_relative */
123 0, /* bitpos */
124 complain_overflow_bitfield, /* complain_on_overflow */
125 bfd_elf_generic_reloc, /* special_function */
126 "R_MIPS_32", /* name */
127 true, /* partial_inplace */
128 0xffffffff, /* src_mask */
129 0xffffffff, /* dst_mask */
130 false), /* pcrel_offset */
132 /* 32 bit symbol relative relocation. */
133 HOWTO (R_MIPS_REL32, /* type */
134 0, /* rightshift */
135 2, /* size (0 = byte, 1 = short, 2 = long) */
136 32, /* bitsize */
137 false, /* pc_relative */
138 0, /* bitpos */
139 complain_overflow_bitfield, /* complain_on_overflow */
140 bfd_elf_generic_reloc, /* special_function */
141 "R_MIPS_REL32", /* name */
142 true, /* partial_inplace */
143 0xffffffff, /* src_mask */
144 0xffffffff, /* dst_mask */
145 false), /* pcrel_offset */
147 /* 26 bit branch address. */
148 HOWTO (R_MIPS_26, /* type */
149 2, /* rightshift */
150 2, /* size (0 = byte, 1 = short, 2 = long) */
151 26, /* bitsize */
152 false, /* pc_relative */
153 0, /* bitpos */
154 complain_overflow_dont, /* complain_on_overflow */
155 /* This needs complex overflow
156 detection, because the upper four
157 bits must match the PC. */
158 bfd_elf_generic_reloc, /* special_function */
159 "R_MIPS_26", /* name */
160 true, /* partial_inplace */
161 0x3ffffff, /* src_mask */
162 0x3ffffff, /* dst_mask */
163 false), /* pcrel_offset */
165 /* High 16 bits of symbol value. */
166 HOWTO (R_MIPS_HI16, /* type */
167 0, /* rightshift */
168 2, /* size (0 = byte, 1 = short, 2 = long) */
169 16, /* bitsize */
170 false, /* pc_relative */
171 0, /* bitpos */
172 complain_overflow_dont, /* complain_on_overflow */
173 _bfd_mips_elf_hi16_reloc, /* special_function */
174 "R_MIPS_HI16", /* name */
175 true, /* partial_inplace */
176 0xffff, /* src_mask */
177 0xffff, /* dst_mask */
178 false), /* pcrel_offset */
180 /* Low 16 bits of symbol value. */
181 HOWTO (R_MIPS_LO16, /* type */
182 0, /* rightshift */
183 2, /* size (0 = byte, 1 = short, 2 = long) */
184 16, /* bitsize */
185 false, /* pc_relative */
186 0, /* bitpos */
187 complain_overflow_dont, /* complain_on_overflow */
188 _bfd_mips_elf_lo16_reloc, /* special_function */
189 "R_MIPS_LO16", /* name */
190 true, /* partial_inplace */
191 0xffff, /* src_mask */
192 0xffff, /* dst_mask */
193 false), /* pcrel_offset */
195 /* GP relative reference. */
196 HOWTO (R_MIPS_GPREL16, /* type */
197 0, /* rightshift */
198 2, /* size (0 = byte, 1 = short, 2 = long) */
199 16, /* bitsize */
200 false, /* pc_relative */
201 0, /* bitpos */
202 complain_overflow_signed, /* complain_on_overflow */
203 _bfd_mips_elf_gprel16_reloc, /* special_function */
204 "R_MIPS_GPREL16", /* name */
205 true, /* partial_inplace */
206 0xffff, /* src_mask */
207 0xffff, /* dst_mask */
208 false), /* pcrel_offset */
210 /* Reference to literal section. */
211 HOWTO (R_MIPS_LITERAL, /* type */
212 0, /* rightshift */
213 2, /* size (0 = byte, 1 = short, 2 = long) */
214 16, /* bitsize */
215 false, /* pc_relative */
216 0, /* bitpos */
217 complain_overflow_signed, /* complain_on_overflow */
218 _bfd_mips_elf_gprel16_reloc, /* special_function */
219 "R_MIPS_LITERAL", /* name */
220 true, /* partial_inplace */
221 0xffff, /* src_mask */
222 0xffff, /* dst_mask */
223 false), /* pcrel_offset */
225 /* Reference to global offset table. */
226 HOWTO (R_MIPS_GOT16, /* type */
227 0, /* rightshift */
228 2, /* size (0 = byte, 1 = short, 2 = long) */
229 16, /* bitsize */
230 false, /* pc_relative */
231 0, /* bitpos */
232 complain_overflow_signed, /* complain_on_overflow */
233 _bfd_mips_elf_got16_reloc, /* special_function */
234 "R_MIPS_GOT16", /* name */
235 false, /* partial_inplace */
236 0, /* src_mask */
237 0xffff, /* dst_mask */
238 false), /* pcrel_offset */
240 /* 16 bit PC relative reference. */
241 HOWTO (R_MIPS_PC16, /* type */
242 0, /* rightshift */
243 2, /* size (0 = byte, 1 = short, 2 = long) */
244 16, /* bitsize */
245 true, /* pc_relative */
246 0, /* bitpos */
247 complain_overflow_signed, /* complain_on_overflow */
248 bfd_elf_generic_reloc, /* special_function */
249 "R_MIPS_PC16", /* name */
250 true, /* partial_inplace */
251 0xffff, /* src_mask */
252 0xffff, /* dst_mask */
253 false), /* pcrel_offset */
255 /* 16 bit call through global offset table. */
256 /* FIXME: This is not handled correctly. */
257 HOWTO (R_MIPS_CALL16, /* type */
258 0, /* rightshift */
259 2, /* size (0 = byte, 1 = short, 2 = long) */
260 16, /* bitsize */
261 false, /* pc_relative */
262 0, /* bitpos */
263 complain_overflow_signed, /* complain_on_overflow */
264 bfd_elf_generic_reloc, /* special_function */
265 "R_MIPS_CALL16", /* name */
266 false, /* partial_inplace */
267 0, /* src_mask */
268 0xffff, /* dst_mask */
269 false), /* pcrel_offset */
271 /* 32 bit GP relative reference. */
272 HOWTO (R_MIPS_GPREL32, /* type */
273 0, /* rightshift */
274 2, /* size (0 = byte, 1 = short, 2 = long) */
275 32, /* bitsize */
276 false, /* pc_relative */
277 0, /* bitpos */
278 complain_overflow_bitfield, /* complain_on_overflow */
279 _bfd_mips_elf_gprel32_reloc, /* special_function */
280 "R_MIPS_GPREL32", /* name */
281 true, /* partial_inplace */
282 0xffffffff, /* src_mask */
283 0xffffffff, /* dst_mask */
284 false), /* pcrel_offset */
286 { 13 },
287 { 14 },
288 { 15 },
290 /* A 5 bit shift field. */
291 HOWTO (R_MIPS_SHIFT5, /* type */
292 0, /* rightshift */
293 2, /* size (0 = byte, 1 = short, 2 = long) */
294 5, /* bitsize */
295 false, /* pc_relative */
296 6, /* bitpos */
297 complain_overflow_bitfield, /* complain_on_overflow */
298 bfd_elf_generic_reloc, /* special_function */
299 "R_MIPS_SHIFT5", /* name */
300 true, /* partial_inplace */
301 0x000007c0, /* src_mask */
302 0x000007c0, /* dst_mask */
303 false), /* pcrel_offset */
305 /* A 6 bit shift field. */
306 /* FIXME: This is not handled correctly; a special function is
307 needed to put the most significant bit in the right place. */
308 HOWTO (R_MIPS_SHIFT6, /* type */
309 0, /* rightshift */
310 2, /* size (0 = byte, 1 = short, 2 = long) */
311 6, /* bitsize */
312 false, /* pc_relative */
313 6, /* bitpos */
314 complain_overflow_bitfield, /* complain_on_overflow */
315 bfd_elf_generic_reloc, /* special_function */
316 "R_MIPS_SHIFT6", /* name */
317 true, /* partial_inplace */
318 0x000007c4, /* src_mask */
319 0x000007c4, /* dst_mask */
320 false), /* pcrel_offset */
322 /* 64 bit relocation. */
323 HOWTO (R_MIPS_64, /* type */
324 0, /* rightshift */
325 4, /* size (0 = byte, 1 = short, 2 = long) */
326 64, /* bitsize */
327 false, /* pc_relative */
328 0, /* bitpos */
329 complain_overflow_bitfield, /* complain_on_overflow */
330 bfd_elf_generic_reloc, /* special_function */
331 "R_MIPS_64", /* name */
332 true, /* partial_inplace */
333 MINUS_ONE, /* src_mask */
334 MINUS_ONE, /* dst_mask */
335 false), /* pcrel_offset */
337 /* Displacement in the global offset table. */
338 /* FIXME: Not handled correctly. */
339 HOWTO (R_MIPS_GOT_DISP, /* type */
340 0, /* rightshift */
341 2, /* size (0 = byte, 1 = short, 2 = long) */
342 16, /* bitsize */
343 false, /* pc_relative */
344 0, /* bitpos */
345 complain_overflow_bitfield, /* complain_on_overflow */
346 bfd_elf_generic_reloc, /* special_function */
347 "R_MIPS_GOT_DISP", /* name */
348 true, /* partial_inplace */
349 0x0000ffff, /* src_mask */
350 0x0000ffff, /* dst_mask */
351 false), /* pcrel_offset */
353 /* Displacement to page pointer in the global offset table. */
354 /* FIXME: Not handled correctly. */
355 HOWTO (R_MIPS_GOT_PAGE, /* type */
356 0, /* rightshift */
357 2, /* size (0 = byte, 1 = short, 2 = long) */
358 16, /* bitsize */
359 false, /* pc_relative */
360 0, /* bitpos */
361 complain_overflow_bitfield, /* complain_on_overflow */
362 bfd_elf_generic_reloc, /* special_function */
363 "R_MIPS_GOT_PAGE", /* name */
364 true, /* partial_inplace */
365 0x0000ffff, /* src_mask */
366 0x0000ffff, /* dst_mask */
367 false), /* pcrel_offset */
369 /* Offset from page pointer in the global offset table. */
370 /* FIXME: Not handled correctly. */
371 HOWTO (R_MIPS_GOT_OFST, /* type */
372 0, /* rightshift */
373 2, /* size (0 = byte, 1 = short, 2 = long) */
374 16, /* bitsize */
375 false, /* pc_relative */
376 0, /* bitpos */
377 complain_overflow_bitfield, /* complain_on_overflow */
378 bfd_elf_generic_reloc, /* special_function */
379 "R_MIPS_GOT_OFST", /* name */
380 true, /* partial_inplace */
381 0x0000ffff, /* src_mask */
382 0x0000ffff, /* dst_mask */
383 false), /* pcrel_offset */
385 /* High 16 bits of displacement in global offset table. */
386 /* FIXME: Not handled correctly. */
387 HOWTO (R_MIPS_GOT_HI16, /* type */
388 0, /* rightshift */
389 2, /* size (0 = byte, 1 = short, 2 = long) */
390 16, /* bitsize */
391 false, /* pc_relative */
392 0, /* bitpos */
393 complain_overflow_dont, /* complain_on_overflow */
394 bfd_elf_generic_reloc, /* special_function */
395 "R_MIPS_GOT_HI16", /* name */
396 true, /* partial_inplace */
397 0x0000ffff, /* src_mask */
398 0x0000ffff, /* dst_mask */
399 false), /* pcrel_offset */
401 /* Low 16 bits of displacement in global offset table. */
402 /* FIXME: Not handled correctly. */
403 HOWTO (R_MIPS_GOT_LO16, /* type */
404 0, /* rightshift */
405 2, /* size (0 = byte, 1 = short, 2 = long) */
406 16, /* bitsize */
407 false, /* pc_relative */
408 0, /* bitpos */
409 complain_overflow_dont, /* complain_on_overflow */
410 bfd_elf_generic_reloc, /* special_function */
411 "R_MIPS_GOT_LO16", /* name */
412 true, /* partial_inplace */
413 0x0000ffff, /* src_mask */
414 0x0000ffff, /* dst_mask */
415 false), /* pcrel_offset */
417 /* 64 bit substraction. */
418 /* FIXME: Not handled correctly. */
419 HOWTO (R_MIPS_SUB, /* type */
420 0, /* rightshift */
421 4, /* size (0 = byte, 1 = short, 2 = long) */
422 64, /* bitsize */
423 false, /* pc_relative */
424 0, /* bitpos */
425 complain_overflow_bitfield, /* complain_on_overflow */
426 bfd_elf_generic_reloc, /* special_function */
427 "R_MIPS_SUB", /* name */
428 true, /* partial_inplace */
429 MINUS_ONE, /* src_mask */
430 MINUS_ONE, /* dst_mask */
431 false), /* pcrel_offset */
433 /* Insert the addend as an instruction. */
434 /* FIXME: Not handled correctly. */
435 HOWTO (R_MIPS_INSERT_A, /* type */
436 0, /* rightshift */
437 0, /* size (0 = byte, 1 = short, 2 = long) */
438 0, /* bitsize */
439 false, /* pc_relative */
440 0, /* bitpos */
441 complain_overflow_dont, /* complain_on_overflow */
442 bfd_elf_generic_reloc, /* special_function */
443 "R_MIPS_INSERT_A", /* name */
444 false, /* partial_inplace */
445 0, /* src_mask */
446 0, /* dst_mask */
447 false), /* pcrel_offset */
449 /* Insert the addend as an instruction, and change all relocations
450 to refer to the old instruction at the address. */
451 /* FIXME: Not handled correctly. */
452 HOWTO (R_MIPS_INSERT_B, /* type */
453 0, /* rightshift */
454 0, /* size (0 = byte, 1 = short, 2 = long) */
455 0, /* bitsize */
456 false, /* pc_relative */
457 0, /* bitpos */
458 complain_overflow_dont, /* complain_on_overflow */
459 bfd_elf_generic_reloc, /* special_function */
460 "R_MIPS_INSERT_B", /* name */
461 false, /* partial_inplace */
462 0, /* src_mask */
463 0, /* dst_mask */
464 false), /* pcrel_offset */
466 /* Delete a 32 bit instruction. */
467 /* FIXME: Not handled correctly. */
468 HOWTO (R_MIPS_DELETE, /* type */
469 0, /* rightshift */
470 0, /* size (0 = byte, 1 = short, 2 = long) */
471 0, /* bitsize */
472 false, /* pc_relative */
473 0, /* bitpos */
474 complain_overflow_dont, /* complain_on_overflow */
475 bfd_elf_generic_reloc, /* special_function */
476 "R_MIPS_DELETE", /* name */
477 false, /* partial_inplace */
478 0, /* src_mask */
479 0, /* dst_mask */
480 false), /* pcrel_offset */
482 /* Get the higher value of a 64 bit addend. */
483 /* FIXME: Not handled correctly. */
484 HOWTO (R_MIPS_HIGHER, /* type */
485 0, /* rightshift */
486 2, /* size (0 = byte, 1 = short, 2 = long) */
487 16, /* bitsize */
488 false, /* pc_relative */
489 0, /* bitpos */
490 complain_overflow_dont, /* complain_on_overflow */
491 bfd_elf_generic_reloc, /* special_function */
492 "R_MIPS_HIGHER", /* name */
493 true, /* partial_inplace */
494 0xffff, /* src_mask */
495 0xffff, /* dst_mask */
496 false), /* pcrel_offset */
498 /* Get the highest value of a 64 bit addend. */
499 /* FIXME: Not handled correctly. */
500 HOWTO (R_MIPS_HIGHEST, /* type */
501 0, /* rightshift */
502 2, /* size (0 = byte, 1 = short, 2 = long) */
503 16, /* bitsize */
504 false, /* pc_relative */
505 0, /* bitpos */
506 complain_overflow_dont, /* complain_on_overflow */
507 bfd_elf_generic_reloc, /* special_function */
508 "R_MIPS_HIGHEST", /* name */
509 true, /* partial_inplace */
510 0xffff, /* src_mask */
511 0xffff, /* dst_mask */
512 false), /* pcrel_offset */
514 /* High 16 bits of displacement in global offset table. */
515 /* FIXME: Not handled correctly. */
516 HOWTO (R_MIPS_CALL_HI16, /* type */
517 0, /* rightshift */
518 2, /* size (0 = byte, 1 = short, 2 = long) */
519 16, /* bitsize */
520 false, /* pc_relative */
521 0, /* bitpos */
522 complain_overflow_dont, /* complain_on_overflow */
523 bfd_elf_generic_reloc, /* special_function */
524 "R_MIPS_CALL_HI16", /* name */
525 true, /* partial_inplace */
526 0x0000ffff, /* src_mask */
527 0x0000ffff, /* dst_mask */
528 false), /* pcrel_offset */
530 /* Low 16 bits of displacement in global offset table. */
531 /* FIXME: Not handled correctly. */
532 HOWTO (R_MIPS_CALL_LO16, /* type */
533 0, /* rightshift */
534 2, /* size (0 = byte, 1 = short, 2 = long) */
535 16, /* bitsize */
536 false, /* pc_relative */
537 0, /* bitpos */
538 complain_overflow_dont, /* complain_on_overflow */
539 bfd_elf_generic_reloc, /* special_function */
540 "R_MIPS_CALL_LO16", /* name */
541 true, /* partial_inplace */
542 0x0000ffff, /* src_mask */
543 0x0000ffff, /* dst_mask */
544 false), /* pcrel_offset */
546 /* I'm not sure what the remaining relocs are, but they are defined
547 on Irix 6. */
549 HOWTO (R_MIPS_SCN_DISP, /* type */
550 0, /* rightshift */
551 0, /* size (0 = byte, 1 = short, 2 = long) */
552 0, /* bitsize */
553 false, /* pc_relative */
554 0, /* bitpos */
555 complain_overflow_dont, /* complain_on_overflow */
556 bfd_elf_generic_reloc, /* special_function */
557 "R_MIPS_SCN_DISP", /* name */
558 false, /* partial_inplace */
559 0, /* src_mask */
560 0, /* dst_mask */
561 false), /* pcrel_offset */
563 HOWTO (R_MIPS_REL16, /* type */
564 0, /* rightshift */
565 0, /* size (0 = byte, 1 = short, 2 = long) */
566 0, /* bitsize */
567 false, /* pc_relative */
568 0, /* bitpos */
569 complain_overflow_dont, /* complain_on_overflow */
570 bfd_elf_generic_reloc, /* special_function */
571 "R_MIPS_REL16", /* name */
572 false, /* partial_inplace */
573 0, /* src_mask */
574 0, /* dst_mask */
575 false), /* pcrel_offset */
577 HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
578 0, /* rightshift */
579 0, /* size (0 = byte, 1 = short, 2 = long) */
580 0, /* bitsize */
581 false, /* pc_relative */
582 0, /* bitpos */
583 complain_overflow_dont, /* complain_on_overflow */
584 bfd_elf_generic_reloc, /* special_function */
585 "R_MIPS_ADD_IMMEDIATE", /* name */
586 false, /* partial_inplace */
587 0, /* src_mask */
588 0, /* dst_mask */
589 false), /* pcrel_offset */
591 HOWTO (R_MIPS_PJUMP, /* type */
592 0, /* rightshift */
593 0, /* size (0 = byte, 1 = short, 2 = long) */
594 0, /* bitsize */
595 false, /* pc_relative */
596 0, /* bitpos */
597 complain_overflow_dont, /* complain_on_overflow */
598 bfd_elf_generic_reloc, /* special_function */
599 "R_MIPS_PJUMP", /* name */
600 false, /* partial_inplace */
601 0, /* src_mask */
602 0, /* dst_mask */
603 false), /* pcrel_offset */
605 HOWTO (R_MIPS_RELGOT, /* type */
606 0, /* rightshift */
607 0, /* size (0 = byte, 1 = short, 2 = long) */
608 0, /* bitsize */
609 false, /* pc_relative */
610 0, /* bitpos */
611 complain_overflow_dont, /* complain_on_overflow */
612 bfd_elf_generic_reloc, /* special_function */
613 "R_MIPS_RELGOT", /* name */
614 false, /* partial_inplace */
615 0, /* src_mask */
616 0, /* dst_mask */
617 false), /* pcrel_offset */
619 /* Protected jump conversion. This is an optimization hint. No
620 relocation is required for correctness. */
621 HOWTO (R_MIPS_JALR, /* type */
622 0, /* rightshift */
623 0, /* size (0 = byte, 1 = short, 2 = long) */
624 0, /* bitsize */
625 false, /* pc_relative */
626 0, /* bitpos */
627 complain_overflow_dont, /* complain_on_overflow */
628 bfd_elf_generic_reloc, /* special_function */
629 "R_MIPS_JALR", /* name */
630 false, /* partial_inplace */
631 0x00000000, /* src_mask */
632 0x00000000, /* dst_mask */
633 false), /* pcrel_offset */
636 /* The relocation table used for SHT_RELA sections. */
638 static reloc_howto_type mips_elf64_howto_table_rela[] =
640 /* No relocation. */
641 HOWTO (R_MIPS_NONE, /* type */
642 0, /* rightshift */
643 0, /* size (0 = byte, 1 = short, 2 = long) */
644 0, /* bitsize */
645 false, /* pc_relative */
646 0, /* bitpos */
647 complain_overflow_dont, /* complain_on_overflow */
648 bfd_elf_generic_reloc, /* special_function */
649 "R_MIPS_NONE", /* name */
650 false, /* partial_inplace */
651 0, /* src_mask */
652 0, /* dst_mask */
653 false), /* pcrel_offset */
655 /* 16 bit relocation. */
656 HOWTO (R_MIPS_16, /* type */
657 0, /* rightshift */
658 1, /* size (0 = byte, 1 = short, 2 = long) */
659 16, /* 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_16", /* name */
665 true, /* partial_inplace */
666 0, /* src_mask */
667 0xffff, /* dst_mask */
668 false), /* pcrel_offset */
670 /* 32 bit relocation. */
671 HOWTO (R_MIPS_32, /* 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_32", /* name */
680 true, /* partial_inplace */
681 0, /* src_mask */
682 0xffffffff, /* dst_mask */
683 false), /* pcrel_offset */
685 /* 32 bit symbol relative relocation. */
686 HOWTO (R_MIPS_REL32, /* type */
687 0, /* rightshift */
688 2, /* size (0 = byte, 1 = short, 2 = long) */
689 32, /* bitsize */
690 false, /* pc_relative */
691 0, /* bitpos */
692 complain_overflow_bitfield, /* complain_on_overflow */
693 bfd_elf_generic_reloc, /* special_function */
694 "R_MIPS_REL32", /* name */
695 true, /* partial_inplace */
696 0, /* src_mask */
697 0xffffffff, /* dst_mask */
698 false), /* pcrel_offset */
700 /* 26 bit branch address. */
701 HOWTO (R_MIPS_26, /* type */
702 2, /* rightshift */
703 2, /* size (0 = byte, 1 = short, 2 = long) */
704 26, /* bitsize */
705 false, /* pc_relative */
706 0, /* bitpos */
707 complain_overflow_dont, /* complain_on_overflow */
708 /* This needs complex overflow
709 detection, because the upper four
710 bits must match the PC. */
711 bfd_elf_generic_reloc, /* special_function */
712 "R_MIPS_26", /* name */
713 true, /* partial_inplace */
714 0, /* src_mask */
715 0x3ffffff, /* dst_mask */
716 false), /* pcrel_offset */
718 /* High 16 bits of symbol value. */
719 HOWTO (R_MIPS_HI16, /* 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_HI16", /* name */
728 true, /* partial_inplace */
729 0, /* src_mask */
730 0xffff, /* dst_mask */
731 false), /* pcrel_offset */
733 /* Low 16 bits of symbol value. */
734 HOWTO (R_MIPS_LO16, /* 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_dont, /* complain_on_overflow */
741 bfd_elf_generic_reloc, /* special_function */
742 "R_MIPS_LO16", /* name */
743 true, /* partial_inplace */
744 0, /* src_mask */
745 0xffff, /* dst_mask */
746 false), /* pcrel_offset */
748 /* GP relative reference. */
749 HOWTO (R_MIPS_GPREL16, /* 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 _bfd_mips_elf_gprel16_reloc, /* special_function */
757 "R_MIPS_GPREL16", /* name */
758 true, /* partial_inplace */
759 0, /* src_mask */
760 0xffff, /* dst_mask */
761 false), /* pcrel_offset */
763 /* Reference to literal section. */
764 HOWTO (R_MIPS_LITERAL, /* 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 _bfd_mips_elf_gprel16_reloc, /* special_function */
772 "R_MIPS_LITERAL", /* name */
773 true, /* partial_inplace */
774 0, /* src_mask */
775 0xffff, /* dst_mask */
776 false), /* pcrel_offset */
778 /* Reference to global offset table. */
779 /* FIXME: This is not handled correctly. */
780 HOWTO (R_MIPS_GOT16, /* type */
781 0, /* rightshift */
782 2, /* size (0 = byte, 1 = short, 2 = long) */
783 16, /* bitsize */
784 false, /* pc_relative */
785 0, /* bitpos */
786 complain_overflow_signed, /* complain_on_overflow */
787 bfd_elf_generic_reloc, /* special_function */
788 "R_MIPS_GOT16", /* name */
789 false, /* partial_inplace */
790 0, /* src_mask */
791 0xffff, /* dst_mask */
792 false), /* pcrel_offset */
794 /* 16 bit PC relative reference. */
795 HOWTO (R_MIPS_PC16, /* type */
796 0, /* rightshift */
797 2, /* size (0 = byte, 1 = short, 2 = long) */
798 16, /* bitsize */
799 true, /* pc_relative */
800 0, /* bitpos */
801 complain_overflow_signed, /* complain_on_overflow */
802 bfd_elf_generic_reloc, /* special_function */
803 "R_MIPS_PC16", /* name */
804 true, /* partial_inplace */
805 0, /* src_mask */
806 0xffff, /* dst_mask */
807 false), /* pcrel_offset */
809 /* 16 bit call through global offset table. */
810 /* FIXME: This is not handled correctly. */
811 HOWTO (R_MIPS_CALL16, /* type */
812 0, /* rightshift */
813 2, /* size (0 = byte, 1 = short, 2 = long) */
814 16, /* bitsize */
815 false, /* pc_relative */
816 0, /* bitpos */
817 complain_overflow_signed, /* complain_on_overflow */
818 bfd_elf_generic_reloc, /* special_function */
819 "R_MIPS_CALL16", /* name */
820 false, /* partial_inplace */
821 0, /* src_mask */
822 0xffff, /* dst_mask */
823 false), /* pcrel_offset */
825 /* 32 bit GP relative reference. */
826 HOWTO (R_MIPS_GPREL32, /* type */
827 0, /* rightshift */
828 2, /* size (0 = byte, 1 = short, 2 = long) */
829 32, /* bitsize */
830 false, /* pc_relative */
831 0, /* bitpos */
832 complain_overflow_bitfield, /* complain_on_overflow */
833 _bfd_mips_elf_gprel32_reloc, /* special_function */
834 "R_MIPS_GPREL32", /* name */
835 true, /* partial_inplace */
836 0, /* src_mask */
837 0xffffffff, /* dst_mask */
838 false), /* pcrel_offset */
840 { 13 },
841 { 14 },
842 { 15 },
844 /* A 5 bit shift field. */
845 HOWTO (R_MIPS_SHIFT5, /* type */
846 0, /* rightshift */
847 2, /* size (0 = byte, 1 = short, 2 = long) */
848 5, /* bitsize */
849 false, /* pc_relative */
850 6, /* bitpos */
851 complain_overflow_bitfield, /* complain_on_overflow */
852 bfd_elf_generic_reloc, /* special_function */
853 "R_MIPS_SHIFT5", /* name */
854 true, /* partial_inplace */
855 0, /* src_mask */
856 0x000007c0, /* dst_mask */
857 false), /* pcrel_offset */
859 /* A 6 bit shift field. */
860 /* FIXME: This is not handled correctly; a special function is
861 needed to put the most significant bit in the right place. */
862 HOWTO (R_MIPS_SHIFT6, /* type */
863 0, /* rightshift */
864 2, /* size (0 = byte, 1 = short, 2 = long) */
865 6, /* bitsize */
866 false, /* pc_relative */
867 6, /* bitpos */
868 complain_overflow_bitfield, /* complain_on_overflow */
869 bfd_elf_generic_reloc, /* special_function */
870 "R_MIPS_SHIFT6", /* name */
871 true, /* partial_inplace */
872 0, /* src_mask */
873 0x000007c4, /* dst_mask */
874 false), /* pcrel_offset */
876 /* 64 bit relocation. */
877 HOWTO (R_MIPS_64, /* type */
878 0, /* rightshift */
879 4, /* size (0 = byte, 1 = short, 2 = long) */
880 64, /* 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_64", /* name */
886 true, /* partial_inplace */
887 0, /* src_mask */
888 MINUS_ONE, /* dst_mask */
889 false), /* pcrel_offset */
891 /* Displacement in the global offset table. */
892 /* FIXME: Not handled correctly. */
893 HOWTO (R_MIPS_GOT_DISP, /* 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_DISP", /* name */
902 true, /* partial_inplace */
903 0, /* src_mask */
904 0x0000ffff, /* dst_mask */
905 false), /* pcrel_offset */
907 /* Displacement to page pointer in the global offset table. */
908 /* FIXME: Not handled correctly. */
909 HOWTO (R_MIPS_GOT_PAGE, /* 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_PAGE", /* name */
918 true, /* partial_inplace */
919 0, /* src_mask */
920 0x0000ffff, /* dst_mask */
921 false), /* pcrel_offset */
923 /* Offset from page pointer in the global offset table. */
924 /* FIXME: Not handled correctly. */
925 HOWTO (R_MIPS_GOT_OFST, /* 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_bitfield, /* complain_on_overflow */
932 bfd_elf_generic_reloc, /* special_function */
933 "R_MIPS_GOT_OFST", /* name */
934 true, /* partial_inplace */
935 0, /* src_mask */
936 0x0000ffff, /* dst_mask */
937 false), /* pcrel_offset */
939 /* High 16 bits of displacement in global offset table. */
940 /* FIXME: Not handled correctly. */
941 HOWTO (R_MIPS_GOT_HI16, /* 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_HI16", /* name */
950 true, /* partial_inplace */
951 0, /* src_mask */
952 0x0000ffff, /* dst_mask */
953 false), /* pcrel_offset */
955 /* Low 16 bits of displacement in global offset table. */
956 /* FIXME: Not handled correctly. */
957 HOWTO (R_MIPS_GOT_LO16, /* type */
958 0, /* rightshift */
959 2, /* size (0 = byte, 1 = short, 2 = long) */
960 16, /* bitsize */
961 false, /* pc_relative */
962 0, /* bitpos */
963 complain_overflow_dont, /* complain_on_overflow */
964 bfd_elf_generic_reloc, /* special_function */
965 "R_MIPS_GOT_LO16", /* name */
966 true, /* partial_inplace */
967 0, /* src_mask */
968 0x0000ffff, /* dst_mask */
969 false), /* pcrel_offset */
971 /* 64 bit substraction. */
972 /* FIXME: Not handled correctly. */
973 HOWTO (R_MIPS_SUB, /* type */
974 0, /* rightshift */
975 4, /* size (0 = byte, 1 = short, 2 = long) */
976 64, /* bitsize */
977 false, /* pc_relative */
978 0, /* bitpos */
979 complain_overflow_bitfield, /* complain_on_overflow */
980 bfd_elf_generic_reloc, /* special_function */
981 "R_MIPS_SUB", /* name */
982 true, /* partial_inplace */
983 0, /* src_mask */
984 MINUS_ONE, /* dst_mask */
985 false), /* pcrel_offset */
987 /* Insert the addend as an instruction. */
988 /* FIXME: Not handled correctly. */
989 HOWTO (R_MIPS_INSERT_A, /* type */
990 0, /* rightshift */
991 0, /* size (0 = byte, 1 = short, 2 = long) */
992 0, /* bitsize */
993 false, /* pc_relative */
994 0, /* bitpos */
995 complain_overflow_dont, /* complain_on_overflow */
996 bfd_elf_generic_reloc, /* special_function */
997 "R_MIPS_INSERT_A", /* name */
998 false, /* partial_inplace */
999 0, /* src_mask */
1000 0, /* dst_mask */
1001 false), /* pcrel_offset */
1003 /* Insert the addend as an instruction, and change all relocations
1004 to refer to the old instruction at the address. */
1005 /* FIXME: Not handled correctly. */
1006 HOWTO (R_MIPS_INSERT_B, /* 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_INSERT_B", /* name */
1015 false, /* partial_inplace */
1016 0, /* src_mask */
1017 0, /* dst_mask */
1018 false), /* pcrel_offset */
1020 /* Delete a 32 bit instruction. */
1021 /* FIXME: Not handled correctly. */
1022 HOWTO (R_MIPS_DELETE, /* type */
1023 0, /* rightshift */
1024 0, /* size (0 = byte, 1 = short, 2 = long) */
1025 0, /* 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_DELETE", /* name */
1031 false, /* partial_inplace */
1032 0, /* src_mask */
1033 0, /* dst_mask */
1034 false), /* pcrel_offset */
1036 /* Get the higher value of a 64 bit addend. */
1037 /* FIXME: Not handled correctly. */
1038 HOWTO (R_MIPS_HIGHER, /* 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_HIGHER", /* name */
1047 true, /* partial_inplace */
1048 0, /* src_mask */
1049 0xffff, /* dst_mask */
1050 false), /* pcrel_offset */
1052 /* Get the highest value of a 64 bit addend. */
1053 /* FIXME: Not handled correctly. */
1054 HOWTO (R_MIPS_HIGHEST, /* 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_HIGHEST", /* name */
1063 true, /* partial_inplace */
1064 0, /* src_mask */
1065 0xffff, /* dst_mask */
1066 false), /* pcrel_offset */
1068 /* High 16 bits of displacement in global offset table. */
1069 /* FIXME: Not handled correctly. */
1070 HOWTO (R_MIPS_CALL_HI16, /* 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_HI16", /* name */
1079 true, /* partial_inplace */
1080 0, /* src_mask */
1081 0x0000ffff, /* dst_mask */
1082 false), /* pcrel_offset */
1084 /* Low 16 bits of displacement in global offset table. */
1085 /* FIXME: Not handled correctly. */
1086 HOWTO (R_MIPS_CALL_LO16, /* type */
1087 0, /* rightshift */
1088 2, /* size (0 = byte, 1 = short, 2 = long) */
1089 16, /* bitsize */
1090 false, /* pc_relative */
1091 0, /* bitpos */
1092 complain_overflow_dont, /* complain_on_overflow */
1093 bfd_elf_generic_reloc, /* special_function */
1094 "R_MIPS_CALL_LO16", /* name */
1095 true, /* partial_inplace */
1096 0, /* src_mask */
1097 0x0000ffff, /* dst_mask */
1098 false), /* pcrel_offset */
1100 /* I'm not sure what the remaining relocs are, but they are defined
1101 on Irix 6. */
1103 HOWTO (R_MIPS_SCN_DISP, /* type */
1104 0, /* rightshift */
1105 0, /* size (0 = byte, 1 = short, 2 = long) */
1106 0, /* bitsize */
1107 false, /* pc_relative */
1108 0, /* bitpos */
1109 complain_overflow_dont, /* complain_on_overflow */
1110 bfd_elf_generic_reloc, /* special_function */
1111 "R_MIPS_SCN_DISP", /* name */
1112 false, /* partial_inplace */
1113 0, /* src_mask */
1114 0, /* dst_mask */
1115 false), /* pcrel_offset */
1117 HOWTO (R_MIPS_REL16, /* type */
1118 0, /* rightshift */
1119 0, /* size (0 = byte, 1 = short, 2 = long) */
1120 0, /* bitsize */
1121 false, /* pc_relative */
1122 0, /* bitpos */
1123 complain_overflow_dont, /* complain_on_overflow */
1124 bfd_elf_generic_reloc, /* special_function */
1125 "R_MIPS_REL16", /* name */
1126 false, /* partial_inplace */
1127 0, /* src_mask */
1128 0, /* dst_mask */
1129 false), /* pcrel_offset */
1131 HOWTO (R_MIPS_ADD_IMMEDIATE, /* type */
1132 0, /* rightshift */
1133 0, /* size (0 = byte, 1 = short, 2 = long) */
1134 0, /* bitsize */
1135 false, /* pc_relative */
1136 0, /* bitpos */
1137 complain_overflow_dont, /* complain_on_overflow */
1138 bfd_elf_generic_reloc, /* special_function */
1139 "R_MIPS_ADD_IMMEDIATE", /* name */
1140 false, /* partial_inplace */
1141 0, /* src_mask */
1142 0, /* dst_mask */
1143 false), /* pcrel_offset */
1145 HOWTO (R_MIPS_PJUMP, /* type */
1146 0, /* rightshift */
1147 0, /* size (0 = byte, 1 = short, 2 = long) */
1148 0, /* bitsize */
1149 false, /* pc_relative */
1150 0, /* bitpos */
1151 complain_overflow_dont, /* complain_on_overflow */
1152 bfd_elf_generic_reloc, /* special_function */
1153 "R_MIPS_PJUMP", /* name */
1154 false, /* partial_inplace */
1155 0, /* src_mask */
1156 0, /* dst_mask */
1157 false), /* pcrel_offset */
1159 HOWTO (R_MIPS_RELGOT, /* type */
1160 0, /* rightshift */
1161 0, /* size (0 = byte, 1 = short, 2 = long) */
1162 0, /* bitsize */
1163 false, /* pc_relative */
1164 0, /* bitpos */
1165 complain_overflow_dont, /* complain_on_overflow */
1166 bfd_elf_generic_reloc, /* special_function */
1167 "R_MIPS_RELGOT", /* name */
1168 false, /* partial_inplace */
1169 0, /* src_mask */
1170 0, /* dst_mask */
1171 false), /* pcrel_offset */
1173 /* Protected jump conversion. This is an optimization hint. No
1174 relocation is required for correctness. */
1175 HOWTO (R_MIPS_JALR, /* type */
1176 0, /* rightshift */
1177 0, /* size (0 = byte, 1 = short, 2 = long) */
1178 0, /* bitsize */
1179 false, /* pc_relative */
1180 0, /* bitpos */
1181 complain_overflow_dont, /* complain_on_overflow */
1182 bfd_elf_generic_reloc, /* special_function */
1183 "R_MIPS_JALR", /* name */
1184 false, /* partial_inplace */
1185 0x00000000, /* src_mask */
1186 0x00000000, /* dst_mask */
1187 false), /* pcrel_offset */
1190 /* Swap in a MIPS 64-bit Rel reloc. */
1192 static void
1193 mips_elf64_swap_reloc_in (abfd, src, dst)
1194 bfd *abfd;
1195 const Elf64_Mips_External_Rel *src;
1196 Elf64_Mips_Internal_Rel *dst;
1198 dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
1199 dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
1200 dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
1201 dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
1202 dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
1203 dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
1206 /* Swap in a MIPS 64-bit Rela reloc. */
1208 static void
1209 mips_elf64_swap_reloca_in (abfd, src, dst)
1210 bfd *abfd;
1211 const Elf64_Mips_External_Rela *src;
1212 Elf64_Mips_Internal_Rela *dst;
1214 dst->r_offset = bfd_h_get_64 (abfd, (bfd_byte *) src->r_offset);
1215 dst->r_sym = bfd_h_get_32 (abfd, (bfd_byte *) src->r_sym);
1216 dst->r_ssym = bfd_h_get_8 (abfd, (bfd_byte *) src->r_ssym);
1217 dst->r_type3 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type3);
1218 dst->r_type2 = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type2);
1219 dst->r_type = bfd_h_get_8 (abfd, (bfd_byte *) src->r_type);
1220 dst->r_addend = bfd_h_get_signed_64 (abfd, (bfd_byte *) src->r_addend);
1223 #if 0
1225 /* This is not currently used. */
1227 /* Swap out a MIPS 64-bit Rel reloc. */
1229 static void
1230 mips_elf64_swap_reloc_out (abfd, src, dst)
1231 bfd *abfd;
1232 const Elf64_Mips_Internal_Rel *src;
1233 Elf64_Mips_External_Rel *dst;
1235 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1236 bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
1237 bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
1238 bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
1239 bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
1240 bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
1243 #endif /* 0 */
1245 /* Swap out a MIPS 64-bit Rela reloc. */
1247 static void
1248 mips_elf64_swap_reloca_out (abfd, src, dst)
1249 bfd *abfd;
1250 const Elf64_Mips_Internal_Rela *src;
1251 Elf64_Mips_External_Rela *dst;
1253 bfd_h_put_64 (abfd, src->r_offset, (bfd_byte *) dst->r_offset);
1254 bfd_h_put_32 (abfd, src->r_sym, (bfd_byte *) dst->r_sym);
1255 bfd_h_put_8 (abfd, src->r_ssym, (bfd_byte *) dst->r_ssym);
1256 bfd_h_put_8 (abfd, src->r_type3, (bfd_byte *) dst->r_type3);
1257 bfd_h_put_8 (abfd, src->r_type2, (bfd_byte *) dst->r_type2);
1258 bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type);
1259 bfd_h_put_64 (abfd, src->r_addend, (bfd_byte *) dst->r_addend);
1262 /* A mapping from BFD reloc types to MIPS ELF reloc types. */
1264 struct elf_reloc_map
1266 bfd_reloc_code_real_type bfd_reloc_val;
1267 enum elf_mips_reloc_type elf_reloc_val;
1270 static CONST struct elf_reloc_map mips_reloc_map[] =
1272 { BFD_RELOC_NONE, R_MIPS_NONE, },
1273 { BFD_RELOC_16, R_MIPS_16 },
1274 { BFD_RELOC_32, R_MIPS_32 },
1275 { BFD_RELOC_64, R_MIPS_64 },
1276 { BFD_RELOC_CTOR, R_MIPS_64 },
1277 { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
1278 { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
1279 { BFD_RELOC_HI16_S, R_MIPS_HI16 },
1280 { BFD_RELOC_LO16, R_MIPS_LO16 },
1281 { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 },
1282 { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
1283 { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
1284 { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
1285 { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
1286 { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 },
1287 { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
1288 { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
1289 { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
1290 { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
1291 { BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
1292 { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
1293 { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
1294 { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP }
1297 /* Given a BFD reloc type, return a howto structure. */
1299 static reloc_howto_type *
1300 mips_elf64_reloc_type_lookup (abfd, code)
1301 bfd *abfd;
1302 bfd_reloc_code_real_type code;
1304 unsigned int i;
1306 for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
1308 if (mips_reloc_map[i].bfd_reloc_val == code)
1310 int v;
1312 v = (int) mips_reloc_map[i].elf_reloc_val;
1313 return &mips_elf64_howto_table_rel[v];
1317 return NULL;
1320 /* Since each entry in an SHT_REL or SHT_RELA section can represent up
1321 to three relocs, we must tell the user to allocate more space. */
1323 static long
1324 mips_elf64_get_reloc_upper_bound (abfd, sec)
1325 bfd *abfd;
1326 asection *sec;
1328 return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
1331 /* Read the relocations from one reloc section. */
1333 static boolean
1334 mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
1335 bfd *abfd;
1336 asection *asect;
1337 asymbol **symbols;
1338 const Elf_Internal_Shdr *rel_hdr;
1340 PTR allocated = NULL;
1341 bfd_byte *native_relocs;
1342 arelent *relents;
1343 arelent *relent;
1344 unsigned int count;
1345 unsigned int i;
1346 int entsize;
1347 reloc_howto_type *howto_table;
1349 allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
1350 if (allocated == NULL)
1351 goto error_return;
1353 if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
1354 || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
1355 goto error_return;
1357 native_relocs = (bfd_byte *) allocated;
1359 relents = asect->relocation + asect->reloc_count;
1361 entsize = rel_hdr->sh_entsize;
1362 BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
1363 || entsize == sizeof (Elf64_Mips_External_Rela));
1365 count = rel_hdr->sh_size / entsize;
1367 if (entsize == sizeof (Elf64_Mips_External_Rel))
1368 howto_table = mips_elf64_howto_table_rel;
1369 else
1370 howto_table = mips_elf64_howto_table_rela;
1372 relent = relents;
1373 for (i = 0; i < count; i++, native_relocs += entsize)
1375 Elf64_Mips_Internal_Rela rela;
1376 boolean used_sym, used_ssym;
1377 int ir;
1379 if (entsize == sizeof (Elf64_Mips_External_Rela))
1380 mips_elf64_swap_reloca_in (abfd,
1381 (Elf64_Mips_External_Rela *) native_relocs,
1382 &rela);
1383 else
1385 Elf64_Mips_Internal_Rel rel;
1387 mips_elf64_swap_reloc_in (abfd,
1388 (Elf64_Mips_External_Rel *) native_relocs,
1389 &rel);
1390 rela.r_offset = rel.r_offset;
1391 rela.r_sym = rel.r_sym;
1392 rela.r_ssym = rel.r_ssym;
1393 rela.r_type3 = rel.r_type3;
1394 rela.r_type2 = rel.r_type2;
1395 rela.r_type = rel.r_type;
1396 rela.r_addend = 0;
1399 /* Each entry represents up to three actual relocations. */
1401 used_sym = false;
1402 used_ssym = false;
1403 for (ir = 0; ir < 3; ir++)
1405 enum elf_mips_reloc_type type;
1407 switch (ir)
1409 default:
1410 abort ();
1411 case 0:
1412 type = (enum elf_mips_reloc_type) rela.r_type;
1413 break;
1414 case 1:
1415 type = (enum elf_mips_reloc_type) rela.r_type2;
1416 break;
1417 case 2:
1418 type = (enum elf_mips_reloc_type) rela.r_type3;
1419 break;
1422 if (type == R_MIPS_NONE)
1424 /* There are no more relocations in this entry. If this
1425 is the first entry, we need to generate a dummy
1426 relocation so that the generic linker knows that
1427 there has been a break in the sequence of relocations
1428 applying to a particular address. */
1429 if (ir == 0)
1431 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1432 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1433 relent->address = rela.r_offset;
1434 else
1435 relent->address = rela.r_offset - asect->vma;
1436 relent->addend = 0;
1437 relent->howto = &howto_table[(int) R_MIPS_NONE];
1438 ++relent;
1440 break;
1443 /* Some types require symbols, whereas some do not. */
1444 switch (type)
1446 case R_MIPS_NONE:
1447 case R_MIPS_LITERAL:
1448 case R_MIPS_INSERT_A:
1449 case R_MIPS_INSERT_B:
1450 case R_MIPS_DELETE:
1451 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1452 break;
1454 default:
1455 if (! used_sym)
1457 if (rela.r_sym == 0)
1458 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1459 else
1461 asymbol **ps, *s;
1463 ps = symbols + rela.r_sym - 1;
1464 s = *ps;
1465 if ((s->flags & BSF_SECTION_SYM) == 0)
1466 relent->sym_ptr_ptr = ps;
1467 else
1468 relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
1471 used_sym = true;
1473 else if (! used_ssym)
1475 switch (rela.r_ssym)
1477 case RSS_UNDEF:
1478 relent->sym_ptr_ptr =
1479 bfd_abs_section_ptr->symbol_ptr_ptr;
1480 break;
1482 case RSS_GP:
1483 case RSS_GP0:
1484 case RSS_LOC:
1485 /* FIXME: I think these need to be handled using
1486 special howto structures. */
1487 BFD_ASSERT (0);
1488 break;
1490 default:
1491 BFD_ASSERT (0);
1492 break;
1495 used_ssym = true;
1497 else
1498 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1500 break;
1503 /* The address of an ELF reloc is section relative for an
1504 object file, and absolute for an executable file or
1505 shared library. The address of a BFD reloc is always
1506 section relative. */
1507 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1508 relent->address = rela.r_offset;
1509 else
1510 relent->address = rela.r_offset - asect->vma;
1512 relent->addend = rela.r_addend;
1514 relent->howto = &howto_table[(int) type];
1516 ++relent;
1520 asect->reloc_count += relent - relents;
1522 if (allocated != NULL)
1523 free (allocated);
1525 return true;
1527 error_return:
1528 if (allocated != NULL)
1529 free (allocated);
1530 return false;
1533 /* Read the relocations. On Irix 6, there can be two reloc sections
1534 associated with a single data section. */
1536 static boolean
1537 mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
1538 bfd *abfd;
1539 asection *asect;
1540 asymbol **symbols;
1541 boolean dynamic;
1543 struct bfd_elf_section_data * const d = elf_section_data (asect);
1545 if (dynamic)
1547 bfd_set_error (bfd_error_invalid_operation);
1548 return false;
1551 if (asect->relocation != NULL
1552 || (asect->flags & SEC_RELOC) == 0
1553 || asect->reloc_count == 0)
1554 return true;
1556 /* Allocate space for 3 arelent structures for each Rel structure. */
1557 asect->relocation = ((arelent *)
1558 bfd_alloc (abfd,
1559 asect->reloc_count * 3 * sizeof (arelent)));
1560 if (asect->relocation == NULL)
1561 return false;
1563 /* The slurp_one_reloc_table routine increments reloc_count. */
1564 asect->reloc_count = 0;
1566 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
1567 return false;
1568 if (d->rel_hdr2 != NULL)
1570 if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
1571 d->rel_hdr2))
1572 return false;
1575 return true;
1578 /* Write out the relocations. */
1580 static void
1581 mips_elf64_write_relocs (abfd, sec, data)
1582 bfd *abfd;
1583 asection *sec;
1584 PTR data;
1586 boolean *failedp = (boolean *) data;
1587 unsigned int count;
1588 Elf_Internal_Shdr *rela_hdr;
1589 Elf64_Mips_External_Rela *ext_rela;
1590 unsigned int idx;
1591 asymbol *last_sym = 0;
1592 int last_sym_idx = 0;
1594 /* If we have already failed, don't do anything. */
1595 if (*failedp)
1596 return;
1598 if ((sec->flags & SEC_RELOC) == 0)
1599 return;
1601 /* The linker backend writes the relocs out itself, and sets the
1602 reloc_count field to zero to inhibit writing them here. Also,
1603 sometimes the SEC_RELOC flag gets set even when there aren't any
1604 relocs. */
1605 if (sec->reloc_count == 0)
1606 return;
1608 /* We can combine up to three relocs that refer to the same address
1609 if the latter relocs have no associated symbol. */
1610 count = 0;
1611 for (idx = 0; idx < sec->reloc_count; idx++)
1613 bfd_vma addr;
1614 unsigned int i;
1616 ++count;
1618 addr = sec->orelocation[idx]->address;
1619 for (i = 0; i < 2; i++)
1621 arelent *r;
1623 if (idx + 1 >= sec->reloc_count)
1624 break;
1625 r = sec->orelocation[idx + 1];
1626 if (r->address != addr
1627 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
1628 || (*r->sym_ptr_ptr)->value != 0)
1629 break;
1631 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1633 ++idx;
1637 rela_hdr = &elf_section_data (sec)->rel_hdr;
1639 rela_hdr->sh_size = rela_hdr->sh_entsize * count;
1640 rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
1641 if (rela_hdr->contents == NULL)
1643 *failedp = true;
1644 return;
1647 ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
1648 for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
1650 arelent *ptr;
1651 Elf64_Mips_Internal_Rela int_rela;
1652 asymbol *sym;
1653 int n;
1654 unsigned int i;
1656 ptr = sec->orelocation[idx];
1658 /* The address of an ELF reloc is section relative for an object
1659 file, and absolute for an executable file or shared library.
1660 The address of a BFD reloc is always section relative. */
1661 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
1662 int_rela.r_offset = ptr->address;
1663 else
1664 int_rela.r_offset = ptr->address + sec->vma;
1666 sym = *ptr->sym_ptr_ptr;
1667 if (sym == last_sym)
1668 n = last_sym_idx;
1669 else
1671 last_sym = sym;
1672 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
1673 if (n < 0)
1675 *failedp = true;
1676 return;
1678 last_sym_idx = n;
1681 int_rela.r_sym = n;
1683 int_rela.r_addend = ptr->addend;
1685 int_rela.r_ssym = RSS_UNDEF;
1687 if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
1688 && ! _bfd_elf_validate_reloc (abfd, ptr))
1690 *failedp = true;
1691 return;
1694 int_rela.r_type = ptr->howto->type;
1695 int_rela.r_type2 = (int) R_MIPS_NONE;
1696 int_rela.r_type3 = (int) R_MIPS_NONE;
1698 for (i = 0; i < 2; i++)
1700 arelent *r;
1702 if (idx + 1 >= sec->reloc_count)
1703 break;
1704 r = sec->orelocation[idx + 1];
1705 if (r->address != ptr->address
1706 || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
1707 || (*r->sym_ptr_ptr)->value != 0)
1708 break;
1710 /* We can merge the reloc at IDX + 1 with the reloc at IDX. */
1712 if (i == 0)
1713 int_rela.r_type2 = r->howto->type;
1714 else
1715 int_rela.r_type3 = r->howto->type;
1717 ++idx;
1720 mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
1723 BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
1724 == count);
1727 /* Handle a 64-bit MIPS ELF specific section. */
1729 static boolean
1730 mips_elf64_section_from_shdr (abfd, hdr, name)
1731 bfd *abfd;
1732 Elf_Internal_Shdr *hdr;
1733 char *name;
1735 if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
1736 return false;
1738 /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
1739 set the gp value based on what we find. We may see both
1740 SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
1741 they should agree. */
1742 if (hdr->sh_type == SHT_MIPS_OPTIONS)
1744 bfd_byte *contents, *l, *lend;
1746 contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
1747 if (contents == NULL)
1748 return false;
1749 if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
1750 (file_ptr) 0, hdr->sh_size))
1752 free (contents);
1753 return false;
1755 l = contents;
1756 lend = contents + hdr->sh_size;
1757 while (l + sizeof (Elf_External_Options) <= lend)
1759 Elf_Internal_Options intopt;
1761 bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
1762 &intopt);
1763 if (intopt.kind == ODK_REGINFO)
1765 Elf64_Internal_RegInfo intreg;
1767 bfd_mips_elf64_swap_reginfo_in
1768 (abfd,
1769 ((Elf64_External_RegInfo *)
1770 (l + sizeof (Elf_External_Options))),
1771 &intreg);
1772 elf_gp (abfd) = intreg.ri_gp_value;
1774 l += intopt.size;
1776 free (contents);
1779 return true;
1782 /* Work over a section just before writing it out. We update the GP
1783 value in the SHT_MIPS_OPTIONS section based on the value we are
1784 using. */
1786 static boolean
1787 mips_elf64_section_processing (abfd, hdr)
1788 bfd *abfd;
1789 Elf_Internal_Shdr *hdr;
1791 if (hdr->sh_type == SHT_MIPS_OPTIONS
1792 && hdr->bfd_section != NULL
1793 && elf_section_data (hdr->bfd_section) != NULL
1794 && elf_section_data (hdr->bfd_section)->tdata != NULL)
1796 bfd_byte *contents, *l, *lend;
1798 /* We stored the section contents in the elf_section_data tdata
1799 field in the set_section_contents routine. We save the
1800 section contents so that we don't have to read them again.
1801 At this point we know that elf_gp is set, so we can look
1802 through the section contents to see if there is an
1803 ODK_REGINFO structure. */
1805 contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
1806 l = contents;
1807 lend = contents + hdr->sh_size;
1808 while (l + sizeof (Elf_External_Options) <= lend)
1810 Elf_Internal_Options intopt;
1812 bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
1813 &intopt);
1814 if (intopt.kind == ODK_REGINFO)
1816 bfd_byte buf[8];
1818 if (bfd_seek (abfd,
1819 (hdr->sh_offset
1820 + (l - contents)
1821 + sizeof (Elf_External_Options)
1822 + (sizeof (Elf64_External_RegInfo) - 8)),
1823 SEEK_SET) == -1)
1824 return false;
1825 bfd_h_put_64 (abfd, elf_gp (abfd), buf);
1826 if (bfd_write (buf, 1, 8, abfd) != 8)
1827 return false;
1829 l += intopt.size;
1833 return _bfd_mips_elf_section_processing (abfd, hdr);
1836 /* Irix 6 defines a brand new archive map format, so that they can
1837 have archives more than 4 GB in size. */
1839 /* Read an Irix 6 armap. */
1841 static boolean
1842 mips_elf64_slurp_armap (abfd)
1843 bfd *abfd;
1845 struct artdata *ardata = bfd_ardata (abfd);
1846 char nextname[17];
1847 file_ptr arhdrpos;
1848 bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
1849 struct areltdata *mapdata;
1850 bfd_byte int_buf[8];
1851 char *stringbase;
1852 bfd_byte *raw_armap = NULL;
1853 carsym *carsyms;
1855 ardata->symdefs = NULL;
1857 /* Get the name of the first element. */
1858 arhdrpos = bfd_tell (abfd);
1859 i = bfd_read ((PTR) nextname, 1, 16, abfd);
1860 if (i == 0)
1861 return true;
1862 if (i != 16)
1863 return false;
1865 if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
1866 return false;
1868 /* Archives with traditional armaps are still permitted. */
1869 if (strncmp (nextname, "/ ", 16) == 0)
1870 return bfd_slurp_armap (abfd);
1872 if (strncmp (nextname, "/SYM64/ ", 16) != 0)
1874 bfd_has_map (abfd) = false;
1875 return true;
1878 mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
1879 if (mapdata == NULL)
1880 return false;
1881 parsed_size = mapdata->parsed_size;
1882 bfd_release (abfd, (PTR) mapdata);
1884 if (bfd_read (int_buf, 1, 8, abfd) != 8)
1886 if (bfd_get_error () != bfd_error_system_call)
1887 bfd_set_error (bfd_error_malformed_archive);
1888 return false;
1891 nsymz = bfd_getb64 (int_buf);
1892 stringsize = parsed_size - 8 * nsymz - 8;
1894 carsym_size = nsymz * sizeof (carsym);
1895 ptrsize = 8 * nsymz;
1897 ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1);
1898 if (ardata->symdefs == NULL)
1899 return false;
1900 carsyms = ardata->symdefs;
1901 stringbase = ((char *) ardata->symdefs) + carsym_size;
1903 raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
1904 if (raw_armap == NULL)
1905 goto error_return;
1907 if (bfd_read (raw_armap, 1, ptrsize, abfd) != ptrsize
1908 || bfd_read (stringbase, 1, stringsize, abfd) != stringsize)
1910 if (bfd_get_error () != bfd_error_system_call)
1911 bfd_set_error (bfd_error_malformed_archive);
1912 goto error_return;
1915 for (i = 0; i < nsymz; i++)
1917 carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
1918 carsyms->name = stringbase;
1919 stringbase += strlen (stringbase) + 1;
1920 ++carsyms;
1922 *stringbase = '\0';
1924 ardata->symdef_count = nsymz;
1925 ardata->first_file_filepos = arhdrpos + sizeof (struct ar_hdr) + parsed_size;
1927 bfd_has_map (abfd) = true;
1928 bfd_release (abfd, raw_armap);
1930 return true;
1932 error_return:
1933 if (raw_armap != NULL)
1934 bfd_release (abfd, raw_armap);
1935 if (ardata->symdefs != NULL)
1936 bfd_release (abfd, ardata->symdefs);
1937 return false;
1940 /* Write out an Irix 6 armap. The Irix 6 tools are supposed to be
1941 able to handle ordinary ELF armaps, but at least on Irix 6.2 the
1942 linker crashes. */
1944 static boolean
1945 mips_elf64_write_armap (arch, elength, map, symbol_count, stridx)
1946 bfd *arch;
1947 unsigned int elength;
1948 struct orl *map;
1949 unsigned int symbol_count;
1950 int stridx;
1952 unsigned int ranlibsize = (symbol_count * 8) + 8;
1953 unsigned int stringsize = stridx;
1954 unsigned int mapsize = stringsize + ranlibsize;
1955 file_ptr archive_member_file_ptr;
1956 bfd *current = arch->archive_head;
1957 unsigned int count;
1958 struct ar_hdr hdr;
1959 unsigned int i;
1960 int padding;
1961 bfd_byte buf[8];
1963 padding = BFD_ALIGN (mapsize, 8) - mapsize;
1964 mapsize += padding;
1966 /* work out where the first object file will go in the archive */
1967 archive_member_file_ptr = (mapsize
1968 + elength
1969 + sizeof (struct ar_hdr)
1970 + SARMAG);
1972 memset ((char *) (&hdr), 0, sizeof (struct ar_hdr));
1973 strcpy (hdr.ar_name, "/SYM64/");
1974 sprintf (hdr.ar_size, "%-10d", (int) mapsize);
1975 sprintf (hdr.ar_date, "%ld", (long) time (NULL));
1976 /* This, at least, is what Intel coff sets the values to.: */
1977 sprintf ((hdr.ar_uid), "%d", 0);
1978 sprintf ((hdr.ar_gid), "%d", 0);
1979 sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0);
1980 strncpy (hdr.ar_fmag, ARFMAG, 2);
1982 for (i = 0; i < sizeof (struct ar_hdr); i++)
1983 if (((char *) (&hdr))[i] == '\0')
1984 (((char *) (&hdr))[i]) = ' ';
1986 /* Write the ar header for this item and the number of symbols */
1988 if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), arch)
1989 != sizeof (struct ar_hdr))
1990 return false;
1992 bfd_putb64 (symbol_count, buf);
1993 if (bfd_write (buf, 1, 8, arch) != 8)
1994 return false;
1996 /* Two passes, first write the file offsets for each symbol -
1997 remembering that each offset is on a two byte boundary. */
1999 /* Write out the file offset for the file associated with each
2000 symbol, and remember to keep the offsets padded out. */
2002 current = arch->archive_head;
2003 count = 0;
2004 while (current != (bfd *) NULL && count < symbol_count)
2006 /* For each symbol which is used defined in this object, write out
2007 the object file's address in the archive */
2009 while (((bfd *) (map[count]).pos) == current)
2011 bfd_putb64 (archive_member_file_ptr, buf);
2012 if (bfd_write (buf, 1, 8, arch) != 8)
2013 return false;
2014 count++;
2016 /* Add size of this archive entry */
2017 archive_member_file_ptr += (arelt_size (current)
2018 + sizeof (struct ar_hdr));
2019 /* remember about the even alignment */
2020 archive_member_file_ptr += archive_member_file_ptr % 2;
2021 current = current->next;
2024 /* now write the strings themselves */
2025 for (count = 0; count < symbol_count; count++)
2027 size_t len = strlen (*map[count].name) + 1;
2029 if (bfd_write (*map[count].name, 1, len, arch) != len)
2030 return false;
2033 /* The spec says that this should be padded to an 8 byte boundary.
2034 However, the Irix 6.2 tools do not appear to do this. */
2035 while (padding != 0)
2037 if (bfd_write ("", 1, 1, arch) != 1)
2038 return false;
2039 --padding;
2042 return true;
2045 /* ECOFF swapping routines. These are used when dealing with the
2046 .mdebug section, which is in the ECOFF debugging format. */
2047 static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
2049 /* Symbol table magic number. */
2050 magicSym2,
2051 /* Alignment of debugging information. E.g., 4. */
2053 /* Sizes of external symbolic information. */
2054 sizeof (struct hdr_ext),
2055 sizeof (struct dnr_ext),
2056 sizeof (struct pdr_ext),
2057 sizeof (struct sym_ext),
2058 sizeof (struct opt_ext),
2059 sizeof (struct fdr_ext),
2060 sizeof (struct rfd_ext),
2061 sizeof (struct ext_ext),
2062 /* Functions to swap in external symbolic data. */
2063 ecoff_swap_hdr_in,
2064 ecoff_swap_dnr_in,
2065 ecoff_swap_pdr_in,
2066 ecoff_swap_sym_in,
2067 ecoff_swap_opt_in,
2068 ecoff_swap_fdr_in,
2069 ecoff_swap_rfd_in,
2070 ecoff_swap_ext_in,
2071 _bfd_ecoff_swap_tir_in,
2072 _bfd_ecoff_swap_rndx_in,
2073 /* Functions to swap out external symbolic data. */
2074 ecoff_swap_hdr_out,
2075 ecoff_swap_dnr_out,
2076 ecoff_swap_pdr_out,
2077 ecoff_swap_sym_out,
2078 ecoff_swap_opt_out,
2079 ecoff_swap_fdr_out,
2080 ecoff_swap_rfd_out,
2081 ecoff_swap_ext_out,
2082 _bfd_ecoff_swap_tir_out,
2083 _bfd_ecoff_swap_rndx_out,
2084 /* Function to read in symbolic data. */
2085 _bfd_mips_elf_read_ecoff_info
2088 /* Relocations in the 64 bit MIPS ELF ABI are more complex than in
2089 standard ELF. This structure is used to redirect the relocation
2090 handling routines. */
2092 const struct elf_size_info mips_elf64_size_info =
2094 sizeof (Elf64_External_Ehdr),
2095 sizeof (Elf64_External_Phdr),
2096 sizeof (Elf64_External_Shdr),
2097 sizeof (Elf64_Mips_External_Rel),
2098 sizeof (Elf64_Mips_External_Rela),
2099 sizeof (Elf64_External_Sym),
2100 sizeof (Elf64_External_Dyn),
2101 sizeof (Elf_External_Note),
2102 64, /* arch_size */
2103 8, /* file_align */
2104 ELFCLASS64,
2105 EV_CURRENT,
2106 bfd_elf64_write_out_phdrs,
2107 bfd_elf64_write_shdrs_and_ehdr,
2108 mips_elf64_write_relocs,
2109 bfd_elf64_swap_symbol_out,
2110 mips_elf64_slurp_reloc_table,
2111 bfd_elf64_slurp_symbol_table,
2112 bfd_elf64_swap_dyn_in
2115 #define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
2116 #define TARGET_LITTLE_NAME "elf64-littlemips"
2117 #define TARGET_BIG_SYM bfd_elf64_bigmips_vec
2118 #define TARGET_BIG_NAME "elf64-bigmips"
2119 #define ELF_ARCH bfd_arch_mips
2120 #define ELF_MACHINE_CODE EM_MIPS
2121 #define ELF_MAXPAGESIZE 0x1000
2122 #define elf_backend_size_info mips_elf64_size_info
2123 #define elf_backend_object_p _bfd_mips_elf_object_p
2124 #define elf_backend_section_from_shdr mips_elf64_section_from_shdr
2125 #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
2126 #define elf_backend_section_from_bfd_section \
2127 _bfd_mips_elf_section_from_bfd_section
2128 #define elf_backend_section_processing mips_elf64_section_processing
2129 #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
2130 #define elf_backend_final_write_processing \
2131 _bfd_mips_elf_final_write_processing
2132 #define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
2134 #define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
2135 #define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
2136 #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup
2137 #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
2138 #define bfd_elf64_bfd_copy_private_bfd_data \
2139 _bfd_mips_elf_copy_private_bfd_data
2140 #define bfd_elf64_bfd_merge_private_bfd_data \
2141 _bfd_mips_elf_merge_private_bfd_data
2142 #define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
2144 #define bfd_elf64_archive_functions
2145 #define bfd_elf64_archive_slurp_armap mips_elf64_slurp_armap
2146 #define bfd_elf64_archive_slurp_extended_name_table \
2147 _bfd_archive_coff_slurp_extended_name_table
2148 #define bfd_elf64_archive_construct_extended_name_table \
2149 _bfd_archive_coff_construct_extended_name_table
2150 #define bfd_elf64_archive_truncate_arname \
2151 _bfd_archive_coff_truncate_arname
2152 #define bfd_elf64_archive_write_armap mips_elf64_write_armap
2153 #define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
2154 #define bfd_elf64_archive_openr_next_archived_file \
2155 _bfd_archive_coff_openr_next_archived_file
2156 #define bfd_elf64_archive_get_elt_at_index \
2157 _bfd_archive_coff_get_elt_at_index
2158 #define bfd_elf64_archive_generic_stat_arch_elt \
2159 _bfd_archive_coff_generic_stat_arch_elt
2160 #define bfd_elf64_archive_update_armap_timestamp \
2161 _bfd_archive_coff_update_armap_timestamp
2163 #include "elf64-target.h"