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