1
/* MIPS-specific support for 64-bit ELF
2
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
3
Free Software Foundation, Inc.
4
Ian Lance Taylor, Cygnus Support
5
Linker support added by Mark Mitchell, CodeSourcery, LLC.
6
<mark@codesourcery.com>
8
This file is part of BFD, the Binary File Descriptor library.
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 2 of the License, or
13
(at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
/* This file supports the 64-bit MIPS ELF ABI.
26
The MIPS 64-bit ELF ABI uses an unusual reloc format. This file
27
overrides the usual ELF reloc handling, and handles reading and
28
writing the relocations here. */
30
/* TODO: Many things are unsupported, even if there is some code for it
31
. (which was mostly stolen from elf32-mips.c and slightly adapted).
33
. - Relocation handling for REL relocs is wrong in many cases and
35
. - Relocation handling for RELA relocs related to GOT support are
36
. also likely to be wrong.
37
. - Support for MIPS16 is only partially implemented.
38
. - Embedded PIC is only partially implemented (is it needed?).
39
. - Combined relocs with RSS_* entries are unsupported.
40
. - The whole GOT handling for NewABI is missing, some parts of
41
. the OldABI version is still lying around and should be removed.
51
#include "elfxx-mips.h"
54
/* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to
55
use ECOFF. However, we support it anyhow for an easier changeover. */
57
#include "coff/symconst.h"
58
#include "coff/internal.h"
59
#include "coff/ecoff.h"
60
/* The 64 bit versions of the mdebug data structures are in alpha.h. */
61
#include "coff/alpha.h"
62
#define ECOFF_SIGNED_64
63
#include "ecoffswap.h"
65
static void mips_elf64_swap_reloc_in
66
PARAMS ((bfd *, const Elf64_Mips_External_Rel *,
67
Elf64_Mips_Internal_Rel *));
68
static void mips_elf64_swap_reloca_in
69
PARAMS ((bfd *, const Elf64_Mips_External_Rela *,
70
Elf64_Mips_Internal_Rela *));
71
static void mips_elf64_swap_reloc_out
72
PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *,
73
Elf64_Mips_External_Rel *));
74
static void mips_elf64_swap_reloca_out
75
PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *,
76
Elf64_Mips_External_Rela *));
77
static void mips_elf64_be_swap_reloc_in
78
PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rel *));
79
static void mips_elf64_be_swap_reloc_out
80
PARAMS ((bfd *, const Elf_Internal_Rel *, bfd_byte *));
81
static void mips_elf64_be_swap_reloca_in
82
PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
83
static void mips_elf64_be_swap_reloca_out
84
PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
85
static reloc_howto_type *bfd_elf64_bfd_reloc_type_lookup
86
PARAMS ((bfd *, bfd_reloc_code_real_type));
87
static reloc_howto_type *mips_elf64_rtype_to_howto
88
PARAMS ((unsigned int, boolean));
89
static void mips_elf64_info_to_howto_rel
90
PARAMS ((bfd *, arelent *, Elf64_Internal_Rel *));
91
static void mips_elf64_info_to_howto_rela
92
PARAMS ((bfd *, arelent *, Elf64_Internal_Rela *));
93
static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *));
94
static boolean mips_elf64_slurp_one_reloc_table
95
PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
96
static boolean mips_elf64_slurp_reloc_table
97
PARAMS ((bfd *, asection *, asymbol **, boolean));
98
static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
99
static void mips_elf64_write_rel
100
PARAMS((bfd *, asection *, Elf_Internal_Shdr *, int *, PTR));
101
static void mips_elf64_write_rela
102
PARAMS((bfd *, asection *, Elf_Internal_Shdr *, int *, PTR));
103
static bfd_reloc_status_type mips_elf64_hi16_reloc
104
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
105
static bfd_reloc_status_type mips_elf64_higher_reloc
106
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
107
static bfd_reloc_status_type mips_elf64_highest_reloc
108
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
109
static bfd_reloc_status_type mips_elf64_gprel16_reloc
110
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
111
static bfd_reloc_status_type mips_elf64_gprel16_reloca
112
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
113
static bfd_reloc_status_type mips_elf64_literal_reloc
114
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
115
static bfd_reloc_status_type mips_elf64_gprel32_reloc
116
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
117
static bfd_reloc_status_type mips_elf64_shift6_reloc
118
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
119
static bfd_reloc_status_type mips_elf64_got16_reloc
120
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
121
static boolean mips_elf64_assign_gp PARAMS ((bfd *, bfd_vma *));
122
static bfd_reloc_status_type mips_elf64_final_gp
123
PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));
124
static boolean mips_elf64_object_p PARAMS ((bfd *));
125
static irix_compat_t elf64_mips_irix_compat PARAMS ((bfd *));
127
extern const bfd_target bfd_elf64_tradbigmips_vec;
128
extern const bfd_target bfd_elf64_tradlittlemips_vec;
130
static bfd_vma prev_reloc_addend = 0;
131
static bfd_size_type prev_reloc_address = 0;
133
/* Whether we are trying to be compatible with IRIX6 (or little endianers
134
which are otherwise IRIX-ABI compliant). */
135
#define SGI_COMPAT(abfd) \
136
(elf64_mips_irix_compat (abfd) != ict_none)
138
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
139
from smaller values. Start with zero, widen, *then* decrement. */
140
#define MINUS_ONE (((bfd_vma)0) - 1)
142
/* The number of local .got entries we reserve. */
143
#define MIPS_RESERVED_GOTNO (2)
145
/* The relocation table used for SHT_REL sections. */
147
#define UNUSED_RELOC(num) { num, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
149
static reloc_howto_type mips_elf64_howto_table_rel[] =
152
HOWTO (R_MIPS_NONE, /* type */
154
0, /* size (0 = byte, 1 = short, 2 = long) */
156
false, /* pc_relative */
158
complain_overflow_dont, /* complain_on_overflow */
159
bfd_elf_generic_reloc, /* special_function */
160
"R_MIPS_NONE", /* name */
161
false, /* partial_inplace */
164
false), /* pcrel_offset */
166
/* 16 bit relocation. */
167
HOWTO (R_MIPS_16, /* type */
169
2, /* size (0 = byte, 1 = short, 2 = long) */
171
false, /* pc_relative */
173
complain_overflow_signed, /* complain_on_overflow */
174
bfd_elf_generic_reloc, /* special_function */
175
"R_MIPS_16", /* name */
176
true, /* partial_inplace */
177
0x0000ffff, /* src_mask */
178
0x0000ffff, /* dst_mask */
179
false), /* pcrel_offset */
181
/* 32 bit relocation. */
182
HOWTO (R_MIPS_32, /* type */
184
2, /* size (0 = byte, 1 = short, 2 = long) */
186
false, /* pc_relative */
188
complain_overflow_dont, /* complain_on_overflow */
189
bfd_elf_generic_reloc, /* special_function */
190
"R_MIPS_32", /* name */
191
true, /* partial_inplace */
192
0xffffffff, /* src_mask */
193
0xffffffff, /* dst_mask */
194
false), /* pcrel_offset */
196
/* 32 bit symbol relative relocation. */
197
HOWTO (R_MIPS_REL32, /* type */
199
2, /* size (0 = byte, 1 = short, 2 = long) */
201
false, /* pc_relative */
203
complain_overflow_dont, /* complain_on_overflow */
204
bfd_elf_generic_reloc, /* special_function */
205
"R_MIPS_REL32", /* name */
206
true, /* partial_inplace */
207
0xffffffff, /* src_mask */
208
0xffffffff, /* dst_mask */
209
false), /* pcrel_offset */
211
/* 26 bit jump address. */
212
HOWTO (R_MIPS_26, /* type */
214
2, /* size (0 = byte, 1 = short, 2 = long) */
216
false, /* pc_relative */
218
complain_overflow_dont, /* complain_on_overflow */
219
/* This needs complex overflow
220
detection, because the upper 36
221
bits must match the PC + 4. */
222
bfd_elf_generic_reloc, /* special_function */
223
"R_MIPS_26", /* name */
224
true, /* partial_inplace */
225
0x03ffffff, /* src_mask */
226
0x03ffffff, /* dst_mask */
227
false), /* pcrel_offset */
229
/* High 16 bits of symbol value. */
230
HOWTO (R_MIPS_HI16, /* type */
232
2, /* size (0 = byte, 1 = short, 2 = long) */
234
false, /* pc_relative */
236
complain_overflow_dont, /* complain_on_overflow */
237
bfd_elf_generic_reloc, /* special_function */
238
"R_MIPS_HI16", /* name */
239
true, /* partial_inplace */
240
0x0000ffff, /* src_mask */
241
0x0000ffff, /* dst_mask */
242
false), /* pcrel_offset */
244
/* Low 16 bits of symbol value. */
245
HOWTO (R_MIPS_LO16, /* type */
247
2, /* size (0 = byte, 1 = short, 2 = long) */
249
false, /* pc_relative */
251
complain_overflow_dont, /* complain_on_overflow */
252
bfd_elf_generic_reloc, /* special_function */
253
"R_MIPS_LO16", /* name */
254
true, /* partial_inplace */
255
0x0000ffff, /* src_mask */
256
0x0000ffff, /* dst_mask */
257
false), /* pcrel_offset */
259
/* GP relative reference. */
260
HOWTO (R_MIPS_GPREL16, /* type */
262
2, /* size (0 = byte, 1 = short, 2 = long) */
264
false, /* pc_relative */
266
complain_overflow_signed, /* complain_on_overflow */
267
mips_elf64_gprel16_reloc, /* special_function */
268
"R_MIPS_GPREL16", /* name */
269
true, /* partial_inplace */
270
0x0000ffff, /* src_mask */
271
0x0000ffff, /* dst_mask */
272
false), /* pcrel_offset */
274
/* Reference to literal section. */
275
HOWTO (R_MIPS_LITERAL, /* type */
277
2, /* size (0 = byte, 1 = short, 2 = long) */
279
false, /* pc_relative */
281
complain_overflow_signed, /* complain_on_overflow */
282
mips_elf64_literal_reloc, /* special_function */
283
"R_MIPS_LITERAL", /* name */
284
true, /* partial_inplace */
285
0x0000ffff, /* src_mask */
286
0x0000ffff, /* dst_mask */
287
false), /* pcrel_offset */
289
/* Reference to global offset table. */
290
HOWTO (R_MIPS_GOT16, /* type */
292
2, /* size (0 = byte, 1 = short, 2 = long) */
294
false, /* pc_relative */
296
complain_overflow_signed, /* complain_on_overflow */
297
mips_elf64_got16_reloc, /* special_function */
298
"R_MIPS_GOT16", /* name */
299
true, /* partial_inplace */
300
0x0000ffff, /* src_mask */
301
0x0000ffff, /* dst_mask */
302
false), /* pcrel_offset */
304
/* 16 bit PC relative reference. */
305
HOWTO (R_MIPS_PC16, /* type */
307
2, /* size (0 = byte, 1 = short, 2 = long) */
309
true, /* pc_relative */
311
complain_overflow_signed, /* complain_on_overflow */
312
bfd_elf_generic_reloc, /* special_function */
313
"R_MIPS_PC16", /* name */
314
true, /* partial_inplace */
315
0x0000ffff, /* src_mask */
316
0x0000ffff, /* dst_mask */
317
true), /* pcrel_offset */
319
/* 16 bit call through global offset table. */
320
/* FIXME: This is not handled correctly. */
321
HOWTO (R_MIPS_CALL16, /* type */
323
2, /* size (0 = byte, 1 = short, 2 = long) */
325
false, /* pc_relative */
327
complain_overflow_signed, /* complain_on_overflow */
328
bfd_elf_generic_reloc, /* special_function */
329
"R_MIPS_CALL16", /* name */
330
true, /* partial_inplace */
331
0x0000ffff, /* src_mask */
332
0x0000ffff, /* dst_mask */
333
false), /* pcrel_offset */
335
/* 32 bit GP relative reference. */
336
HOWTO (R_MIPS_GPREL32, /* type */
338
2, /* size (0 = byte, 1 = short, 2 = long) */
340
false, /* pc_relative */
342
complain_overflow_dont, /* complain_on_overflow */
343
mips_elf64_gprel32_reloc, /* special_function */
344
"R_MIPS_GPREL32", /* name */
345
true, /* partial_inplace */
346
0xffffffff, /* src_mask */
347
0xffffffff, /* dst_mask */
348
false), /* pcrel_offset */
354
/* A 5 bit shift field. */
355
HOWTO (R_MIPS_SHIFT5, /* type */
357
2, /* size (0 = byte, 1 = short, 2 = long) */
359
false, /* pc_relative */
361
complain_overflow_bitfield, /* complain_on_overflow */
362
bfd_elf_generic_reloc, /* special_function */
363
"R_MIPS_SHIFT5", /* name */
364
true, /* partial_inplace */
365
0x000007c0, /* src_mask */
366
0x000007c0, /* dst_mask */
367
false), /* pcrel_offset */
369
/* A 6 bit shift field. */
370
HOWTO (R_MIPS_SHIFT6, /* type */
372
2, /* size (0 = byte, 1 = short, 2 = long) */
374
false, /* pc_relative */
376
complain_overflow_bitfield, /* complain_on_overflow */
377
mips_elf64_shift6_reloc, /* special_function */
378
"R_MIPS_SHIFT6", /* name */
379
true, /* partial_inplace */
380
0x000007c4, /* src_mask */
381
0x000007c4, /* dst_mask */
382
false), /* pcrel_offset */
384
/* 64 bit relocation. */
385
HOWTO (R_MIPS_64, /* type */
387
4, /* size (0 = byte, 1 = short, 2 = long) */
389
false, /* pc_relative */
391
complain_overflow_dont, /* complain_on_overflow */
392
bfd_elf_generic_reloc, /* special_function */
393
"R_MIPS_64", /* name */
394
true, /* partial_inplace */
395
MINUS_ONE, /* src_mask */
396
MINUS_ONE, /* dst_mask */
397
false), /* pcrel_offset */
399
/* Displacement in the global offset table. */
400
/* FIXME: Not handled correctly. */
401
HOWTO (R_MIPS_GOT_DISP, /* type */
403
2, /* size (0 = byte, 1 = short, 2 = long) */
405
false, /* pc_relative */
407
complain_overflow_signed, /* complain_on_overflow */
408
bfd_elf_generic_reloc, /* special_function */
409
"R_MIPS_GOT_DISP", /* name */
410
true, /* partial_inplace */
411
0x0000ffff, /* src_mask */
412
0x0000ffff, /* dst_mask */
413
false), /* pcrel_offset */
415
/* Displacement to page pointer in the global offset table. */
416
/* FIXME: Not handled correctly. */
417
HOWTO (R_MIPS_GOT_PAGE, /* type */
419
2, /* size (0 = byte, 1 = short, 2 = long) */
421
false, /* pc_relative */
423
complain_overflow_signed, /* complain_on_overflow */
424
bfd_elf_generic_reloc, /* special_function */
425
"R_MIPS_GOT_PAGE", /* name */
426
true, /* partial_inplace */
427
0x0000ffff, /* src_mask */
428
0x0000ffff, /* dst_mask */
429
false), /* pcrel_offset */
431
/* Offset from page pointer in the global offset table. */
432
/* FIXME: Not handled correctly. */
433
HOWTO (R_MIPS_GOT_OFST, /* type */
435
2, /* size (0 = byte, 1 = short, 2 = long) */
437
false, /* pc_relative */
439
complain_overflow_signed, /* complain_on_overflow */
440
bfd_elf_generic_reloc, /* special_function */
441
"R_MIPS_GOT_OFST", /* name */
442
true, /* partial_inplace */
443
0x0000ffff, /* src_mask */
444
0x0000ffff, /* dst_mask */
445
false), /* pcrel_offset */
447
/* High 16 bits of displacement in global offset table. */
448
/* FIXME: Not handled correctly. */
449
HOWTO (R_MIPS_GOT_HI16, /* type */
451
2, /* size (0 = byte, 1 = short, 2 = long) */
453
false, /* pc_relative */
455
complain_overflow_dont, /* complain_on_overflow */
456
bfd_elf_generic_reloc, /* special_function */
457
"R_MIPS_GOT_HI16", /* name */
458
true, /* partial_inplace */
459
0x0000ffff, /* src_mask */
460
0x0000ffff, /* dst_mask */
461
false), /* pcrel_offset */
463
/* Low 16 bits of displacement in global offset table. */
464
/* FIXME: Not handled correctly. */
465
HOWTO (R_MIPS_GOT_LO16, /* type */
467
2, /* size (0 = byte, 1 = short, 2 = long) */
469
false, /* pc_relative */
471
complain_overflow_dont, /* complain_on_overflow */
472
bfd_elf_generic_reloc, /* special_function */
473
"R_MIPS_GOT_LO16", /* name */
474
true, /* partial_inplace */
475
0x0000ffff, /* src_mask */
476
0x0000ffff, /* dst_mask */
477
false), /* pcrel_offset */
479
/* 64 bit substraction. */
480
/* FIXME: Not handled correctly. */
481
HOWTO (R_MIPS_SUB, /* type */
483
4, /* size (0 = byte, 1 = short, 2 = long) */
485
false, /* pc_relative */
487
complain_overflow_dont, /* complain_on_overflow */
488
bfd_elf_generic_reloc, /* special_function */
489
"R_MIPS_SUB", /* name */
490
true, /* partial_inplace */
491
MINUS_ONE, /* src_mask */
492
MINUS_ONE, /* dst_mask */
493
false), /* pcrel_offset */
495
/* Insert the addend as an instruction. */
496
/* FIXME: Not handled correctly. */
497
HOWTO (R_MIPS_INSERT_A, /* type */
499
2, /* size (0 = byte, 1 = short, 2 = long) */
501
false, /* pc_relative */
503
complain_overflow_dont, /* complain_on_overflow */
504
bfd_elf_generic_reloc, /* special_function */
505
"R_MIPS_INSERT_A", /* name */
506
true, /* partial_inplace */
507
0xffffffff, /* src_mask */
508
0xffffffff, /* dst_mask */
509
false), /* pcrel_offset */
511
/* Insert the addend as an instruction, and change all relocations
512
to refer to the old instruction at the address. */
513
/* FIXME: Not handled correctly. */
514
HOWTO (R_MIPS_INSERT_B, /* type */
516
2, /* size (0 = byte, 1 = short, 2 = long) */
518
false, /* pc_relative */
520
complain_overflow_dont, /* complain_on_overflow */
521
bfd_elf_generic_reloc, /* special_function */
522
"R_MIPS_INSERT_B", /* name */
523
true, /* partial_inplace */
524
0xffffffff, /* src_mask */
525
0xffffffff, /* dst_mask */
526
false), /* pcrel_offset */
528
/* Delete a 32 bit instruction. */
529
/* FIXME: Not handled correctly. */
530
HOWTO (R_MIPS_DELETE, /* type */
532
2, /* size (0 = byte, 1 = short, 2 = long) */
534
false, /* pc_relative */
536
complain_overflow_dont, /* complain_on_overflow */
537
bfd_elf_generic_reloc, /* special_function */
538
"R_MIPS_DELETE", /* name */
539
true, /* partial_inplace */
540
0xffffffff, /* src_mask */
541
0xffffffff, /* dst_mask */
542
false), /* pcrel_offset */
544
/* Get the higher value of a 64 bit addend. */
545
HOWTO (R_MIPS_HIGHER, /* type */
547
2, /* size (0 = byte, 1 = short, 2 = long) */
549
false, /* pc_relative */
551
complain_overflow_dont, /* complain_on_overflow */
552
mips_elf64_higher_reloc, /* special_function */
553
"R_MIPS_HIGHER", /* name */
554
true, /* partial_inplace */
555
0x0000ffff, /* src_mask */
556
0x0000ffff, /* dst_mask */
557
false), /* pcrel_offset */
559
/* Get the highest value of a 64 bit addend. */
560
HOWTO (R_MIPS_HIGHEST, /* type */
562
2, /* size (0 = byte, 1 = short, 2 = long) */
564
false, /* pc_relative */
566
complain_overflow_dont, /* complain_on_overflow */
567
mips_elf64_highest_reloc, /* special_function */
568
"R_MIPS_HIGHEST", /* name */
569
true, /* partial_inplace */
570
0x0000ffff, /* src_mask */
571
0x0000ffff, /* dst_mask */
572
false), /* pcrel_offset */
574
/* High 16 bits of displacement in global offset table. */
575
/* FIXME: Not handled correctly. */
576
HOWTO (R_MIPS_CALL_HI16, /* type */
578
2, /* size (0 = byte, 1 = short, 2 = long) */
580
false, /* pc_relative */
582
complain_overflow_dont, /* complain_on_overflow */
583
bfd_elf_generic_reloc, /* special_function */
584
"R_MIPS_CALL_HI16", /* name */
585
true, /* partial_inplace */
586
0x0000ffff, /* src_mask */
587
0x0000ffff, /* dst_mask */
588
false), /* pcrel_offset */
590
/* Low 16 bits of displacement in global offset table. */
591
/* FIXME: Not handled correctly. */
592
HOWTO (R_MIPS_CALL_LO16, /* type */
594
2, /* size (0 = byte, 1 = short, 2 = long) */
596
false, /* pc_relative */
598
complain_overflow_dont, /* complain_on_overflow */
599
bfd_elf_generic_reloc, /* special_function */
600
"R_MIPS_CALL_LO16", /* name */
601
true, /* partial_inplace */
602
0x0000ffff, /* src_mask */
603
0x0000ffff, /* dst_mask */
604
false), /* pcrel_offset */
606
/* Section displacement, used by an associated event location section. */
607
/* FIXME: Not handled correctly. */
608
HOWTO (R_MIPS_SCN_DISP, /* type */
610
2, /* size (0 = byte, 1 = short, 2 = long) */
612
false, /* pc_relative */
614
complain_overflow_dont, /* complain_on_overflow */
615
bfd_elf_generic_reloc, /* special_function */
616
"R_MIPS_SCN_DISP", /* name */
617
true, /* partial_inplace */
618
0xffffffff, /* src_mask */
619
0xffffffff, /* dst_mask */
620
false), /* pcrel_offset */
622
HOWTO (R_MIPS_REL16, /* type */
624
1, /* size (0 = byte, 1 = short, 2 = long) */
626
false, /* pc_relative */
628
complain_overflow_signed, /* complain_on_overflow */
629
bfd_elf_generic_reloc, /* special_function */
630
"R_MIPS_REL16", /* name */
631
true, /* partial_inplace */
632
0xffff, /* src_mask */
633
0xffff, /* dst_mask */
634
false), /* pcrel_offset */
636
/* These two are obsolete. */
637
EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
638
EMPTY_HOWTO (R_MIPS_PJUMP),
640
/* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
641
It must be used for multigot GOT's (and only there). */
642
HOWTO (R_MIPS_RELGOT, /* type */
644
2, /* size (0 = byte, 1 = short, 2 = long) */
646
false, /* pc_relative */
648
complain_overflow_dont, /* complain_on_overflow */
649
bfd_elf_generic_reloc, /* special_function */
650
"R_MIPS_RELGOT", /* name */
651
true, /* partial_inplace */
652
0xffffffff, /* src_mask */
653
0xffffffff, /* dst_mask */
654
false), /* pcrel_offset */
656
/* Protected jump conversion. This is an optimization hint. No
657
relocation is required for correctness. */
658
HOWTO (R_MIPS_JALR, /* type */
660
2, /* size (0 = byte, 1 = short, 2 = long) */
662
false, /* pc_relative */
664
complain_overflow_dont, /* complain_on_overflow */
665
bfd_elf_generic_reloc, /* special_function */
666
"R_MIPS_JALR", /* name */
667
false, /* partial_inplace */
669
0x00000000, /* dst_mask */
670
false), /* pcrel_offset */
673
/* The relocation table used for SHT_RELA sections. */
675
static reloc_howto_type mips_elf64_howto_table_rela[] =
678
HOWTO (R_MIPS_NONE, /* type */
680
0, /* size (0 = byte, 1 = short, 2 = long) */
682
false, /* pc_relative */
684
complain_overflow_dont, /* complain_on_overflow */
685
bfd_elf_generic_reloc, /* special_function */
686
"R_MIPS_NONE", /* name */
687
false, /* partial_inplace */
690
false), /* pcrel_offset */
692
/* 16 bit relocation. */
693
HOWTO (R_MIPS_16, /* type */
695
2, /* size (0 = byte, 1 = short, 2 = long) */
697
false, /* pc_relative */
699
complain_overflow_signed, /* complain_on_overflow */
700
bfd_elf_generic_reloc, /* special_function */
701
"R_MIPS_16", /* name */
702
false, /* partial_inplace */
704
0x0000ffff, /* dst_mask */
705
false), /* pcrel_offset */
707
/* 32 bit relocation. */
708
HOWTO (R_MIPS_32, /* type */
710
2, /* size (0 = byte, 1 = short, 2 = long) */
712
false, /* pc_relative */
714
complain_overflow_dont, /* complain_on_overflow */
715
bfd_elf_generic_reloc, /* special_function */
716
"R_MIPS_32", /* name */
717
false, /* partial_inplace */
719
0xffffffff, /* dst_mask */
720
false), /* pcrel_offset */
722
/* 32 bit symbol relative relocation. */
723
HOWTO (R_MIPS_REL32, /* type */
725
2, /* size (0 = byte, 1 = short, 2 = long) */
727
false, /* pc_relative */
729
complain_overflow_dont, /* complain_on_overflow */
730
bfd_elf_generic_reloc, /* special_function */
731
"R_MIPS_REL32", /* name */
732
false, /* partial_inplace */
734
0xffffffff, /* dst_mask */
735
false), /* pcrel_offset */
737
/* 26 bit jump address. */
738
HOWTO (R_MIPS_26, /* type */
740
2, /* size (0 = byte, 1 = short, 2 = long) */
742
false, /* pc_relative */
744
complain_overflow_dont, /* complain_on_overflow */
745
/* This needs complex overflow
746
detection, because the upper 36
747
bits must match the PC + 4. */
748
bfd_elf_generic_reloc, /* special_function */
749
"R_MIPS_26", /* name */
750
false, /* partial_inplace */
752
0x03ffffff, /* dst_mask */
753
false), /* pcrel_offset */
755
/* R_MIPS_HI16 and R_MIPS_LO16 are unsupported for 64 bit REL. */
756
/* High 16 bits of symbol value. */
757
HOWTO (R_MIPS_HI16, /* type */
759
2, /* size (0 = byte, 1 = short, 2 = long) */
761
false, /* pc_relative */
763
complain_overflow_dont, /* complain_on_overflow */
764
bfd_elf_generic_reloc, /* special_function */
765
"R_MIPS_HI16", /* name */
766
false, /* partial_inplace */
768
0x0000ffff, /* dst_mask */
769
false), /* pcrel_offset */
771
/* Low 16 bits of symbol value. */
772
HOWTO (R_MIPS_LO16, /* type */
774
2, /* size (0 = byte, 1 = short, 2 = long) */
776
false, /* pc_relative */
778
complain_overflow_dont, /* complain_on_overflow */
779
bfd_elf_generic_reloc, /* special_function */
780
"R_MIPS_LO16", /* name */
781
false, /* partial_inplace */
783
0x0000ffff, /* dst_mask */
784
false), /* pcrel_offset */
786
/* GP relative reference. */
787
HOWTO (R_MIPS_GPREL16, /* type */
789
2, /* size (0 = byte, 1 = short, 2 = long) */
791
false, /* pc_relative */
793
complain_overflow_signed, /* complain_on_overflow */
794
mips_elf64_gprel16_reloca, /* special_function */
795
"R_MIPS_GPREL16", /* name */
796
false, /* partial_inplace */
798
0x0000ffff, /* dst_mask */
799
false), /* pcrel_offset */
801
/* Reference to literal section. */
802
HOWTO (R_MIPS_LITERAL, /* type */
804
2, /* size (0 = byte, 1 = short, 2 = long) */
806
false, /* pc_relative */
808
complain_overflow_signed, /* complain_on_overflow */
809
mips_elf64_literal_reloc, /* special_function */
810
"R_MIPS_LITERAL", /* name */
811
false, /* partial_inplace */
813
0x0000ffff, /* dst_mask */
814
false), /* pcrel_offset */
816
/* Reference to global offset table. */
817
/* FIXME: This is not handled correctly. */
818
HOWTO (R_MIPS_GOT16, /* type */
820
2, /* size (0 = byte, 1 = short, 2 = long) */
822
false, /* pc_relative */
824
complain_overflow_signed, /* complain_on_overflow */
825
bfd_elf_generic_reloc, /* special_function */
826
"R_MIPS_GOT16", /* name */
827
false, /* partial_inplace */
829
0x0000ffff, /* dst_mask */
830
false), /* pcrel_offset */
832
/* 16 bit PC relative reference. */
833
HOWTO (R_MIPS_PC16, /* type */
835
2, /* size (0 = byte, 1 = short, 2 = long) */
837
true, /* pc_relative */
839
complain_overflow_signed, /* complain_on_overflow */
840
bfd_elf_generic_reloc, /* special_function */
841
"R_MIPS_PC16", /* name */
842
false, /* partial_inplace */
844
0x0000ffff, /* dst_mask */
845
true), /* pcrel_offset */
847
/* 16 bit call through global offset table. */
848
/* FIXME: This is not handled correctly. */
849
HOWTO (R_MIPS_CALL16, /* type */
851
2, /* size (0 = byte, 1 = short, 2 = long) */
853
false, /* pc_relative */
855
complain_overflow_signed, /* complain_on_overflow */
856
bfd_elf_generic_reloc, /* special_function */
857
"R_MIPS_CALL16", /* name */
858
false, /* partial_inplace */
860
0x0000ffff, /* dst_mask */
861
false), /* pcrel_offset */
863
/* 32 bit GP relative reference. */
864
HOWTO (R_MIPS_GPREL32, /* type */
866
2, /* size (0 = byte, 1 = short, 2 = long) */
868
false, /* pc_relative */
870
complain_overflow_dont, /* complain_on_overflow */
871
mips_elf64_gprel32_reloc, /* special_function */
872
"R_MIPS_GPREL32", /* name */
873
false, /* partial_inplace */
875
0xffffffff, /* dst_mask */
876
false), /* pcrel_offset */
882
/* A 5 bit shift field. */
883
HOWTO (R_MIPS_SHIFT5, /* type */
885
2, /* size (0 = byte, 1 = short, 2 = long) */
887
false, /* pc_relative */
889
complain_overflow_bitfield, /* complain_on_overflow */
890
bfd_elf_generic_reloc, /* special_function */
891
"R_MIPS_SHIFT5", /* name */
892
false, /* partial_inplace */
894
0x000007c0, /* dst_mask */
895
false), /* pcrel_offset */
897
/* A 6 bit shift field. */
898
HOWTO (R_MIPS_SHIFT6, /* type */
900
2, /* size (0 = byte, 1 = short, 2 = long) */
902
false, /* pc_relative */
904
complain_overflow_bitfield, /* complain_on_overflow */
905
mips_elf64_shift6_reloc, /* special_function */
906
"R_MIPS_SHIFT6", /* name */
907
false, /* partial_inplace */
909
0x000007c4, /* dst_mask */
910
false), /* pcrel_offset */
912
/* 64 bit relocation. */
913
HOWTO (R_MIPS_64, /* type */
915
4, /* size (0 = byte, 1 = short, 2 = long) */
917
false, /* pc_relative */
919
complain_overflow_dont, /* complain_on_overflow */
920
bfd_elf_generic_reloc, /* special_function */
921
"R_MIPS_64", /* name */
922
false, /* partial_inplace */
924
MINUS_ONE, /* dst_mask */
925
false), /* pcrel_offset */
927
/* Displacement in the global offset table. */
928
/* FIXME: Not handled correctly. */
929
HOWTO (R_MIPS_GOT_DISP, /* type */
931
2, /* size (0 = byte, 1 = short, 2 = long) */
933
false, /* pc_relative */
935
complain_overflow_signed, /* complain_on_overflow */
936
bfd_elf_generic_reloc, /* special_function */
937
"R_MIPS_GOT_DISP", /* name */
938
false, /* partial_inplace */
940
0x0000ffff, /* dst_mask */
941
false), /* pcrel_offset */
943
/* Displacement to page pointer in the global offset table. */
944
/* FIXME: Not handled correctly. */
945
HOWTO (R_MIPS_GOT_PAGE, /* type */
947
2, /* size (0 = byte, 1 = short, 2 = long) */
949
false, /* pc_relative */
951
complain_overflow_signed, /* complain_on_overflow */
952
bfd_elf_generic_reloc, /* special_function */
953
"R_MIPS_GOT_PAGE", /* name */
954
false, /* partial_inplace */
956
0x0000ffff, /* dst_mask */
957
false), /* pcrel_offset */
959
/* Offset from page pointer in the global offset table. */
960
/* FIXME: Not handled correctly. */
961
HOWTO (R_MIPS_GOT_OFST, /* type */
963
2, /* size (0 = byte, 1 = short, 2 = long) */
965
false, /* pc_relative */
967
complain_overflow_signed, /* complain_on_overflow */
968
bfd_elf_generic_reloc, /* special_function */
969
"R_MIPS_GOT_OFST", /* name */
970
false, /* partial_inplace */
972
0x0000ffff, /* dst_mask */
973
false), /* pcrel_offset */
975
/* High 16 bits of displacement in global offset table. */
976
/* FIXME: Not handled correctly. */
977
HOWTO (R_MIPS_GOT_HI16, /* type */
979
2, /* size (0 = byte, 1 = short, 2 = long) */
981
false, /* pc_relative */
983
complain_overflow_dont, /* complain_on_overflow */
984
bfd_elf_generic_reloc, /* special_function */
985
"R_MIPS_GOT_HI16", /* name */
986
false, /* partial_inplace */
988
0x0000ffff, /* dst_mask */
989
false), /* pcrel_offset */
991
/* Low 16 bits of displacement in global offset table. */
992
/* FIXME: Not handled correctly. */
993
HOWTO (R_MIPS_GOT_LO16, /* type */
995
2, /* size (0 = byte, 1 = short, 2 = long) */
997
false, /* pc_relative */
999
complain_overflow_dont, /* complain_on_overflow */
1000
bfd_elf_generic_reloc, /* special_function */
1001
"R_MIPS_GOT_LO16", /* name */
1002
false, /* partial_inplace */
1004
0x0000ffff, /* dst_mask */
1005
false), /* pcrel_offset */
1007
/* 64 bit substraction. */
1008
/* FIXME: Not handled correctly. */
1009
HOWTO (R_MIPS_SUB, /* type */
1011
4, /* size (0 = byte, 1 = short, 2 = long) */
1013
false, /* pc_relative */
1015
complain_overflow_dont, /* complain_on_overflow */
1016
bfd_elf_generic_reloc, /* special_function */
1017
"R_MIPS_SUB", /* name */
1018
false, /* partial_inplace */
1020
MINUS_ONE, /* dst_mask */
1021
false), /* pcrel_offset */
1023
/* Insert the addend as an instruction. */
1024
/* FIXME: Not handled correctly. */
1025
HOWTO (R_MIPS_INSERT_A, /* type */
1027
2, /* size (0 = byte, 1 = short, 2 = long) */
1029
false, /* pc_relative */
1031
complain_overflow_dont, /* complain_on_overflow */
1032
bfd_elf_generic_reloc, /* special_function */
1033
"R_MIPS_INSERT_A", /* name */
1034
false, /* partial_inplace */
1036
0xffffffff, /* dst_mask */
1037
false), /* pcrel_offset */
1039
/* Insert the addend as an instruction, and change all relocations
1040
to refer to the old instruction at the address. */
1041
/* FIXME: Not handled correctly. */
1042
HOWTO (R_MIPS_INSERT_B, /* type */
1044
2, /* size (0 = byte, 1 = short, 2 = long) */
1046
false, /* pc_relative */
1048
complain_overflow_dont, /* complain_on_overflow */
1049
bfd_elf_generic_reloc, /* special_function */
1050
"R_MIPS_INSERT_B", /* name */
1051
false, /* partial_inplace */
1053
0xffffffff, /* dst_mask */
1054
false), /* pcrel_offset */
1056
/* Delete a 32 bit instruction. */
1057
/* FIXME: Not handled correctly. */
1058
HOWTO (R_MIPS_DELETE, /* type */
1060
2, /* size (0 = byte, 1 = short, 2 = long) */
1062
false, /* pc_relative */
1064
complain_overflow_dont, /* complain_on_overflow */
1065
bfd_elf_generic_reloc, /* special_function */
1066
"R_MIPS_DELETE", /* name */
1067
false, /* partial_inplace */
1069
0xffffffff, /* dst_mask */
1070
false), /* pcrel_offset */
1072
/* Get the higher value of a 64 bit addend. */
1073
HOWTO (R_MIPS_HIGHER, /* type */
1075
2, /* size (0 = byte, 1 = short, 2 = long) */
1077
false, /* pc_relative */
1079
complain_overflow_dont, /* complain_on_overflow */
1080
bfd_elf_generic_reloc, /* special_function */
1081
"R_MIPS_HIGHER", /* name */
1082
false, /* partial_inplace */
1084
0x0000ffff, /* dst_mask */
1085
false), /* pcrel_offset */
1087
/* Get the highest value of a 64 bit addend. */
1088
HOWTO (R_MIPS_HIGHEST, /* type */
1090
2, /* size (0 = byte, 1 = short, 2 = long) */
1092
false, /* pc_relative */
1094
complain_overflow_dont, /* complain_on_overflow */
1095
bfd_elf_generic_reloc, /* special_function */
1096
"R_MIPS_HIGHEST", /* name */
1097
false, /* partial_inplace */
1099
0x0000ffff, /* dst_mask */
1100
false), /* pcrel_offset */
1102
/* High 16 bits of displacement in global offset table. */
1103
/* FIXME: Not handled correctly. */
1104
HOWTO (R_MIPS_CALL_HI16, /* type */
1106
2, /* size (0 = byte, 1 = short, 2 = long) */
1108
false, /* pc_relative */
1110
complain_overflow_dont, /* complain_on_overflow */
1111
bfd_elf_generic_reloc, /* special_function */
1112
"R_MIPS_CALL_HI16", /* name */
1113
false, /* partial_inplace */
1115
0x0000ffff, /* dst_mask */
1116
false), /* pcrel_offset */
1118
/* Low 16 bits of displacement in global offset table. */
1119
/* FIXME: Not handled correctly. */
1120
HOWTO (R_MIPS_CALL_LO16, /* type */
1122
2, /* size (0 = byte, 1 = short, 2 = long) */
1124
false, /* pc_relative */
1126
complain_overflow_dont, /* complain_on_overflow */
1127
bfd_elf_generic_reloc, /* special_function */
1128
"R_MIPS_CALL_LO16", /* name */
1129
false, /* partial_inplace */
1131
0x0000ffff, /* dst_mask */
1132
false), /* pcrel_offset */
1134
/* Section displacement, used by an associated event location section. */
1135
/* FIXME: Not handled correctly. */
1136
HOWTO (R_MIPS_SCN_DISP, /* type */
1138
2, /* size (0 = byte, 1 = short, 2 = long) */
1140
false, /* pc_relative */
1142
complain_overflow_dont, /* complain_on_overflow */
1143
bfd_elf_generic_reloc, /* special_function */
1144
"R_MIPS_SCN_DISP", /* name */
1145
false, /* partial_inplace */
1147
0xffffffff, /* dst_mask */
1148
false), /* pcrel_offset */
1150
HOWTO (R_MIPS_REL16, /* type */
1152
1, /* size (0 = byte, 1 = short, 2 = long) */
1154
false, /* pc_relative */
1156
complain_overflow_signed, /* complain_on_overflow */
1157
bfd_elf_generic_reloc, /* special_function */
1158
"R_MIPS_REL16", /* name */
1159
false, /* partial_inplace */
1161
0xffff, /* dst_mask */
1162
false), /* pcrel_offset */
1164
/* These two are obsolete. */
1165
EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
1166
EMPTY_HOWTO (R_MIPS_PJUMP),
1168
/* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
1169
It must be used for multigot GOT's (and only there). */
1170
HOWTO (R_MIPS_RELGOT, /* type */
1172
2, /* size (0 = byte, 1 = short, 2 = long) */
1174
false, /* pc_relative */
1176
complain_overflow_dont, /* complain_on_overflow */
1177
bfd_elf_generic_reloc, /* special_function */
1178
"R_MIPS_RELGOT", /* name */
1179
false, /* partial_inplace */
1181
0xffffffff, /* dst_mask */
1182
false), /* pcrel_offset */
1184
/* Protected jump conversion. This is an optimization hint. No
1185
relocation is required for correctness. */
1186
HOWTO (R_MIPS_JALR, /* type */
1188
2, /* size (0 = byte, 1 = short, 2 = long) */
1190
false, /* pc_relative */
1192
complain_overflow_dont, /* complain_on_overflow */
1193
bfd_elf_generic_reloc, /* special_function */
1194
"R_MIPS_JALR", /* name */
1195
false, /* partial_inplace */
1197
0x00000000, /* dst_mask */
1198
false), /* pcrel_offset */
1201
/* Swap in a MIPS 64-bit Rel reloc. */
1204
mips_elf64_swap_reloc_in (abfd, src, dst)
1206
const Elf64_Mips_External_Rel *src;
1207
Elf64_Mips_Internal_Rel *dst;
1209
dst->r_offset = H_GET_64 (abfd, src->r_offset);
1210
dst->r_sym = H_GET_32 (abfd, src->r_sym);
1211
dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1212
dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1213
dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1214
dst->r_type = H_GET_8 (abfd, src->r_type);
1217
/* Swap in a MIPS 64-bit Rela reloc. */
1220
mips_elf64_swap_reloca_in (abfd, src, dst)
1222
const Elf64_Mips_External_Rela *src;
1223
Elf64_Mips_Internal_Rela *dst;
1225
dst->r_offset = H_GET_64 (abfd, src->r_offset);
1226
dst->r_sym = H_GET_32 (abfd, src->r_sym);
1227
dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1228
dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1229
dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1230
dst->r_type = H_GET_8 (abfd, src->r_type);
1231
dst->r_addend = H_GET_S64 (abfd, src->r_addend);
1234
/* Swap out a MIPS 64-bit Rel reloc. */
1237
mips_elf64_swap_reloc_out (abfd, src, dst)
1239
const Elf64_Mips_Internal_Rel *src;
1240
Elf64_Mips_External_Rel *dst;
1242
H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1243
H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1244
H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1245
H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1246
H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1247
H_PUT_8 (abfd, src->r_type, dst->r_type);
1250
/* Swap out a MIPS 64-bit Rela reloc. */
1253
mips_elf64_swap_reloca_out (abfd, src, dst)
1255
const Elf64_Mips_Internal_Rela *src;
1256
Elf64_Mips_External_Rela *dst;
1258
H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1259
H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1260
H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1261
H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1262
H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1263
H_PUT_8 (abfd, src->r_type, dst->r_type);
1264
H_PUT_S64 (abfd, src->r_addend, dst->r_addend);
1267
/* Swap in a MIPS 64-bit Rel reloc. */
1270
mips_elf64_be_swap_reloc_in (abfd, src, dst)
1272
const bfd_byte *src;
1273
Elf_Internal_Rel *dst;
1275
Elf64_Mips_Internal_Rel mirel;
1277
mips_elf64_swap_reloc_in (abfd,
1278
(const Elf64_Mips_External_Rel *) src,
1281
dst[0].r_offset = mirel.r_offset;
1282
dst[0].r_info = ELF64_R_INFO (mirel.r_sym, mirel.r_type);
1283
dst[1].r_offset = mirel.r_offset;
1284
dst[1].r_info = ELF64_R_INFO (mirel.r_ssym, mirel.r_type2);
1285
dst[2].r_offset = mirel.r_offset;
1286
dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirel.r_type3);
1289
/* Swap in a MIPS 64-bit Rela reloc. */
1292
mips_elf64_be_swap_reloca_in (abfd, src, dst)
1294
const bfd_byte *src;
1295
Elf_Internal_Rela *dst;
1297
Elf64_Mips_Internal_Rela mirela;
1299
mips_elf64_swap_reloca_in (abfd,
1300
(const Elf64_Mips_External_Rela *) src,
1303
dst[0].r_offset = mirela.r_offset;
1304
dst[0].r_info = ELF64_R_INFO (mirela.r_sym, mirela.r_type);
1305
dst[0].r_addend = mirela.r_addend;
1306
dst[1].r_offset = mirela.r_offset;
1307
dst[1].r_info = ELF64_R_INFO (mirela.r_ssym, mirela.r_type2);
1308
dst[1].r_addend = 0;
1309
dst[2].r_offset = mirela.r_offset;
1310
dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirela.r_type3);
1311
dst[2].r_addend = 0;
1314
/* Swap out a MIPS 64-bit Rel reloc. */
1317
mips_elf64_be_swap_reloc_out (abfd, src, dst)
1319
const Elf_Internal_Rel *src;
1322
Elf64_Mips_Internal_Rel mirel;
1324
mirel.r_offset = src[0].r_offset;
1325
BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1326
BFD_ASSERT(src[0].r_offset == src[2].r_offset);
1328
mirel.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1329
mirel.r_sym = ELF64_R_SYM (src[0].r_info);
1330
mirel.r_type2 = ELF64_MIPS_R_TYPE2 (src[1].r_info);
1331
mirel.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1332
mirel.r_type3 = ELF64_MIPS_R_TYPE3 (src[2].r_info);
1334
mips_elf64_swap_reloc_out (abfd, &mirel,
1335
(Elf64_Mips_External_Rel *) dst);
1338
/* Swap out a MIPS 64-bit Rela reloc. */
1341
mips_elf64_be_swap_reloca_out (abfd, src, dst)
1343
const Elf_Internal_Rela *src;
1346
Elf64_Mips_Internal_Rela mirela;
1348
mirela.r_offset = src[0].r_offset;
1349
BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1350
BFD_ASSERT(src[0].r_offset == src[2].r_offset);
1352
mirela.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1353
mirela.r_sym = ELF64_R_SYM (src[0].r_info);
1354
mirela.r_addend = src[0].r_addend;
1355
BFD_ASSERT(src[1].r_addend == 0);
1356
BFD_ASSERT(src[2].r_addend == 0);
1358
mirela.r_type2 = ELF64_MIPS_R_TYPE2 (src[1].r_info);
1359
mirela.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1360
mirela.r_type3 = ELF64_MIPS_R_TYPE3 (src[2].r_info);
1362
mips_elf64_swap_reloca_out (abfd, &mirela,
1363
(Elf64_Mips_External_Rela *) dst);
1366
/* Do a R_MIPS_HI16 relocation. */
1368
bfd_reloc_status_type
1369
mips_elf64_hi16_reloc (abfd,
1376
bfd *abfd ATTRIBUTE_UNUSED;
1377
arelent *reloc_entry;
1379
PTR data ATTRIBUTE_UNUSED;
1380
asection *input_section;
1382
char **error_message ATTRIBUTE_UNUSED;
1384
/* If we're relocating, and this is an external symbol, we don't
1385
want to change anything. */
1386
if (output_bfd != (bfd *) NULL
1387
&& (symbol->flags & BSF_SECTION_SYM) == 0
1388
&& (! reloc_entry->howto->partial_inplace
1389
|| reloc_entry->addend == 0))
1391
reloc_entry->address += input_section->output_offset;
1392
return bfd_reloc_ok;
1395
if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
1396
reloc_entry->addend += 0x8000;
1398
return bfd_reloc_continue;
1401
/* Do a R_MIPS_HIGHER relocation. */
1403
bfd_reloc_status_type
1404
mips_elf64_higher_reloc (abfd,
1411
bfd *abfd ATTRIBUTE_UNUSED;
1412
arelent *reloc_entry;
1414
PTR data ATTRIBUTE_UNUSED;
1415
asection *input_section;
1417
char **error_message ATTRIBUTE_UNUSED;
1419
/* If we're relocating, and this is an external symbol, we don't
1420
want to change anything. */
1421
if (output_bfd != (bfd *) NULL
1422
&& (symbol->flags & BSF_SECTION_SYM) == 0
1423
&& (! reloc_entry->howto->partial_inplace
1424
|| reloc_entry->addend == 0))
1426
reloc_entry->address += input_section->output_offset;
1427
return bfd_reloc_ok;
1430
if (((reloc_entry->addend & 0xffffffff) + 0x80008000)
1432
reloc_entry->addend += 0x80008000;
1434
return bfd_reloc_continue;
1437
/* Do a R_MIPS_HIGHEST relocation. */
1439
bfd_reloc_status_type
1440
mips_elf64_highest_reloc (abfd,
1447
bfd *abfd ATTRIBUTE_UNUSED;
1448
arelent *reloc_entry;
1450
PTR data ATTRIBUTE_UNUSED;
1451
asection *input_section;
1453
char **error_message ATTRIBUTE_UNUSED;
1455
/* If we're relocating, and this is an external symbol, we don't
1456
want to change anything. */
1457
if (output_bfd != (bfd *) NULL
1458
&& (symbol->flags & BSF_SECTION_SYM) == 0
1459
&& (! reloc_entry->howto->partial_inplace
1460
|| reloc_entry->addend == 0))
1462
reloc_entry->address += input_section->output_offset;
1463
return bfd_reloc_ok;
1466
if (((reloc_entry->addend & 0xffffffffffff) + 0x800080008000)
1468
reloc_entry->addend += 0x800080008000;
1470
return bfd_reloc_continue;
1473
/* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset
1474
table used for PIC code. If the symbol is an external symbol, the
1475
instruction is modified to contain the offset of the appropriate
1476
entry in the global offset table. If the symbol is a section
1477
symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
1478
addends are combined to form the real addend against the section
1479
symbol; the GOT16 is modified to contain the offset of an entry in
1480
the global offset table, and the LO16 is modified to offset it
1481
appropriately. Thus an offset larger than 16 bits requires a
1482
modified value in the global offset table.
1484
This implementation suffices for the assembler, but the linker does
1485
not yet know how to create global offset tables. */
1487
bfd_reloc_status_type
1488
mips_elf64_got16_reloc (abfd,
1496
arelent *reloc_entry;
1499
asection *input_section;
1501
char **error_message;
1503
/* If we're relocating, and this an external symbol, we don't want
1504
to change anything. */
1505
if (output_bfd != (bfd *) NULL
1506
&& (symbol->flags & BSF_SECTION_SYM) == 0
1507
&& reloc_entry->addend == 0)
1509
reloc_entry->address += input_section->output_offset;
1510
return bfd_reloc_ok;
1513
/* If we're relocating, and this is a local symbol, we can handle it
1515
if (output_bfd != (bfd *) NULL
1516
&& (symbol->flags & BSF_SECTION_SYM) != 0)
1517
return mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data,
1518
input_section, output_bfd, error_message);
1523
/* Set the GP value for OUTPUT_BFD. Returns false if this is a
1524
dangerous relocation. */
1527
mips_elf64_assign_gp (output_bfd, pgp)
1535
/* If we've already figured out what GP will be, just return it. */
1536
*pgp = _bfd_get_gp_value (output_bfd);
1540
count = bfd_get_symcount (output_bfd);
1541
sym = bfd_get_outsymbols (output_bfd);
1543
/* The linker script will have created a symbol named `_gp' with the
1544
appropriate value. */
1545
if (sym == (asymbol **) NULL)
1549
for (i = 0; i < count; i++, sym++)
1551
register const char *name;
1553
name = bfd_asymbol_name (*sym);
1554
if (*name == '_' && strcmp (name, "_gp") == 0)
1556
*pgp = bfd_asymbol_value (*sym);
1557
_bfd_set_gp_value (output_bfd, *pgp);
1565
/* Only get the error once. */
1567
_bfd_set_gp_value (output_bfd, *pgp);
1574
/* We have to figure out the gp value, so that we can adjust the
1575
symbol value correctly. We look up the symbol _gp in the output
1576
BFD. If we can't find it, we're stuck. We cache it in the ELF
1577
target data. We don't need to adjust the symbol value for an
1578
external symbol if we are producing relocateable output. */
1580
static bfd_reloc_status_type
1581
mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message, pgp)
1584
boolean relocateable;
1585
char **error_message;
1588
if (bfd_is_und_section (symbol->section)
1592
return bfd_reloc_undefined;
1595
*pgp = _bfd_get_gp_value (output_bfd);
1598
|| (symbol->flags & BSF_SECTION_SYM) != 0))
1602
/* Make up a value. */
1603
*pgp = symbol->section->output_section->vma + 0x4000;
1604
_bfd_set_gp_value (output_bfd, *pgp);
1606
else if (!mips_elf64_assign_gp (output_bfd, pgp))
1609
(char *) _("GP relative relocation when _gp not defined");
1610
return bfd_reloc_dangerous;
1614
return bfd_reloc_ok;
1617
/* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must
1618
become the offset from the gp register. */
1620
bfd_reloc_status_type
1621
mips_elf64_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
1622
output_bfd, error_message)
1624
arelent *reloc_entry;
1627
asection *input_section;
1629
char **error_message;
1631
boolean relocateable;
1632
bfd_reloc_status_type ret;
1635
/* If we're relocating, and this is an external symbol with no
1636
addend, we don't want to change anything. We will only have an
1637
addend if this is a newly created reloc, not read from an ELF
1639
if (output_bfd != (bfd *) NULL
1640
&& (symbol->flags & BSF_SECTION_SYM) == 0
1641
&& reloc_entry->addend == 0)
1643
reloc_entry->address += input_section->output_offset;
1644
return bfd_reloc_ok;
1647
if (output_bfd != (bfd *) NULL)
1648
relocateable = true;
1651
relocateable = false;
1652
output_bfd = symbol->section->output_section->owner;
1655
ret = mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
1657
if (ret != bfd_reloc_ok)
1660
return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1661
input_section, relocateable,
1665
/* Do a R_MIPS_GPREL16 RELA relocation. */
1667
bfd_reloc_status_type
1668
mips_elf64_gprel16_reloca (abfd, reloc_entry, symbol, data, input_section,
1669
output_bfd, error_message)
1671
arelent *reloc_entry;
1673
PTR data ATTRIBUTE_UNUSED;
1674
asection *input_section;
1676
char **error_message;
1678
boolean relocateable;
1681
/* This works only for NewABI. */
1682
BFD_ASSERT (reloc_entry->howto->src_mask == 0);
1684
/* If we're relocating, and this is an external symbol with no
1685
addend, we don't want to change anything. We will only have an
1686
addend if this is a newly created reloc, not read from an ELF
1688
if (output_bfd != (bfd *) NULL
1689
&& (symbol->flags & BSF_SECTION_SYM) == 0
1690
&& reloc_entry->addend == 0)
1692
reloc_entry->address += input_section->output_offset;
1693
return bfd_reloc_ok;
1696
if (output_bfd != (bfd *) NULL)
1697
relocateable = true;
1700
relocateable = false;
1701
output_bfd = symbol->section->output_section->owner;
1704
if (prev_reloc_address != reloc_entry->address)
1705
prev_reloc_address = reloc_entry->address;
1708
mips_elf64_final_gp (output_bfd, symbol, relocateable, error_message,
1710
prev_reloc_addend = reloc_entry->addend + reloc_entry->address - gp;
1711
if (symbol->flags & BSF_LOCAL)
1712
prev_reloc_addend += _bfd_get_gp_value (abfd);
1713
/*fprintf(stderr, "Addend: %lx, Next Addend: %lx\n", reloc_entry->addend, prev_reloc_addend);*/
1716
return bfd_reloc_ok;
1719
/* Do a R_MIPS_LITERAL relocation. */
1721
bfd_reloc_status_type
1722
mips_elf64_literal_reloc (abfd, reloc_entry, symbol, data, input_section,
1723
output_bfd, error_message)
1725
arelent *reloc_entry;
1728
asection *input_section;
1730
char **error_message;
1732
/* If we're relocating, and this is an external symbol, we don't
1733
want to change anything. */
1734
if (output_bfd != (bfd *) NULL
1735
&& (symbol->flags & BSF_SECTION_SYM) == 0
1736
&& (! reloc_entry->howto->partial_inplace
1737
|| reloc_entry->addend == 0))
1739
reloc_entry->address += input_section->output_offset;
1740
return bfd_reloc_ok;
1743
/* FIXME: The entries in the .lit8 and .lit4 sections should be merged.
1744
Currently we simply call mips_elf64_gprel16_reloc. */
1745
return mips_elf64_gprel16_reloc (abfd, reloc_entry, symbol, data,
1746
input_section, output_bfd, error_message);
1749
/* Do a R_MIPS_GPREL32 relocation. Is this 32 bit value the offset
1750
from the gp register? XXX */
1752
bfd_reloc_status_type
1753
mips_elf64_gprel32_reloc (abfd,
1761
arelent *reloc_entry;
1764
asection *input_section;
1766
char **error_message;
1768
boolean relocateable;
1769
bfd_reloc_status_type ret;
1774
/* If we're relocating, and this is an external symbol with no
1775
addend, we don't want to change anything. We will only have an
1776
addend if this is a newly created reloc, not read from an ELF
1778
if (output_bfd != (bfd *) NULL
1779
&& (symbol->flags & BSF_SECTION_SYM) == 0
1780
&& reloc_entry->addend == 0)
1782
*error_message = (char *)
1783
_("32bits gp relative relocation occurs for an external symbol");
1784
return bfd_reloc_outofrange;
1787
if (output_bfd != (bfd *) NULL)
1789
relocateable = true;
1790
gp = _bfd_get_gp_value (output_bfd);
1794
relocateable = false;
1795
output_bfd = symbol->section->output_section->owner;
1797
ret = mips_elf64_final_gp (output_bfd, symbol, relocateable,
1798
error_message, &gp);
1799
if (ret != bfd_reloc_ok)
1803
if (bfd_is_com_section (symbol->section))
1806
relocation = symbol->value;
1808
relocation += symbol->section->output_section->vma;
1809
relocation += symbol->section->output_offset;
1811
if (reloc_entry->address > input_section->_cooked_size)
1812
return bfd_reloc_outofrange;
1814
if (reloc_entry->howto->src_mask == 0)
1816
/* This case arises with the 64-bit MIPS ELF ABI. */
1820
val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1822
/* Set val to the offset into the section or symbol. */
1823
val += reloc_entry->addend;
1825
/* Adjust val for the final section location and GP value. If we
1826
are producing relocateable output, we don't want to do this for
1827
an external symbol. */
1829
|| (symbol->flags & BSF_SECTION_SYM) != 0)
1830
val += relocation - gp;
1832
bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
1835
reloc_entry->address += input_section->output_offset;
1837
return bfd_reloc_ok;
1840
/* Do a R_MIPS_SHIFT6 relocation. The MSB of the shift is stored at bit 2,
1841
the rest is at bits 6-10. The bitpos alredy got right by the howto. */
1843
bfd_reloc_status_type
1844
mips_elf64_shift6_reloc (abfd, reloc_entry, symbol, data, input_section,
1845
output_bfd, error_message)
1846
bfd *abfd ATTRIBUTE_UNUSED;
1847
arelent *reloc_entry;
1849
PTR data ATTRIBUTE_UNUSED;
1850
asection *input_section;
1852
char **error_message ATTRIBUTE_UNUSED;
1854
/* If we're relocating, and this is an external symbol, we don't
1855
want to change anything. */
1856
if (output_bfd != (bfd *) NULL
1857
&& (symbol->flags & BSF_SECTION_SYM) == 0
1858
&& (! reloc_entry->howto->partial_inplace
1859
|| reloc_entry->addend == 0))
1861
reloc_entry->address += input_section->output_offset;
1862
return bfd_reloc_ok;
1865
reloc_entry->addend = (reloc_entry->addend & 0x00007c0)
1866
| (reloc_entry->addend & 0x00000800) >> 9;
1868
return bfd_reloc_continue;
1871
/* Given a BFD reloc type, return a howto structure. */
1873
static reloc_howto_type *
1874
bfd_elf64_bfd_reloc_type_lookup (abfd, code)
1875
bfd *abfd ATTRIBUTE_UNUSED;
1876
bfd_reloc_code_real_type code;
1878
/* FIXME: We default to RELA here instead of choosing the right
1879
relocation variant. */
1880
reloc_howto_type *howto_table = mips_elf64_howto_table_rela;
1884
case BFD_RELOC_NONE:
1885
return &howto_table[R_MIPS_NONE];
1887
return &howto_table[R_MIPS_16];
1889
return &howto_table[R_MIPS_32];
1891
case BFD_RELOC_CTOR:
1892
return &howto_table[R_MIPS_64];
1893
case BFD_RELOC_16_PCREL:
1894
return &howto_table[R_MIPS_PC16];
1895
case BFD_RELOC_HI16_S:
1896
return &howto_table[R_MIPS_HI16];
1897
case BFD_RELOC_LO16:
1898
return &howto_table[R_MIPS_LO16];
1899
case BFD_RELOC_GPREL16:
1900
return &howto_table[R_MIPS_GPREL16];
1901
case BFD_RELOC_GPREL32:
1902
return &howto_table[R_MIPS_GPREL32];
1903
case BFD_RELOC_MIPS_JMP:
1904
return &howto_table[R_MIPS_26];
1905
case BFD_RELOC_MIPS_LITERAL:
1906
return &howto_table[R_MIPS_LITERAL];
1907
case BFD_RELOC_MIPS_GOT16:
1908
return &howto_table[R_MIPS_GOT16];
1909
case BFD_RELOC_MIPS_CALL16:
1910
return &howto_table[R_MIPS_CALL16];
1911
case BFD_RELOC_MIPS_SHIFT5:
1912
return &howto_table[R_MIPS_SHIFT5];
1913
case BFD_RELOC_MIPS_SHIFT6:
1914
return &howto_table[R_MIPS_SHIFT6];
1915
case BFD_RELOC_MIPS_GOT_DISP:
1916
return &howto_table[R_MIPS_GOT_DISP];
1917
case BFD_RELOC_MIPS_GOT_PAGE:
1918
return &howto_table[R_MIPS_GOT_PAGE];
1919
case BFD_RELOC_MIPS_GOT_OFST:
1920
return &howto_table[R_MIPS_GOT_OFST];
1921
case BFD_RELOC_MIPS_GOT_HI16:
1922
return &howto_table[R_MIPS_GOT_HI16];
1923
case BFD_RELOC_MIPS_GOT_LO16:
1924
return &howto_table[R_MIPS_GOT_LO16];
1925
case BFD_RELOC_MIPS_SUB:
1926
return &howto_table[R_MIPS_SUB];
1927
case BFD_RELOC_MIPS_INSERT_A:
1928
return &howto_table[R_MIPS_INSERT_A];
1929
case BFD_RELOC_MIPS_INSERT_B:
1930
return &howto_table[R_MIPS_INSERT_B];
1931
case BFD_RELOC_MIPS_DELETE:
1932
return &howto_table[R_MIPS_DELETE];
1933
case BFD_RELOC_MIPS_HIGHEST:
1934
return &howto_table[R_MIPS_HIGHEST];
1935
case BFD_RELOC_MIPS_HIGHER:
1936
return &howto_table[R_MIPS_HIGHER];
1937
case BFD_RELOC_MIPS_CALL_HI16:
1938
return &howto_table[R_MIPS_CALL_HI16];
1939
case BFD_RELOC_MIPS_CALL_LO16:
1940
return &howto_table[R_MIPS_CALL_LO16];
1941
case BFD_RELOC_MIPS_SCN_DISP:
1942
return &howto_table[R_MIPS_SCN_DISP];
1943
case BFD_RELOC_MIPS_REL16:
1944
return &howto_table[R_MIPS_REL16];
1945
/* Use of R_MIPS_ADD_IMMEDIATE and R_MIPS_PJUMP is deprecated. */
1946
case BFD_RELOC_MIPS_RELGOT:
1947
return &howto_table[R_MIPS_RELGOT];
1948
case BFD_RELOC_MIPS_JALR:
1949
return &howto_table[R_MIPS_JALR];
1951
case BFD_RELOC_MIPS16_JMP:
1952
return &elf_mips16_jump_howto;
1953
case BFD_RELOC_MIPS16_GPREL:
1954
return &elf_mips16_gprel_howto;
1955
case BFD_RELOC_VTABLE_INHERIT:
1956
return &elf_mips_gnu_vtinherit_howto;
1957
case BFD_RELOC_VTABLE_ENTRY:
1958
return &elf_mips_gnu_vtentry_howto;
1959
case BFD_RELOC_PCREL_HI16_S:
1960
return &elf_mips_gnu_rel_hi16;
1961
case BFD_RELOC_PCREL_LO16:
1962
return &elf_mips_gnu_rel_lo16;
1963
case BFD_RELOC_16_PCREL_S2:
1964
return &elf_mips_gnu_rel16_s2;
1965
case BFD_RELOC_64_PCREL:
1966
return &elf_mips_gnu_pcrel64;
1967
case BFD_RELOC_32_PCREL:
1968
return &elf_mips_gnu_pcrel32;
1971
bfd_set_error (bfd_error_bad_value);
1976
/* Given a MIPS Elf64_Internal_Rel, fill in an arelent structure. */
1978
static reloc_howto_type *
1979
mips_elf64_rtype_to_howto (r_type, rela_p)
1980
unsigned int r_type;
1987
return &elf_mips16_jump_howto;
1989
case R_MIPS16_GPREL:
1990
return &elf_mips16_gprel_howto;
1992
case R_MIPS_GNU_VTINHERIT:
1993
return &elf_mips_gnu_vtinherit_howto;
1995
case R_MIPS_GNU_VTENTRY:
1996
return &elf_mips_gnu_vtentry_howto;
1998
case R_MIPS_GNU_REL_HI16:
1999
return &elf_mips_gnu_rel_hi16;
2001
case R_MIPS_GNU_REL_LO16:
2002
return &elf_mips_gnu_rel_lo16;
2004
case R_MIPS_GNU_REL16_S2:
2005
return &elf_mips_gnu_rel16_s2;
2008
return &elf_mips_gnu_pcrel64;
2011
return &elf_mips_gnu_pcrel32;
2016
BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
2018
return &mips_elf64_howto_table_rela[r_type];
2020
return &mips_elf64_howto_table_rel[r_type];
2025
/* Prevent relocation handling by bfd for MIPS ELF64. */
2028
mips_elf64_info_to_howto_rel (abfd, cache_ptr, dst)
2029
bfd *abfd ATTRIBUTE_UNUSED;
2030
arelent *cache_ptr ATTRIBUTE_UNUSED;
2031
Elf64_Internal_Rel *dst ATTRIBUTE_UNUSED;
2037
mips_elf64_info_to_howto_rela (abfd, cache_ptr, dst)
2038
bfd *abfd ATTRIBUTE_UNUSED;
2039
arelent *cache_ptr ATTRIBUTE_UNUSED;
2040
Elf64_Internal_Rela *dst ATTRIBUTE_UNUSED;
2045
/* Since each entry in an SHT_REL or SHT_RELA section can represent up
2046
to three relocs, we must tell the user to allocate more space. */
2049
mips_elf64_get_reloc_upper_bound (abfd, sec)
2050
bfd *abfd ATTRIBUTE_UNUSED;
2053
return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
2056
/* Read the relocations from one reloc section. */
2059
mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
2063
const Elf_Internal_Shdr *rel_hdr;
2065
PTR allocated = NULL;
2066
bfd_byte *native_relocs;
2072
reloc_howto_type *howto_table;
2074
allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
2075
if (allocated == NULL)
2078
if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
2079
|| (bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
2082
native_relocs = (bfd_byte *) allocated;
2084
relents = asect->relocation + asect->reloc_count;
2086
entsize = rel_hdr->sh_entsize;
2087
BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
2088
|| entsize == sizeof (Elf64_Mips_External_Rela));
2090
count = rel_hdr->sh_size / entsize;
2092
if (entsize == sizeof (Elf64_Mips_External_Rel))
2093
howto_table = mips_elf64_howto_table_rel;
2095
howto_table = mips_elf64_howto_table_rela;
2098
for (i = 0; i < count; i++, native_relocs += entsize)
2100
Elf64_Mips_Internal_Rela rela;
2101
boolean used_sym, used_ssym;
2104
if (entsize == sizeof (Elf64_Mips_External_Rela))
2105
mips_elf64_swap_reloca_in (abfd,
2106
(Elf64_Mips_External_Rela *) native_relocs,
2110
Elf64_Mips_Internal_Rel rel;
2112
mips_elf64_swap_reloc_in (abfd,
2113
(Elf64_Mips_External_Rel *) native_relocs,
2115
rela.r_offset = rel.r_offset;
2116
rela.r_sym = rel.r_sym;
2117
rela.r_ssym = rel.r_ssym;
2118
rela.r_type3 = rel.r_type3;
2119
rela.r_type2 = rel.r_type2;
2120
rela.r_type = rel.r_type;
2124
/* Each entry represents up to three actual relocations. */
2128
for (ir = 0; ir < 3; ir++)
2130
enum elf_mips_reloc_type type;
2137
type = (enum elf_mips_reloc_type) rela.r_type;
2140
type = (enum elf_mips_reloc_type) rela.r_type2;
2143
type = (enum elf_mips_reloc_type) rela.r_type3;
2147
if (type == R_MIPS_NONE)
2149
/* There are no more relocations in this entry. If this
2150
is the first entry, we need to generate a dummy
2151
relocation so that the generic linker knows that
2152
there has been a break in the sequence of relocations
2153
applying to a particular address. */
2156
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2157
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2158
relent->address = rela.r_offset;
2160
relent->address = rela.r_offset - asect->vma;
2162
relent->howto = &howto_table[(int) R_MIPS_NONE];
2168
/* Some types require symbols, whereas some do not. */
2172
case R_MIPS_LITERAL:
2173
case R_MIPS_INSERT_A:
2174
case R_MIPS_INSERT_B:
2176
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2182
if (rela.r_sym == 0)
2183
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2188
ps = symbols + rela.r_sym - 1;
2190
if ((s->flags & BSF_SECTION_SYM) == 0)
2191
relent->sym_ptr_ptr = ps;
2193
relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
2198
else if (! used_ssym)
2200
switch (rela.r_ssym)
2203
relent->sym_ptr_ptr =
2204
bfd_abs_section_ptr->symbol_ptr_ptr;
2210
/* FIXME: I think these need to be handled using
2211
special howto structures. */
2223
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2228
/* The address of an ELF reloc is section relative for an
2229
object file, and absolute for an executable file or
2230
shared library. The address of a BFD reloc is always
2231
section relative. */
2232
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2233
relent->address = rela.r_offset;
2235
relent->address = rela.r_offset - asect->vma;
2237
relent->addend = rela.r_addend;
2239
relent->howto = &howto_table[(int) type];
2245
asect->reloc_count += relent - relents;
2247
if (allocated != NULL)
2253
if (allocated != NULL)
2258
/* Read the relocations. On Irix 6, there can be two reloc sections
2259
associated with a single data section. */
2262
mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
2269
struct bfd_elf_section_data * const d = elf_section_data (asect);
2273
bfd_set_error (bfd_error_invalid_operation);
2277
if (asect->relocation != NULL
2278
|| (asect->flags & SEC_RELOC) == 0
2279
|| asect->reloc_count == 0)
2282
/* Allocate space for 3 arelent structures for each Rel structure. */
2283
amt = asect->reloc_count;
2284
amt *= 3 * sizeof (arelent);
2285
asect->relocation = (arelent *) bfd_alloc (abfd, amt);
2286
if (asect->relocation == NULL)
2289
/* The slurp_one_reloc_table routine increments reloc_count. */
2290
asect->reloc_count = 0;
2292
if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
2294
if (d->rel_hdr2 != NULL)
2296
if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
2304
/* Write out the relocations. */
2307
mips_elf64_write_relocs (abfd, sec, data)
2312
boolean *failedp = (boolean *) data;
2314
Elf_Internal_Shdr *rel_hdr;
2317
/* If we have already failed, don't do anything. */
2321
if ((sec->flags & SEC_RELOC) == 0)
2324
/* The linker backend writes the relocs out itself, and sets the
2325
reloc_count field to zero to inhibit writing them here. Also,
2326
sometimes the SEC_RELOC flag gets set even when there aren't any
2328
if (sec->reloc_count == 0)
2331
/* We can combine up to three relocs that refer to the same address
2332
if the latter relocs have no associated symbol. */
2334
for (idx = 0; idx < sec->reloc_count; idx++)
2341
addr = sec->orelocation[idx]->address;
2342
for (i = 0; i < 2; i++)
2346
if (idx + 1 >= sec->reloc_count)
2348
r = sec->orelocation[idx + 1];
2349
if (r->address != addr
2350
|| ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2351
|| (*r->sym_ptr_ptr)->value != 0)
2354
/* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2360
rel_hdr = &elf_section_data (sec)->rel_hdr;
2362
/* Do the actual relocation. */
2364
if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rel))
2365
mips_elf64_write_rel (abfd, sec, rel_hdr, &count, data);
2366
else if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rela))
2367
mips_elf64_write_rela (abfd, sec, rel_hdr, &count, data);
2373
mips_elf64_write_rel (abfd, sec, rel_hdr, count, data)
2376
Elf_Internal_Shdr *rel_hdr;
2380
boolean *failedp = (boolean *) data;
2381
Elf64_Mips_External_Rel *ext_rel;
2383
asymbol *last_sym = 0;
2384
int last_sym_idx = 0;
2386
rel_hdr->sh_size = (bfd_vma)(rel_hdr->sh_entsize * *count);
2387
rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size);
2388
if (rel_hdr->contents == NULL)
2394
ext_rel = (Elf64_Mips_External_Rel *) rel_hdr->contents;
2395
for (idx = 0; idx < sec->reloc_count; idx++, ext_rel++)
2398
Elf64_Mips_Internal_Rel int_rel;
2403
ptr = sec->orelocation[idx];
2405
/* The address of an ELF reloc is section relative for an object
2406
file, and absolute for an executable file or shared library.
2407
The address of a BFD reloc is always section relative. */
2408
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2409
int_rel.r_offset = ptr->address;
2411
int_rel.r_offset = ptr->address + sec->vma;
2413
sym = *ptr->sym_ptr_ptr;
2414
if (sym == last_sym)
2419
n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2429
int_rel.r_ssym = RSS_UNDEF;
2431
if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2432
&& ! _bfd_elf_validate_reloc (abfd, ptr))
2438
int_rel.r_type = ptr->howto->type;
2439
int_rel.r_type2 = (int) R_MIPS_NONE;
2440
int_rel.r_type3 = (int) R_MIPS_NONE;
2442
for (i = 0; i < 2; i++)
2446
if (idx + 1 >= sec->reloc_count)
2448
r = sec->orelocation[idx + 1];
2449
if (r->address != ptr->address
2450
|| ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2451
|| (*r->sym_ptr_ptr)->value != 0)
2454
/* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2457
int_rel.r_type2 = r->howto->type;
2459
int_rel.r_type3 = r->howto->type;
2464
mips_elf64_swap_reloc_out (abfd, &int_rel, ext_rel);
2467
BFD_ASSERT (ext_rel - (Elf64_Mips_External_Rel *) rel_hdr->contents
2472
mips_elf64_write_rela (abfd, sec, rela_hdr, count, data)
2475
Elf_Internal_Shdr *rela_hdr;
2479
boolean *failedp = (boolean *) data;
2480
Elf64_Mips_External_Rela *ext_rela;
2482
asymbol *last_sym = 0;
2483
int last_sym_idx = 0;
2485
rela_hdr->sh_size = (bfd_vma)(rela_hdr->sh_entsize * *count);
2486
rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
2487
if (rela_hdr->contents == NULL)
2493
ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
2494
for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
2497
Elf64_Mips_Internal_Rela int_rela;
2502
ptr = sec->orelocation[idx];
2504
/* The address of an ELF reloc is section relative for an object
2505
file, and absolute for an executable file or shared library.
2506
The address of a BFD reloc is always section relative. */
2507
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2508
int_rela.r_offset = ptr->address;
2510
int_rela.r_offset = ptr->address + sec->vma;
2512
sym = *ptr->sym_ptr_ptr;
2513
if (sym == last_sym)
2518
n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2528
int_rela.r_addend = ptr->addend;
2529
int_rela.r_ssym = RSS_UNDEF;
2531
if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2532
&& ! _bfd_elf_validate_reloc (abfd, ptr))
2538
int_rela.r_type = ptr->howto->type;
2539
int_rela.r_type2 = (int) R_MIPS_NONE;
2540
int_rela.r_type3 = (int) R_MIPS_NONE;
2542
for (i = 0; i < 2; i++)
2546
if (idx + 1 >= sec->reloc_count)
2548
r = sec->orelocation[idx + 1];
2549
if (r->address != ptr->address
2550
|| ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2551
|| (*r->sym_ptr_ptr)->value != 0)
2554
/* We can merge the reloc at IDX + 1 with the reloc at IDX. */
2557
int_rela.r_type2 = r->howto->type;
2559
int_rela.r_type3 = r->howto->type;
2564
mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
2567
BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
2571
/* Set the right machine number for a MIPS ELF file. */
2574
mips_elf64_object_p (abfd)
2579
/* Irix 6 is broken. Object file symbol tables are not always
2580
sorted correctly such that local symbols precede global symbols,
2581
and the sh_info field in the symbol table is not always right. */
2582
if (SGI_COMPAT(abfd))
2583
elf_bad_symtab (abfd) = true;
2585
mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags);
2586
bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach);
2590
/* Depending on the target vector we generate some version of Irix
2591
executables or "normal" MIPS ELF ABI executables. */
2592
static irix_compat_t
2593
elf64_mips_irix_compat (abfd)
2596
if ((abfd->xvec == &bfd_elf64_tradbigmips_vec)
2597
|| (abfd->xvec == &bfd_elf64_tradlittlemips_vec))
2603
/* ECOFF swapping routines. These are used when dealing with the
2604
.mdebug section, which is in the ECOFF debugging format. */
2605
static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
2607
/* Symbol table magic number. */
2609
/* Alignment of debugging information. E.g., 4. */
2611
/* Sizes of external symbolic information. */
2612
sizeof (struct hdr_ext),
2613
sizeof (struct dnr_ext),
2614
sizeof (struct pdr_ext),
2615
sizeof (struct sym_ext),
2616
sizeof (struct opt_ext),
2617
sizeof (struct fdr_ext),
2618
sizeof (struct rfd_ext),
2619
sizeof (struct ext_ext),
2620
/* Functions to swap in external symbolic data. */
2629
_bfd_ecoff_swap_tir_in,
2630
_bfd_ecoff_swap_rndx_in,
2631
/* Functions to swap out external symbolic data. */
2640
_bfd_ecoff_swap_tir_out,
2641
_bfd_ecoff_swap_rndx_out,
2642
/* Function to read in symbolic data. */
2643
_bfd_mips_elf_read_ecoff_info
2646
/* Relocations in the 64 bit MIPS ELF ABI are more complex than in
2647
standard ELF. This structure is used to redirect the relocation
2648
handling routines. */
2650
const struct elf_size_info mips_elf64_size_info =
2652
sizeof (Elf64_External_Ehdr),
2653
sizeof (Elf64_External_Phdr),
2654
sizeof (Elf64_External_Shdr),
2655
sizeof (Elf64_Mips_External_Rel),
2656
sizeof (Elf64_Mips_External_Rela),
2657
sizeof (Elf64_External_Sym),
2658
sizeof (Elf64_External_Dyn),
2659
sizeof (Elf_External_Note),
2660
4, /* hash-table entry size */
2661
3, /* internal relocations per external relocations */
2666
bfd_elf64_write_out_phdrs,
2667
bfd_elf64_write_shdrs_and_ehdr,
2668
mips_elf64_write_relocs,
2669
bfd_elf64_swap_symbol_in,
2670
bfd_elf64_swap_symbol_out,
2671
mips_elf64_slurp_reloc_table,
2672
bfd_elf64_slurp_symbol_table,
2673
bfd_elf64_swap_dyn_in,
2674
bfd_elf64_swap_dyn_out,
2675
mips_elf64_be_swap_reloc_in,
2676
mips_elf64_be_swap_reloc_out,
2677
mips_elf64_be_swap_reloca_in,
2678
mips_elf64_be_swap_reloca_out
2681
#define ELF_ARCH bfd_arch_mips
2682
#define ELF_MACHINE_CODE EM_MIPS
2684
#define ELF_MAXPAGESIZE 0x1000
2686
#define elf_backend_collect true
2687
#define elf_backend_type_change_ok true
2688
#define elf_backend_can_gc_sections true
2689
#define elf_info_to_howto mips_elf64_info_to_howto_rela
2690
#define elf_info_to_howto_rel mips_elf64_info_to_howto_rel
2691
#define elf_backend_object_p mips_elf64_object_p
2692
#define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
2693
#define elf_backend_section_processing _bfd_mips_elf_section_processing
2694
#define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
2695
#define elf_backend_fake_sections _bfd_mips_elf_fake_sections
2696
#define elf_backend_section_from_bfd_section \
2697
_bfd_mips_elf_section_from_bfd_section
2698
#define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook
2699
#define elf_backend_link_output_symbol_hook \
2700
_bfd_mips_elf_link_output_symbol_hook
2701
#define elf_backend_create_dynamic_sections \
2702
_bfd_mips_elf_create_dynamic_sections
2703
#define elf_backend_check_relocs _bfd_mips_elf_check_relocs
2704
#define elf_backend_adjust_dynamic_symbol \
2705
_bfd_mips_elf_adjust_dynamic_symbol
2706
#define elf_backend_always_size_sections \
2707
_bfd_mips_elf_always_size_sections
2708
#define elf_backend_size_dynamic_sections \
2709
_bfd_mips_elf_size_dynamic_sections
2710
#define elf_backend_relocate_section _bfd_mips_elf_relocate_section
2711
#define elf_backend_finish_dynamic_symbol \
2712
_bfd_mips_elf_finish_dynamic_symbol
2713
#define elf_backend_finish_dynamic_sections \
2714
_bfd_mips_elf_finish_dynamic_sections
2715
#define elf_backend_final_write_processing \
2716
_bfd_mips_elf_final_write_processing
2717
#define elf_backend_additional_program_headers \
2718
_bfd_mips_elf_additional_program_headers
2719
#define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
2720
#define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook
2721
#define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
2722
#define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
2723
#define elf_backend_ignore_discarded_relocs \
2724
_bfd_mips_elf_ignore_discarded_relocs
2725
#define elf_backend_mips_irix_compat elf64_mips_irix_compat
2726
#define elf_backend_mips_rtype_to_howto mips_elf64_rtype_to_howto
2727
#define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap
2728
#define elf_backend_size_info mips_elf64_size_info
2730
#define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
2731
#define elf_backend_plt_header_size 0
2733
/* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
2734
work better/work only in RELA, so we default to this. */
2735
#define elf_backend_may_use_rel_p 1
2736
#define elf_backend_may_use_rela_p 1
2737
#define elf_backend_default_use_rela_p 1
2739
/* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit
2740
MIPS-specific function only applies to IRIX5, which had no 64-bit
2742
#define bfd_elf64_find_nearest_line _bfd_mips_elf_find_nearest_line
2743
#define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
2744
#define bfd_elf64_bfd_get_relocated_section_contents \
2745
_bfd_elf_mips_get_relocated_section_contents
2746
#define bfd_elf64_bfd_link_hash_table_create \
2747
_bfd_mips_elf_link_hash_table_create
2748
#define bfd_elf64_bfd_final_link _bfd_mips_elf_final_link
2749
#define bfd_elf64_bfd_merge_private_bfd_data \
2750
_bfd_mips_elf_merge_private_bfd_data
2751
#define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
2752
#define bfd_elf64_bfd_print_private_bfd_data \
2753
_bfd_mips_elf_print_private_bfd_data
2755
#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
2757
/* MIPS ELF64 archive functions. */
2758
#define bfd_elf64_archive_functions
2759
extern boolean bfd_elf64_archive_slurp_armap
2761
extern boolean bfd_elf64_archive_write_armap
2762
PARAMS((bfd *, unsigned int, struct orl *, unsigned int, int));
2763
#define bfd_elf64_archive_slurp_extended_name_table \
2764
_bfd_archive_coff_slurp_extended_name_table
2765
#define bfd_elf64_archive_construct_extended_name_table \
2766
_bfd_archive_coff_construct_extended_name_table
2767
#define bfd_elf64_archive_truncate_arname \
2768
_bfd_archive_coff_truncate_arname
2769
#define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
2770
#define bfd_elf64_archive_openr_next_archived_file \
2771
_bfd_archive_coff_openr_next_archived_file
2772
#define bfd_elf64_archive_get_elt_at_index \
2773
_bfd_archive_coff_get_elt_at_index
2774
#define bfd_elf64_archive_generic_stat_arch_elt \
2775
_bfd_archive_coff_generic_stat_arch_elt
2776
#define bfd_elf64_archive_update_armap_timestamp \
2777
_bfd_archive_coff_update_armap_timestamp
2779
/* The SGI style (n)64 NewABI. */
2780
#define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec
2781
#define TARGET_LITTLE_NAME "elf64-littlemips"
2782
#define TARGET_BIG_SYM bfd_elf64_bigmips_vec
2783
#define TARGET_BIG_NAME "elf64-bigmips"
2785
#include "elf64-target.h"
2787
#define INCLUDED_TARGET_FILE /* More a type of flag. */
2789
/* The SYSV-style 'traditional' (n)64 NewABI. */
2790
#undef TARGET_LITTLE_SYM
2791
#undef TARGET_LITTLE_NAME
2792
#undef TARGET_BIG_SYM
2793
#undef TARGET_BIG_NAME
2795
#define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
2796
#define TARGET_LITTLE_NAME "elf64-tradlittlemips"
2797
#define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
2798
#define TARGET_BIG_NAME "elf64-tradbigmips"
2800
/* Include the target file again for this target. */
2801
#include "elf64-target.h"