1179407Sobrien/* MIPS-specific support for 64-bit ELF
2218822Sdim   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3218822Sdim   2007 Free Software Foundation, Inc.
4179407Sobrien   Ian Lance Taylor, Cygnus Support
5179407Sobrien   Linker support added by Mark Mitchell, CodeSourcery, LLC.
6179407Sobrien   <mark@codesourcery.com>
7179407Sobrien
8179407SobrienThis file is part of BFD, the Binary File Descriptor library.
9179407Sobrien
10179407SobrienThis program is free software; you can redistribute it and/or modify
11179407Sobrienit under the terms of the GNU General Public License as published by
12179407Sobrienthe Free Software Foundation; either version 2 of the License, or
13179407Sobrien(at your option) any later version.
14179407Sobrien
15179407SobrienThis program is distributed in the hope that it will be useful,
16179407Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
17179407SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18179407SobrienGNU General Public License for more details.
19179407Sobrien
20179407SobrienYou should have received a copy of the GNU General Public License
21179407Sobrienalong with this program; if not, write to the Free Software
22218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
23179407Sobrien
24179407Sobrien/* This file supports the 64-bit MIPS ELF ABI.
25179407Sobrien
26179407Sobrien   The MIPS 64-bit ELF ABI uses an unusual reloc format.  This file
27179407Sobrien   overrides the usual ELF reloc handling, and handles reading and
28179407Sobrien   writing the relocations here.  */
29179407Sobrien
30179407Sobrien/* TODO: Many things are unsupported, even if there is some code for it
31179407Sobrien .       (which was mostly stolen from elf32-mips.c and slightly adapted).
32179407Sobrien .
33179407Sobrien .   - Relocation handling for REL relocs is wrong in many cases and
34179407Sobrien .     generally untested.
35179407Sobrien .   - Relocation handling for RELA relocs related to GOT support are
36179407Sobrien .     also likely to be wrong.
37179407Sobrien .   - Support for MIPS16 is untested.
38179407Sobrien .   - Combined relocs with RSS_* entries are unsupported.
39179407Sobrien .   - The whole GOT handling for NewABI is missing, some parts of
40179407Sobrien .     the OldABI version is still lying around and should be removed.
41179407Sobrien */
42179407Sobrien
43218822Sdim#include "sysdep.h"
44179407Sobrien#include "bfd.h"
45179407Sobrien#include "libbfd.h"
46179407Sobrien#include "aout/ar.h"
47179407Sobrien#include "bfdlink.h"
48179407Sobrien#include "genlink.h"
49179407Sobrien#include "elf-bfd.h"
50179407Sobrien#include "elfxx-mips.h"
51179407Sobrien#include "elf/mips.h"
52179407Sobrien
53179407Sobrien/* Get the ECOFF swapping routines.  The 64-bit ABI is not supposed to
54179407Sobrien   use ECOFF.  However, we support it anyhow for an easier changeover.  */
55179407Sobrien#include "coff/sym.h"
56179407Sobrien#include "coff/symconst.h"
57179407Sobrien#include "coff/internal.h"
58179407Sobrien#include "coff/ecoff.h"
59179407Sobrien/* The 64 bit versions of the mdebug data structures are in alpha.h.  */
60179407Sobrien#include "coff/alpha.h"
61179407Sobrien#define ECOFF_SIGNED_64
62179407Sobrien#include "ecoffswap.h"
63179407Sobrien
64179407Sobrienstatic void mips_elf64_swap_reloc_in
65179407Sobrien  (bfd *, const Elf64_Mips_External_Rel *, Elf64_Mips_Internal_Rela *);
66179407Sobrienstatic void mips_elf64_swap_reloca_in
67179407Sobrien  (bfd *, const Elf64_Mips_External_Rela *, Elf64_Mips_Internal_Rela *);
68179407Sobrienstatic void mips_elf64_swap_reloc_out
69179407Sobrien  (bfd *, const Elf64_Mips_Internal_Rela *, Elf64_Mips_External_Rel *);
70179407Sobrienstatic void mips_elf64_swap_reloca_out
71179407Sobrien  (bfd *, const Elf64_Mips_Internal_Rela *, Elf64_Mips_External_Rela *);
72179407Sobrienstatic void mips_elf64_be_swap_reloc_in
73179407Sobrien  (bfd *, const bfd_byte *, Elf_Internal_Rela *);
74179407Sobrienstatic void mips_elf64_be_swap_reloc_out
75179407Sobrien  (bfd *, const Elf_Internal_Rela *, bfd_byte *);
76179407Sobrienstatic void mips_elf64_be_swap_reloca_in
77179407Sobrien  (bfd *, const bfd_byte *, Elf_Internal_Rela *);
78179407Sobrienstatic void mips_elf64_be_swap_reloca_out
79179407Sobrien  (bfd *, const Elf_Internal_Rela *, bfd_byte *);
80179407Sobrienstatic reloc_howto_type *bfd_elf64_bfd_reloc_type_lookup
81179407Sobrien  (bfd *, bfd_reloc_code_real_type);
82179407Sobrienstatic reloc_howto_type *mips_elf64_rtype_to_howto
83179407Sobrien  (unsigned int, bfd_boolean);
84179407Sobrienstatic void mips_elf64_info_to_howto_rel
85179407Sobrien  (bfd *, arelent *, Elf_Internal_Rela *);
86179407Sobrienstatic void mips_elf64_info_to_howto_rela
87179407Sobrien  (bfd *, arelent *, Elf_Internal_Rela *);
88179407Sobrienstatic long mips_elf64_get_reloc_upper_bound
89179407Sobrien  (bfd *, asection *);
90179407Sobrienstatic long mips_elf64_canonicalize_reloc
91179407Sobrien  (bfd *, asection *, arelent **, asymbol **);
92179407Sobrienstatic long mips_elf64_get_dynamic_reloc_upper_bound
93179407Sobrien  (bfd *);
94179407Sobrienstatic long mips_elf64_canonicalize_dynamic_reloc
95179407Sobrien  (bfd *, arelent **, asymbol **);
96179407Sobrienstatic bfd_boolean mips_elf64_slurp_one_reloc_table
97179407Sobrien  (bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type, arelent *,
98179407Sobrien   asymbol **, bfd_boolean);
99179407Sobrienstatic bfd_boolean mips_elf64_slurp_reloc_table
100179407Sobrien  (bfd *, asection *, asymbol **, bfd_boolean);
101179407Sobrienstatic void mips_elf64_write_relocs
102179407Sobrien  (bfd *, asection *, void *);
103179407Sobrienstatic void mips_elf64_write_rel
104179407Sobrien  (bfd *, asection *, Elf_Internal_Shdr *, int *, void *);
105179407Sobrienstatic void mips_elf64_write_rela
106179407Sobrien  (bfd *, asection *, Elf_Internal_Shdr *, int *, void *);
107179407Sobrienstatic bfd_reloc_status_type mips_elf64_gprel16_reloc
108179407Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
109179407Sobrienstatic bfd_reloc_status_type mips_elf64_literal_reloc
110179407Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
111179407Sobrienstatic bfd_reloc_status_type mips_elf64_gprel32_reloc
112179407Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
113179407Sobrienstatic bfd_reloc_status_type mips_elf64_shift6_reloc
114179407Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
115179407Sobrienstatic bfd_reloc_status_type mips16_gprel_reloc
116179407Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
117179407Sobrienstatic bfd_boolean mips_elf64_assign_gp
118179407Sobrien  (bfd *, bfd_vma *);
119179407Sobrienstatic bfd_reloc_status_type mips_elf64_final_gp
120179407Sobrien  (bfd *, asymbol *, bfd_boolean, char **, bfd_vma *);
121179407Sobrienstatic bfd_boolean mips_elf64_object_p
122179407Sobrien  (bfd *);
123179407Sobrienstatic irix_compat_t elf64_mips_irix_compat
124179407Sobrien  (bfd *);
125179407Sobrienstatic bfd_boolean elf64_mips_grok_prstatus
126179407Sobrien  (bfd *, Elf_Internal_Note *);
127179407Sobrienstatic bfd_boolean elf64_mips_grok_psinfo
128179407Sobrien  (bfd *, Elf_Internal_Note *);
129179407Sobrien
130179407Sobrienextern const bfd_target bfd_elf64_bigmips_vec;
131179407Sobrienextern const bfd_target bfd_elf64_littlemips_vec;
132179407Sobrien
133179407Sobrien/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
134179407Sobrien   from smaller values.  Start with zero, widen, *then* decrement.  */
135179407Sobrien#define MINUS_ONE	(((bfd_vma)0) - 1)
136179407Sobrien
137179407Sobrien/* The number of local .got entries we reserve.  */
138179407Sobrien#define MIPS_RESERVED_GOTNO (2)
139179407Sobrien
140179407Sobrien/* The relocation table used for SHT_REL sections.  */
141179407Sobrien
142179407Sobrienstatic reloc_howto_type mips_elf64_howto_table_rel[] =
143179407Sobrien{
144179407Sobrien  /* No relocation.  */
145179407Sobrien  HOWTO (R_MIPS_NONE,		/* type */
146179407Sobrien	 0,			/* rightshift */
147179407Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
148179407Sobrien	 0,			/* bitsize */
149179407Sobrien	 FALSE,			/* pc_relative */
150179407Sobrien	 0,			/* bitpos */
151179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
152179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
153179407Sobrien	 "R_MIPS_NONE",		/* name */
154179407Sobrien	 FALSE,			/* partial_inplace */
155179407Sobrien	 0,			/* src_mask */
156179407Sobrien	 0,			/* dst_mask */
157179407Sobrien	 FALSE),		/* pcrel_offset */
158179407Sobrien
159179407Sobrien  /* 16 bit relocation.  */
160179407Sobrien  HOWTO (R_MIPS_16,		/* type */
161179407Sobrien	 0,			/* rightshift */
162179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
163179407Sobrien	 16,			/* bitsize */
164179407Sobrien	 FALSE,			/* pc_relative */
165179407Sobrien	 0,			/* bitpos */
166179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
167179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
168179407Sobrien	 "R_MIPS_16",		/* name */
169179407Sobrien	 TRUE,			/* partial_inplace */
170179407Sobrien	 0x0000ffff,		/* src_mask */
171179407Sobrien	 0x0000ffff,		/* dst_mask */
172179407Sobrien	 FALSE),		/* pcrel_offset */
173179407Sobrien
174179407Sobrien  /* 32 bit relocation.  */
175179407Sobrien  HOWTO (R_MIPS_32,		/* type */
176179407Sobrien	 0,			/* rightshift */
177179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
178179407Sobrien	 32,			/* bitsize */
179179407Sobrien	 FALSE,			/* pc_relative */
180179407Sobrien	 0,			/* bitpos */
181179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
182179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
183179407Sobrien	 "R_MIPS_32",		/* name */
184179407Sobrien	 TRUE,			/* partial_inplace */
185179407Sobrien	 0xffffffff,		/* src_mask */
186179407Sobrien	 0xffffffff,		/* dst_mask */
187179407Sobrien	 FALSE),		/* pcrel_offset */
188179407Sobrien
189179407Sobrien  /* 32 bit symbol relative relocation.  */
190179407Sobrien  HOWTO (R_MIPS_REL32,		/* type */
191179407Sobrien	 0,			/* rightshift */
192179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
193179407Sobrien	 32,			/* bitsize */
194179407Sobrien	 FALSE,			/* pc_relative */
195179407Sobrien	 0,			/* bitpos */
196179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
197179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
198179407Sobrien	 "R_MIPS_REL32",	/* name */
199179407Sobrien	 TRUE,			/* partial_inplace */
200179407Sobrien	 0xffffffff,		/* src_mask */
201179407Sobrien	 0xffffffff,		/* dst_mask */
202179407Sobrien	 FALSE),		/* pcrel_offset */
203179407Sobrien
204179407Sobrien  /* 26 bit jump address.  */
205179407Sobrien  HOWTO (R_MIPS_26,		/* type */
206179407Sobrien	 2,			/* rightshift */
207179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
208179407Sobrien	 26,			/* bitsize */
209179407Sobrien	 FALSE,			/* pc_relative */
210179407Sobrien	 0,			/* bitpos */
211179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
212179407Sobrien				/* This needs complex overflow
213179407Sobrien				   detection, because the upper 36
214179407Sobrien				   bits must match the PC + 4.  */
215179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
216179407Sobrien	 "R_MIPS_26",		/* name */
217179407Sobrien	 TRUE,			/* partial_inplace */
218179407Sobrien	 0x03ffffff,		/* src_mask */
219179407Sobrien	 0x03ffffff,		/* dst_mask */
220179407Sobrien	 FALSE),		/* pcrel_offset */
221179407Sobrien
222179407Sobrien  /* R_MIPS_HI16 and R_MIPS_LO16 are unsupported for NewABI REL.
223179407Sobrien     However, the native IRIX6 tools use them, so we try our best. */
224179407Sobrien
225179407Sobrien  /* High 16 bits of symbol value.  */
226179407Sobrien  HOWTO (R_MIPS_HI16,		/* type */
227179407Sobrien	 16,			/* rightshift */
228179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
229179407Sobrien	 16,			/* bitsize */
230179407Sobrien	 FALSE,			/* pc_relative */
231179407Sobrien	 0,			/* bitpos */
232179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
233179407Sobrien	 _bfd_mips_elf_hi16_reloc, /* special_function */
234179407Sobrien	 "R_MIPS_HI16",		/* name */
235179407Sobrien	 TRUE,			/* partial_inplace */
236179407Sobrien	 0x0000ffff,		/* src_mask */
237179407Sobrien	 0x0000ffff,		/* dst_mask */
238179407Sobrien	 FALSE),		/* pcrel_offset */
239179407Sobrien
240179407Sobrien  /* Low 16 bits of symbol value.  */
241179407Sobrien  HOWTO (R_MIPS_LO16,		/* type */
242179407Sobrien	 0,			/* rightshift */
243179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
244179407Sobrien	 16,			/* bitsize */
245179407Sobrien	 FALSE,			/* pc_relative */
246179407Sobrien	 0,			/* bitpos */
247179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
248179407Sobrien	 _bfd_mips_elf_lo16_reloc, /* special_function */
249179407Sobrien	 "R_MIPS_LO16",		/* name */
250179407Sobrien	 TRUE,			/* partial_inplace */
251179407Sobrien	 0x0000ffff,		/* src_mask */
252179407Sobrien	 0x0000ffff,		/* dst_mask */
253179407Sobrien	 FALSE),		/* pcrel_offset */
254179407Sobrien
255179407Sobrien  /* GP relative reference.  */
256179407Sobrien  HOWTO (R_MIPS_GPREL16,	/* type */
257179407Sobrien	 0,			/* rightshift */
258179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
259179407Sobrien	 16,			/* bitsize */
260179407Sobrien	 FALSE,			/* pc_relative */
261179407Sobrien	 0,			/* bitpos */
262179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
263179407Sobrien	 mips_elf64_gprel16_reloc, /* special_function */
264179407Sobrien	 "R_MIPS_GPREL16",	/* name */
265179407Sobrien	 TRUE,			/* partial_inplace */
266179407Sobrien	 0x0000ffff,		/* src_mask */
267179407Sobrien	 0x0000ffff,		/* dst_mask */
268179407Sobrien	 FALSE),		/* pcrel_offset */
269179407Sobrien
270179407Sobrien  /* Reference to literal section.  */
271179407Sobrien  HOWTO (R_MIPS_LITERAL,	/* type */
272179407Sobrien	 0,			/* rightshift */
273179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
274179407Sobrien	 16,			/* bitsize */
275179407Sobrien	 FALSE,			/* pc_relative */
276179407Sobrien	 0,			/* bitpos */
277179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
278179407Sobrien	 mips_elf64_literal_reloc, /* special_function */
279179407Sobrien	 "R_MIPS_LITERAL",	/* name */
280179407Sobrien	 TRUE,			/* partial_inplace */
281179407Sobrien	 0x0000ffff,		/* src_mask */
282179407Sobrien	 0x0000ffff,		/* dst_mask */
283179407Sobrien	 FALSE),		/* pcrel_offset */
284179407Sobrien
285179407Sobrien  /* Reference to global offset table.  */
286179407Sobrien  HOWTO (R_MIPS_GOT16,		/* type */
287179407Sobrien	 0,			/* rightshift */
288179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
289179407Sobrien	 16,			/* bitsize */
290179407Sobrien	 FALSE,			/* pc_relative */
291179407Sobrien	 0,			/* bitpos */
292179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
293179407Sobrien	 _bfd_mips_elf_got16_reloc, /* special_function */
294179407Sobrien	 "R_MIPS_GOT16",	/* name */
295179407Sobrien	 TRUE,			/* partial_inplace */
296179407Sobrien	 0x0000ffff,		/* src_mask */
297179407Sobrien	 0x0000ffff,		/* dst_mask */
298179407Sobrien	 FALSE),		/* pcrel_offset */
299179407Sobrien
300218822Sdim  /* 16 bit PC relative reference.  Note that the ABI document has a typo
301218822Sdim     and claims R_MIPS_PC16 to be not rightshifted, rendering it useless.
302218822Sdim     We do the right thing here.  */
303179407Sobrien  HOWTO (R_MIPS_PC16,		/* type */
304218822Sdim	 2,			/* rightshift */
305179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
306179407Sobrien	 16,			/* bitsize */
307179407Sobrien	 TRUE,			/* pc_relative */
308179407Sobrien	 0,			/* bitpos */
309179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
310179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
311179407Sobrien	 "R_MIPS_PC16",		/* name */
312179407Sobrien	 TRUE,			/* partial_inplace */
313179407Sobrien	 0x0000ffff,		/* src_mask */
314179407Sobrien	 0x0000ffff,		/* dst_mask */
315179407Sobrien	 TRUE),			/* pcrel_offset */
316179407Sobrien
317179407Sobrien  /* 16 bit call through global offset table.  */
318179407Sobrien  HOWTO (R_MIPS_CALL16,		/* type */
319179407Sobrien	 0,			/* rightshift */
320179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
321179407Sobrien	 16,			/* bitsize */
322179407Sobrien	 FALSE,			/* pc_relative */
323179407Sobrien	 0,			/* bitpos */
324179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
325179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
326179407Sobrien	 "R_MIPS_CALL16",	/* name */
327179407Sobrien	 TRUE,			/* partial_inplace */
328179407Sobrien	 0x0000ffff,		/* src_mask */
329179407Sobrien	 0x0000ffff,		/* dst_mask */
330179407Sobrien	 FALSE),		/* pcrel_offset */
331179407Sobrien
332179407Sobrien  /* 32 bit GP relative reference.  */
333179407Sobrien  HOWTO (R_MIPS_GPREL32,	/* type */
334179407Sobrien	 0,			/* rightshift */
335179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
336179407Sobrien	 32,			/* bitsize */
337179407Sobrien	 FALSE,			/* pc_relative */
338179407Sobrien	 0,			/* bitpos */
339179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
340179407Sobrien	 mips_elf64_gprel32_reloc, /* special_function */
341179407Sobrien	 "R_MIPS_GPREL32",	/* name */
342179407Sobrien	 TRUE,			/* partial_inplace */
343179407Sobrien	 0xffffffff,		/* src_mask */
344179407Sobrien	 0xffffffff,		/* dst_mask */
345179407Sobrien	 FALSE),		/* pcrel_offset */
346179407Sobrien
347179407Sobrien  EMPTY_HOWTO (13),
348179407Sobrien  EMPTY_HOWTO (14),
349179407Sobrien  EMPTY_HOWTO (15),
350179407Sobrien
351179407Sobrien  /* A 5 bit shift field.  */
352179407Sobrien  HOWTO (R_MIPS_SHIFT5,		/* type */
353179407Sobrien	 0,			/* rightshift */
354179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
355179407Sobrien	 5,			/* bitsize */
356179407Sobrien	 FALSE,			/* pc_relative */
357179407Sobrien	 6,			/* bitpos */
358179407Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
359179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
360179407Sobrien	 "R_MIPS_SHIFT5",	/* name */
361179407Sobrien	 TRUE,			/* partial_inplace */
362179407Sobrien	 0x000007c0,		/* src_mask */
363179407Sobrien	 0x000007c0,		/* dst_mask */
364179407Sobrien	 FALSE),		/* pcrel_offset */
365179407Sobrien
366179407Sobrien  /* A 6 bit shift field.  */
367179407Sobrien  HOWTO (R_MIPS_SHIFT6,		/* type */
368179407Sobrien	 0,			/* rightshift */
369179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
370179407Sobrien	 6,			/* bitsize */
371179407Sobrien	 FALSE,			/* pc_relative */
372179407Sobrien	 6,			/* bitpos */
373179407Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
374179407Sobrien	 mips_elf64_shift6_reloc, /* special_function */
375179407Sobrien	 "R_MIPS_SHIFT6",	/* name */
376179407Sobrien	 TRUE,			/* partial_inplace */
377179407Sobrien	 0x000007c4,		/* src_mask */
378179407Sobrien	 0x000007c4,		/* dst_mask */
379179407Sobrien	 FALSE),		/* pcrel_offset */
380179407Sobrien
381179407Sobrien  /* 64 bit relocation.  */
382179407Sobrien  HOWTO (R_MIPS_64,		/* type */
383179407Sobrien	 0,			/* rightshift */
384179407Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
385179407Sobrien	 64,			/* bitsize */
386179407Sobrien	 FALSE,			/* pc_relative */
387179407Sobrien	 0,			/* bitpos */
388179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
389179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
390179407Sobrien	 "R_MIPS_64",		/* name */
391179407Sobrien	 TRUE,			/* partial_inplace */
392179407Sobrien	 MINUS_ONE,		/* src_mask */
393179407Sobrien	 MINUS_ONE,		/* dst_mask */
394179407Sobrien	 FALSE),		/* pcrel_offset */
395179407Sobrien
396179407Sobrien  /* Displacement in the global offset table.  */
397179407Sobrien  HOWTO (R_MIPS_GOT_DISP,	/* type */
398179407Sobrien	 0,			/* rightshift */
399179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
400179407Sobrien	 16,			/* bitsize */
401179407Sobrien	 FALSE,			/* pc_relative */
402179407Sobrien	 0,			/* bitpos */
403179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
404179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
405179407Sobrien	 "R_MIPS_GOT_DISP",	/* name */
406179407Sobrien	 TRUE,			/* partial_inplace */
407179407Sobrien	 0x0000ffff,		/* src_mask */
408179407Sobrien	 0x0000ffff,		/* dst_mask */
409179407Sobrien	 FALSE),		/* pcrel_offset */
410179407Sobrien
411179407Sobrien  /* Displacement to page pointer in the global offset table.  */
412179407Sobrien  HOWTO (R_MIPS_GOT_PAGE,	/* type */
413179407Sobrien	 0,			/* rightshift */
414179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
415179407Sobrien	 16,			/* bitsize */
416179407Sobrien	 FALSE,			/* pc_relative */
417179407Sobrien	 0,			/* bitpos */
418179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
419179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
420179407Sobrien	 "R_MIPS_GOT_PAGE",	/* name */
421179407Sobrien	 TRUE,			/* partial_inplace */
422179407Sobrien	 0x0000ffff,		/* src_mask */
423179407Sobrien	 0x0000ffff,		/* dst_mask */
424179407Sobrien	 FALSE),		/* pcrel_offset */
425179407Sobrien
426179407Sobrien  /* Offset from page pointer in the global offset table.  */
427179407Sobrien  HOWTO (R_MIPS_GOT_OFST,	/* type */
428179407Sobrien	 0,			/* rightshift */
429179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
430179407Sobrien	 16,			/* bitsize */
431179407Sobrien	 FALSE,			/* pc_relative */
432179407Sobrien	 0,			/* bitpos */
433179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
434179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
435179407Sobrien	 "R_MIPS_GOT_OFST",	/* name */
436179407Sobrien	 TRUE,			/* partial_inplace */
437179407Sobrien	 0x0000ffff,		/* src_mask */
438179407Sobrien	 0x0000ffff,		/* dst_mask */
439179407Sobrien	 FALSE),		/* pcrel_offset */
440179407Sobrien
441179407Sobrien  /* High 16 bits of displacement in global offset table.  */
442179407Sobrien  HOWTO (R_MIPS_GOT_HI16,	/* type */
443179407Sobrien	 0,			/* rightshift */
444179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
445179407Sobrien	 16,			/* bitsize */
446179407Sobrien	 FALSE,			/* pc_relative */
447179407Sobrien	 0,			/* bitpos */
448179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
449179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
450179407Sobrien	 "R_MIPS_GOT_HI16",	/* name */
451179407Sobrien	 TRUE,			/* partial_inplace */
452179407Sobrien	 0x0000ffff,		/* src_mask */
453179407Sobrien	 0x0000ffff,		/* dst_mask */
454179407Sobrien	 FALSE),		/* pcrel_offset */
455179407Sobrien
456179407Sobrien  /* Low 16 bits of displacement in global offset table.  */
457179407Sobrien  HOWTO (R_MIPS_GOT_LO16,	/* type */
458179407Sobrien	 0,			/* rightshift */
459179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
460179407Sobrien	 16,			/* bitsize */
461179407Sobrien	 FALSE,			/* pc_relative */
462179407Sobrien	 0,			/* bitpos */
463179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
464179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
465179407Sobrien	 "R_MIPS_GOT_LO16",	/* name */
466179407Sobrien	 TRUE,			/* partial_inplace */
467179407Sobrien	 0x0000ffff,		/* src_mask */
468179407Sobrien	 0x0000ffff,		/* dst_mask */
469179407Sobrien	 FALSE),		/* pcrel_offset */
470179407Sobrien
471179407Sobrien  /* 64 bit subtraction.  */
472179407Sobrien  HOWTO (R_MIPS_SUB,		/* type */
473179407Sobrien	 0,			/* rightshift */
474179407Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
475179407Sobrien	 64,			/* bitsize */
476179407Sobrien	 FALSE,			/* pc_relative */
477179407Sobrien	 0,			/* bitpos */
478179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
479179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
480179407Sobrien	 "R_MIPS_SUB",		/* name */
481179407Sobrien	 TRUE,			/* partial_inplace */
482179407Sobrien	 MINUS_ONE,		/* src_mask */
483179407Sobrien	 MINUS_ONE,		/* dst_mask */
484179407Sobrien	 FALSE),		/* pcrel_offset */
485179407Sobrien
486179407Sobrien  /* Insert the addend as an instruction.  */
487179407Sobrien  /* FIXME: Not handled correctly.  */
488179407Sobrien  HOWTO (R_MIPS_INSERT_A,	/* type */
489179407Sobrien	 0,			/* rightshift */
490179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
491179407Sobrien	 32,			/* bitsize */
492179407Sobrien	 FALSE,			/* pc_relative */
493179407Sobrien	 0,			/* bitpos */
494179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
495179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
496179407Sobrien	 "R_MIPS_INSERT_A",	/* name */
497179407Sobrien	 TRUE,			/* partial_inplace */
498179407Sobrien	 0xffffffff,		/* src_mask */
499179407Sobrien	 0xffffffff,		/* dst_mask */
500179407Sobrien	 FALSE),		/* pcrel_offset */
501179407Sobrien
502179407Sobrien  /* Insert the addend as an instruction, and change all relocations
503179407Sobrien     to refer to the old instruction at the address.  */
504179407Sobrien  /* FIXME: Not handled correctly.  */
505179407Sobrien  HOWTO (R_MIPS_INSERT_B,	/* type */
506179407Sobrien	 0,			/* rightshift */
507179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
508179407Sobrien	 32,			/* bitsize */
509179407Sobrien	 FALSE,			/* pc_relative */
510179407Sobrien	 0,			/* bitpos */
511179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
512179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
513179407Sobrien	 "R_MIPS_INSERT_B",	/* name */
514179407Sobrien	 TRUE,			/* partial_inplace */
515179407Sobrien	 0xffffffff,		/* src_mask */
516179407Sobrien	 0xffffffff,		/* dst_mask */
517179407Sobrien	 FALSE),		/* pcrel_offset */
518179407Sobrien
519179407Sobrien  /* Delete a 32 bit instruction.  */
520179407Sobrien  /* FIXME: Not handled correctly.  */
521179407Sobrien  HOWTO (R_MIPS_DELETE,		/* type */
522179407Sobrien	 0,			/* rightshift */
523179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
524179407Sobrien	 32,			/* bitsize */
525179407Sobrien	 FALSE,			/* pc_relative */
526179407Sobrien	 0,			/* bitpos */
527179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
528179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
529179407Sobrien	 "R_MIPS_DELETE",	/* name */
530179407Sobrien	 TRUE,			/* partial_inplace */
531179407Sobrien	 0xffffffff,		/* src_mask */
532179407Sobrien	 0xffffffff,		/* dst_mask */
533179407Sobrien	 FALSE),		/* pcrel_offset */
534179407Sobrien
535179407Sobrien  /* The MIPS ELF64 ABI Draft wants us to support these for REL relocations.
536179407Sobrien     We don't, because
537179407Sobrien       a) It means building the addend from a R_MIPS_HIGHEST/R_MIPS_HIGHER/
538179407Sobrien	  R_MIPS_HI16/R_MIPS_LO16 sequence with varying ordering, using
539179407Sobrien	  fallable heuristics.
540179407Sobrien       b) No other NewABI toolchain actually emits such relocations.  */
541179407Sobrien  EMPTY_HOWTO (R_MIPS_HIGHER),
542179407Sobrien  EMPTY_HOWTO (R_MIPS_HIGHEST),
543179407Sobrien
544179407Sobrien  /* High 16 bits of displacement in global offset table.  */
545179407Sobrien  HOWTO (R_MIPS_CALL_HI16,	/* type */
546179407Sobrien	 0,			/* rightshift */
547179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
548179407Sobrien	 16,			/* bitsize */
549179407Sobrien	 FALSE,			/* pc_relative */
550179407Sobrien	 0,			/* bitpos */
551179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
552179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
553179407Sobrien	 "R_MIPS_CALL_HI16",	/* name */
554179407Sobrien	 TRUE,			/* partial_inplace */
555179407Sobrien	 0x0000ffff,		/* src_mask */
556179407Sobrien	 0x0000ffff,		/* dst_mask */
557179407Sobrien	 FALSE),		/* pcrel_offset */
558179407Sobrien
559179407Sobrien  /* Low 16 bits of displacement in global offset table.  */
560179407Sobrien  HOWTO (R_MIPS_CALL_LO16,	/* type */
561179407Sobrien	 0,			/* rightshift */
562179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
563179407Sobrien	 16,			/* bitsize */
564179407Sobrien	 FALSE,			/* pc_relative */
565179407Sobrien	 0,			/* bitpos */
566179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
567179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
568179407Sobrien	 "R_MIPS_CALL_LO16",	/* name */
569179407Sobrien	 TRUE,			/* partial_inplace */
570179407Sobrien	 0x0000ffff,		/* src_mask */
571179407Sobrien	 0x0000ffff,		/* dst_mask */
572179407Sobrien	 FALSE),		/* pcrel_offset */
573179407Sobrien
574179407Sobrien  /* Section displacement, used by an associated event location section.  */
575179407Sobrien  HOWTO (R_MIPS_SCN_DISP,	/* type */
576179407Sobrien	 0,			/* rightshift */
577179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
578179407Sobrien	 32,			/* bitsize */
579179407Sobrien	 FALSE,			/* pc_relative */
580179407Sobrien	 0,			/* bitpos */
581179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
582179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
583179407Sobrien	 "R_MIPS_SCN_DISP",	/* name */
584179407Sobrien	 TRUE,			/* partial_inplace */
585179407Sobrien	 0xffffffff,		/* src_mask */
586179407Sobrien	 0xffffffff,		/* dst_mask */
587179407Sobrien	 FALSE),		/* pcrel_offset */
588179407Sobrien
589179407Sobrien  HOWTO (R_MIPS_REL16,		/* type */
590179407Sobrien	 0,			/* rightshift */
591179407Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
592179407Sobrien	 16,			/* bitsize */
593179407Sobrien	 FALSE,			/* pc_relative */
594179407Sobrien	 0,			/* bitpos */
595179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
596179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
597179407Sobrien	 "R_MIPS_REL16",	/* name */
598179407Sobrien	 TRUE,			/* partial_inplace */
599179407Sobrien	 0xffff,		/* src_mask */
600179407Sobrien	 0xffff,		/* dst_mask */
601179407Sobrien	 FALSE),		/* pcrel_offset */
602179407Sobrien
603179407Sobrien  /* These two are obsolete.  */
604179407Sobrien  EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
605179407Sobrien  EMPTY_HOWTO (R_MIPS_PJUMP),
606179407Sobrien
607179407Sobrien  /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
608179407Sobrien     It must be used for multigot GOT's (and only there).  */
609179407Sobrien  HOWTO (R_MIPS_RELGOT,		/* type */
610179407Sobrien	 0,			/* rightshift */
611179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
612179407Sobrien	 32,			/* bitsize */
613179407Sobrien	 FALSE,			/* pc_relative */
614179407Sobrien	 0,			/* bitpos */
615179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
616179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
617179407Sobrien	 "R_MIPS_RELGOT",	/* name */
618179407Sobrien	 TRUE,			/* partial_inplace */
619179407Sobrien	 0xffffffff,		/* src_mask */
620179407Sobrien	 0xffffffff,		/* dst_mask */
621179407Sobrien	 FALSE),		/* pcrel_offset */
622179407Sobrien
623179407Sobrien  /* Protected jump conversion.  This is an optimization hint.  No
624179407Sobrien     relocation is required for correctness.  */
625218822Sdim  HOWTO (R_MIPS_JALR,		/* type */
626179407Sobrien	 0,			/* rightshift */
627179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
628179407Sobrien	 32,			/* bitsize */
629179407Sobrien	 FALSE,			/* pc_relative */
630179407Sobrien	 0,			/* bitpos */
631179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
632179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
633218822Sdim	 "R_MIPS_JALR",		/* name */
634179407Sobrien	 FALSE,			/* partial_inplace */
635179407Sobrien	 0,			/* src_mask */
636179407Sobrien	 0x00000000,		/* dst_mask */
637179407Sobrien	 FALSE),		/* pcrel_offset */
638218822Sdim
639218822Sdim  /* TLS relocations.  */
640218822Sdim  EMPTY_HOWTO (R_MIPS_TLS_DTPMOD32),
641218822Sdim  EMPTY_HOWTO (R_MIPS_TLS_DTPREL32),
642218822Sdim
643218822Sdim  HOWTO (R_MIPS_TLS_DTPMOD64,	/* type */
644218822Sdim	 0,			/* rightshift */
645218822Sdim	 4,			/* size (0 = byte, 1 = short, 2 = long) */
646218822Sdim	 64,			/* bitsize */
647218822Sdim	 FALSE,			/* pc_relative */
648218822Sdim	 0,			/* bitpos */
649218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
650218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
651218822Sdim	 "R_MIPS_TLS_DTPMOD64",	/* name */
652218822Sdim	 TRUE,			/* partial_inplace */
653218822Sdim	 MINUS_ONE,		/* src_mask */
654218822Sdim	 MINUS_ONE,		/* dst_mask */
655218822Sdim	 FALSE),		/* pcrel_offset */
656218822Sdim
657218822Sdim  HOWTO (R_MIPS_TLS_DTPREL64,	/* type */
658218822Sdim	 0,			/* rightshift */
659218822Sdim	 4,			/* size (0 = byte, 1 = short, 2 = long) */
660218822Sdim	 64,			/* bitsize */
661218822Sdim	 FALSE,			/* pc_relative */
662218822Sdim	 0,			/* bitpos */
663218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
664218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
665218822Sdim	 "R_MIPS_TLS_DTPREL64",	/* name */
666218822Sdim	 TRUE,			/* partial_inplace */
667218822Sdim	 MINUS_ONE,		/* src_mask */
668218822Sdim	 MINUS_ONE,		/* dst_mask */
669218822Sdim	 FALSE),		/* pcrel_offset */
670218822Sdim
671218822Sdim  /* TLS general dynamic variable reference.  */
672218822Sdim  HOWTO (R_MIPS_TLS_GD,		/* type */
673218822Sdim	 0,			/* rightshift */
674218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
675218822Sdim	 16,			/* bitsize */
676218822Sdim	 FALSE,			/* pc_relative */
677218822Sdim	 0,			/* bitpos */
678218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
679218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
680218822Sdim	 "R_MIPS_TLS_GD",	/* name */
681218822Sdim	 TRUE,			/* partial_inplace */
682218822Sdim	 0x0000ffff,		/* src_mask */
683218822Sdim	 0x0000ffff,		/* dst_mask */
684218822Sdim	 FALSE),		/* pcrel_offset */
685218822Sdim
686218822Sdim  /* TLS local dynamic variable reference.  */
687218822Sdim  HOWTO (R_MIPS_TLS_LDM,	/* type */
688218822Sdim	 0,			/* rightshift */
689218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
690218822Sdim	 16,			/* bitsize */
691218822Sdim	 FALSE,			/* pc_relative */
692218822Sdim	 0,			/* bitpos */
693218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
694218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
695218822Sdim	 "R_MIPS_TLS_LDM",	/* name */
696218822Sdim	 TRUE,			/* partial_inplace */
697218822Sdim	 0x0000ffff,		/* src_mask */
698218822Sdim	 0x0000ffff,		/* dst_mask */
699218822Sdim	 FALSE),		/* pcrel_offset */
700218822Sdim
701218822Sdim  /* TLS local dynamic offset.  */
702218822Sdim  HOWTO (R_MIPS_TLS_DTPREL_HI16,	/* type */
703218822Sdim	 0,			/* rightshift */
704218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
705218822Sdim	 16,			/* bitsize */
706218822Sdim	 FALSE,			/* pc_relative */
707218822Sdim	 0,			/* bitpos */
708218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
709218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
710218822Sdim	 "R_MIPS_TLS_DTPREL_HI16",	/* name */
711218822Sdim	 TRUE,			/* partial_inplace */
712218822Sdim	 0x0000ffff,		/* src_mask */
713218822Sdim	 0x0000ffff,		/* dst_mask */
714218822Sdim	 FALSE),		/* pcrel_offset */
715218822Sdim
716218822Sdim  /* TLS local dynamic offset.  */
717218822Sdim  HOWTO (R_MIPS_TLS_DTPREL_LO16,	/* type */
718218822Sdim	 0,			/* rightshift */
719218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
720218822Sdim	 16,			/* bitsize */
721218822Sdim	 FALSE,			/* pc_relative */
722218822Sdim	 0,			/* bitpos */
723218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
724218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
725218822Sdim	 "R_MIPS_TLS_DTPREL_LO16",	/* name */
726218822Sdim	 TRUE,			/* partial_inplace */
727218822Sdim	 0x0000ffff,		/* src_mask */
728218822Sdim	 0x0000ffff,		/* dst_mask */
729218822Sdim	 FALSE),		/* pcrel_offset */
730218822Sdim
731218822Sdim  /* TLS thread pointer offset.  */
732218822Sdim  HOWTO (R_MIPS_TLS_GOTTPREL,	/* type */
733218822Sdim	 0,			/* rightshift */
734218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
735218822Sdim	 16,			/* bitsize */
736218822Sdim	 FALSE,			/* pc_relative */
737218822Sdim	 0,			/* bitpos */
738218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
739218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
740218822Sdim	 "R_MIPS_TLS_GOTTPREL",	/* name */
741218822Sdim	 TRUE,			/* partial_inplace */
742218822Sdim	 0x0000ffff,		/* src_mask */
743218822Sdim	 0x0000ffff,		/* dst_mask */
744218822Sdim	 FALSE),		/* pcrel_offset */
745218822Sdim
746218822Sdim  /* TLS IE dynamic relocations.  */
747218822Sdim  EMPTY_HOWTO (R_MIPS_TLS_TPREL32),
748218822Sdim
749218822Sdim  HOWTO (R_MIPS_TLS_TPREL64,	/* type */
750218822Sdim	 0,			/* rightshift */
751218822Sdim	 4,			/* size (0 = byte, 1 = short, 2 = long) */
752218822Sdim	 64,			/* bitsize */
753218822Sdim	 FALSE,			/* pc_relative */
754218822Sdim	 0,			/* bitpos */
755218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
756218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
757218822Sdim	 "R_MIPS_TLS_TPREL64",	/* name */
758218822Sdim	 TRUE,			/* partial_inplace */
759218822Sdim	 MINUS_ONE,		/* src_mask */
760218822Sdim	 MINUS_ONE,		/* dst_mask */
761218822Sdim	 FALSE),		/* pcrel_offset */
762218822Sdim
763218822Sdim  /* TLS thread pointer offset.  */
764218822Sdim  HOWTO (R_MIPS_TLS_TPREL_HI16,	/* type */
765218822Sdim	 0,			/* rightshift */
766218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
767218822Sdim	 16,			/* bitsize */
768218822Sdim	 FALSE,			/* pc_relative */
769218822Sdim	 0,			/* bitpos */
770218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
771218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
772218822Sdim	 "R_MIPS_TLS_TPREL_HI16", /* name */
773218822Sdim	 TRUE,			/* partial_inplace */
774218822Sdim	 0x0000ffff,		/* src_mask */
775218822Sdim	 0x0000ffff,		/* dst_mask */
776218822Sdim	 FALSE),		/* pcrel_offset */
777218822Sdim
778218822Sdim  /* TLS thread pointer offset.  */
779218822Sdim  HOWTO (R_MIPS_TLS_TPREL_LO16,	/* type */
780218822Sdim	 0,			/* rightshift */
781218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
782218822Sdim	 16,			/* bitsize */
783218822Sdim	 FALSE,			/* pc_relative */
784218822Sdim	 0,			/* bitpos */
785218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
786218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
787218822Sdim	 "R_MIPS_TLS_TPREL_LO16", /* name */
788218822Sdim	 TRUE,			/* partial_inplace */
789218822Sdim	 0x0000ffff,		/* src_mask */
790218822Sdim	 0x0000ffff,		/* dst_mask */
791218822Sdim	 FALSE),		/* pcrel_offset */
792218822Sdim
793218822Sdim  /* 32 bit relocation with no addend.  */
794218822Sdim  HOWTO (R_MIPS_GLOB_DAT,	/* type */
795218822Sdim	 0,			/* rightshift */
796218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
797218822Sdim	 32,			/* bitsize */
798218822Sdim	 FALSE,			/* pc_relative */
799218822Sdim	 0,			/* bitpos */
800218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
801218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
802218822Sdim	 "R_MIPS_GLOB_DAT",	/* name */
803218822Sdim	 FALSE,			/* partial_inplace */
804218822Sdim	 0x0,			/* src_mask */
805218822Sdim	 0xffffffff,		/* dst_mask */
806218822Sdim	 FALSE),		/* pcrel_offset */
807179407Sobrien};
808179407Sobrien
809179407Sobrien/* The relocation table used for SHT_RELA sections.  */
810179407Sobrien
811179407Sobrienstatic reloc_howto_type mips_elf64_howto_table_rela[] =
812179407Sobrien{
813179407Sobrien  /* No relocation.  */
814179407Sobrien  HOWTO (R_MIPS_NONE,		/* type */
815179407Sobrien	 0,			/* rightshift */
816179407Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
817179407Sobrien	 0,			/* bitsize */
818179407Sobrien	 FALSE,			/* pc_relative */
819179407Sobrien	 0,			/* bitpos */
820179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
821179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
822179407Sobrien	 "R_MIPS_NONE",		/* name */
823179407Sobrien	 FALSE,			/* partial_inplace */
824179407Sobrien	 0,			/* src_mask */
825179407Sobrien	 0,			/* dst_mask */
826179407Sobrien	 FALSE),		/* pcrel_offset */
827179407Sobrien
828179407Sobrien  /* 16 bit relocation.  */
829179407Sobrien  HOWTO (R_MIPS_16,		/* type */
830179407Sobrien	 0,			/* rightshift */
831179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
832179407Sobrien	 16,			/* bitsize */
833179407Sobrien	 FALSE,			/* pc_relative */
834179407Sobrien	 0,			/* bitpos */
835179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
836179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
837179407Sobrien	 "R_MIPS_16",		/* name */
838179407Sobrien	 FALSE,			/* partial_inplace */
839179407Sobrien	 0,			/* src_mask */
840179407Sobrien	 0x0000ffff,		/* dst_mask */
841179407Sobrien	 FALSE),		/* pcrel_offset */
842179407Sobrien
843179407Sobrien  /* 32 bit relocation.  */
844179407Sobrien  HOWTO (R_MIPS_32,		/* type */
845179407Sobrien	 0,			/* rightshift */
846179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
847179407Sobrien	 32,			/* bitsize */
848179407Sobrien	 FALSE,			/* pc_relative */
849179407Sobrien	 0,			/* bitpos */
850179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
851179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
852179407Sobrien	 "R_MIPS_32",		/* name */
853179407Sobrien	 FALSE,			/* partial_inplace */
854179407Sobrien	 0,			/* src_mask */
855179407Sobrien	 0xffffffff,		/* dst_mask */
856179407Sobrien	 FALSE),		/* pcrel_offset */
857179407Sobrien
858179407Sobrien  /* 32 bit symbol relative relocation.  */
859179407Sobrien  HOWTO (R_MIPS_REL32,		/* type */
860179407Sobrien	 0,			/* rightshift */
861179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
862179407Sobrien	 32,			/* bitsize */
863179407Sobrien	 FALSE,			/* pc_relative */
864179407Sobrien	 0,			/* bitpos */
865179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
866179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
867179407Sobrien	 "R_MIPS_REL32",	/* name */
868179407Sobrien	 FALSE,			/* partial_inplace */
869179407Sobrien	 0,			/* src_mask */
870179407Sobrien	 0xffffffff,		/* dst_mask */
871179407Sobrien	 FALSE),		/* pcrel_offset */
872179407Sobrien
873179407Sobrien  /* 26 bit jump address.  */
874179407Sobrien  HOWTO (R_MIPS_26,		/* type */
875179407Sobrien	 2,			/* rightshift */
876179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
877179407Sobrien	 26,			/* bitsize */
878179407Sobrien	 FALSE,			/* pc_relative */
879179407Sobrien	 0,			/* bitpos */
880179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
881179407Sobrien				/* This needs complex overflow
882179407Sobrien				   detection, because the upper 36
883179407Sobrien				   bits must match the PC + 4.  */
884179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
885179407Sobrien	 "R_MIPS_26",		/* name */
886179407Sobrien	 FALSE,			/* partial_inplace */
887179407Sobrien	 0,			/* src_mask */
888179407Sobrien	 0x03ffffff,		/* dst_mask */
889179407Sobrien	 FALSE),		/* pcrel_offset */
890179407Sobrien
891179407Sobrien  /* High 16 bits of symbol value.  */
892179407Sobrien  HOWTO (R_MIPS_HI16,		/* type */
893179407Sobrien	 0,			/* rightshift */
894179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
895179407Sobrien	 16,			/* bitsize */
896179407Sobrien	 FALSE,			/* pc_relative */
897179407Sobrien	 0,			/* bitpos */
898179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
899179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
900179407Sobrien	 "R_MIPS_HI16",		/* name */
901179407Sobrien	 FALSE,			/* partial_inplace */
902179407Sobrien	 0,			/* src_mask */
903179407Sobrien	 0x0000ffff,		/* dst_mask */
904179407Sobrien	 FALSE),		/* pcrel_offset */
905179407Sobrien
906179407Sobrien  /* Low 16 bits of symbol value.  */
907179407Sobrien  HOWTO (R_MIPS_LO16,		/* type */
908179407Sobrien	 0,			/* rightshift */
909179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
910179407Sobrien	 16,			/* bitsize */
911179407Sobrien	 FALSE,			/* pc_relative */
912179407Sobrien	 0,			/* bitpos */
913179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
914179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
915179407Sobrien	 "R_MIPS_LO16",		/* name */
916179407Sobrien	 FALSE,			/* partial_inplace */
917179407Sobrien	 0,			/* src_mask */
918179407Sobrien	 0x0000ffff,		/* dst_mask */
919179407Sobrien	 FALSE),		/* pcrel_offset */
920179407Sobrien
921179407Sobrien  /* GP relative reference.  */
922179407Sobrien  HOWTO (R_MIPS_GPREL16,	/* type */
923179407Sobrien	 0,			/* rightshift */
924179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
925179407Sobrien	 16,			/* bitsize */
926179407Sobrien	 FALSE,			/* pc_relative */
927179407Sobrien	 0,			/* bitpos */
928179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
929179407Sobrien	 mips_elf64_gprel16_reloc, /* special_function */
930179407Sobrien	 "R_MIPS_GPREL16",	/* name */
931179407Sobrien	 FALSE,			/* partial_inplace */
932179407Sobrien	 0,			/* src_mask */
933179407Sobrien	 0x0000ffff,		/* dst_mask */
934179407Sobrien	 FALSE),		/* pcrel_offset */
935179407Sobrien
936179407Sobrien  /* Reference to literal section.  */
937179407Sobrien  HOWTO (R_MIPS_LITERAL,	/* type */
938179407Sobrien	 0,			/* rightshift */
939179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
940179407Sobrien	 16,			/* bitsize */
941179407Sobrien	 FALSE,			/* pc_relative */
942179407Sobrien	 0,			/* bitpos */
943179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
944179407Sobrien	 mips_elf64_literal_reloc, /* special_function */
945179407Sobrien	 "R_MIPS_LITERAL",	/* name */
946179407Sobrien	 FALSE,			/* partial_inplace */
947179407Sobrien	 0,			/* src_mask */
948179407Sobrien	 0x0000ffff,		/* dst_mask */
949179407Sobrien	 FALSE),		/* pcrel_offset */
950179407Sobrien
951179407Sobrien  /* Reference to global offset table.  */
952179407Sobrien  HOWTO (R_MIPS_GOT16,		/* type */
953179407Sobrien	 0,			/* rightshift */
954179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
955179407Sobrien	 16,			/* bitsize */
956179407Sobrien	 FALSE,			/* pc_relative */
957179407Sobrien	 0,			/* bitpos */
958179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
959179407Sobrien	 _bfd_mips_elf_generic_reloc, /* special_function */
960179407Sobrien	 "R_MIPS_GOT16",	/* name */
961179407Sobrien	 FALSE,			/* partial_inplace */
962179407Sobrien	 0,			/* src_mask */
963179407Sobrien	 0x0000ffff,		/* dst_mask */
964179407Sobrien	 FALSE),		/* pcrel_offset */
965179407Sobrien
966218822Sdim  /* 16 bit PC relative reference.  Note that the ABI document has a typo
967218822Sdim     and claims R_MIPS_PC16 to be not rightshifted, rendering it useless.
968218822Sdim     We do the right thing here.  */
969179407Sobrien  HOWTO (R_MIPS_PC16,		/* type */
970218822Sdim	 2,			/* rightshift */
971179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
972179407Sobrien	 16,			/* bitsize */
973179407Sobrien	 TRUE,			/* pc_relative */
974179407Sobrien	 0,			/* bitpos */
975179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
976179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
977179407Sobrien	 "R_MIPS_PC16",		/* name */
978179407Sobrien	 FALSE,			/* partial_inplace */
979179407Sobrien	 0,			/* src_mask */
980179407Sobrien	 0x0000ffff,		/* dst_mask */
981179407Sobrien	 TRUE),			/* pcrel_offset */
982179407Sobrien
983179407Sobrien  /* 16 bit call through global offset table.  */
984179407Sobrien  HOWTO (R_MIPS_CALL16,		/* type */
985179407Sobrien	 0,			/* rightshift */
986179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
987179407Sobrien	 16,			/* bitsize */
988179407Sobrien	 FALSE,			/* pc_relative */
989179407Sobrien	 0,			/* bitpos */
990179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
991179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
992179407Sobrien	 "R_MIPS_CALL16",	/* name */
993179407Sobrien	 FALSE,			/* partial_inplace */
994179407Sobrien	 0,			/* src_mask */
995179407Sobrien	 0x0000ffff,		/* dst_mask */
996179407Sobrien	 FALSE),		/* pcrel_offset */
997179407Sobrien
998179407Sobrien  /* 32 bit GP relative reference.  */
999179407Sobrien  HOWTO (R_MIPS_GPREL32,	/* type */
1000179407Sobrien	 0,			/* rightshift */
1001179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1002179407Sobrien	 32,			/* bitsize */
1003179407Sobrien	 FALSE,			/* pc_relative */
1004179407Sobrien	 0,			/* bitpos */
1005179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1006179407Sobrien	 mips_elf64_gprel32_reloc, /* special_function */
1007179407Sobrien	 "R_MIPS_GPREL32",	/* name */
1008179407Sobrien	 FALSE,			/* partial_inplace */
1009179407Sobrien	 0,			/* src_mask */
1010179407Sobrien	 0xffffffff,		/* dst_mask */
1011179407Sobrien	 FALSE),		/* pcrel_offset */
1012179407Sobrien
1013179407Sobrien  EMPTY_HOWTO (13),
1014179407Sobrien  EMPTY_HOWTO (14),
1015179407Sobrien  EMPTY_HOWTO (15),
1016179407Sobrien
1017179407Sobrien  /* A 5 bit shift field.  */
1018179407Sobrien  HOWTO (R_MIPS_SHIFT5,		/* type */
1019179407Sobrien	 0,			/* rightshift */
1020179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1021179407Sobrien	 5,			/* bitsize */
1022179407Sobrien	 FALSE,			/* pc_relative */
1023179407Sobrien	 6,			/* bitpos */
1024179407Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
1025179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1026179407Sobrien	 "R_MIPS_SHIFT5",	/* name */
1027179407Sobrien	 FALSE,			/* partial_inplace */
1028179407Sobrien	 0,			/* src_mask */
1029179407Sobrien	 0x000007c0,		/* dst_mask */
1030179407Sobrien	 FALSE),		/* pcrel_offset */
1031179407Sobrien
1032179407Sobrien  /* A 6 bit shift field.  */
1033179407Sobrien  HOWTO (R_MIPS_SHIFT6,		/* type */
1034179407Sobrien	 0,			/* rightshift */
1035179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1036179407Sobrien	 6,			/* bitsize */
1037179407Sobrien	 FALSE,			/* pc_relative */
1038179407Sobrien	 6,			/* bitpos */
1039179407Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
1040179407Sobrien	 mips_elf64_shift6_reloc, /* special_function */
1041179407Sobrien	 "R_MIPS_SHIFT6",	/* name */
1042179407Sobrien	 FALSE,			/* partial_inplace */
1043179407Sobrien	 0,			/* src_mask */
1044179407Sobrien	 0x000007c4,		/* dst_mask */
1045179407Sobrien	 FALSE),		/* pcrel_offset */
1046179407Sobrien
1047179407Sobrien  /* 64 bit relocation.  */
1048179407Sobrien  HOWTO (R_MIPS_64,		/* type */
1049179407Sobrien	 0,			/* rightshift */
1050179407Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
1051179407Sobrien	 64,			/* bitsize */
1052179407Sobrien	 FALSE,			/* pc_relative */
1053179407Sobrien	 0,			/* bitpos */
1054179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1055179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1056179407Sobrien	 "R_MIPS_64",		/* name */
1057179407Sobrien	 FALSE,			/* partial_inplace */
1058179407Sobrien	 0,			/* src_mask */
1059179407Sobrien	 MINUS_ONE,		/* dst_mask */
1060179407Sobrien	 FALSE),		/* pcrel_offset */
1061179407Sobrien
1062179407Sobrien  /* Displacement in the global offset table.  */
1063179407Sobrien  HOWTO (R_MIPS_GOT_DISP,	/* type */
1064179407Sobrien	 0,			/* rightshift */
1065179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1066179407Sobrien	 16,			/* bitsize */
1067179407Sobrien	 FALSE,			/* pc_relative */
1068179407Sobrien	 0,			/* bitpos */
1069179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1070179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1071179407Sobrien	 "R_MIPS_GOT_DISP",	/* name */
1072179407Sobrien	 FALSE,			/* partial_inplace */
1073179407Sobrien	 0,			/* src_mask */
1074179407Sobrien	 0x0000ffff,		/* dst_mask */
1075179407Sobrien	 FALSE),		/* pcrel_offset */
1076179407Sobrien
1077179407Sobrien  /* Displacement to page pointer in the global offset table.  */
1078179407Sobrien  HOWTO (R_MIPS_GOT_PAGE,	/* type */
1079179407Sobrien	 0,			/* rightshift */
1080179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1081179407Sobrien	 16,			/* bitsize */
1082179407Sobrien	 FALSE,			/* pc_relative */
1083179407Sobrien	 0,			/* bitpos */
1084179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1085179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1086179407Sobrien	 "R_MIPS_GOT_PAGE",	/* name */
1087179407Sobrien	 FALSE,			/* partial_inplace */
1088179407Sobrien	 0,			/* src_mask */
1089179407Sobrien	 0x0000ffff,		/* dst_mask */
1090179407Sobrien	 FALSE),		/* pcrel_offset */
1091179407Sobrien
1092179407Sobrien  /* Offset from page pointer in the global offset table.  */
1093179407Sobrien  HOWTO (R_MIPS_GOT_OFST,	/* type */
1094179407Sobrien	 0,			/* rightshift */
1095179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1096179407Sobrien	 16,			/* bitsize */
1097179407Sobrien	 FALSE,			/* pc_relative */
1098179407Sobrien	 0,			/* bitpos */
1099179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1100179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1101179407Sobrien	 "R_MIPS_GOT_OFST",	/* name */
1102179407Sobrien	 FALSE,			/* partial_inplace */
1103179407Sobrien	 0,			/* src_mask */
1104179407Sobrien	 0x0000ffff,		/* dst_mask */
1105179407Sobrien	 FALSE),		/* pcrel_offset */
1106179407Sobrien
1107179407Sobrien  /* High 16 bits of displacement in global offset table.  */
1108179407Sobrien  HOWTO (R_MIPS_GOT_HI16,	/* type */
1109179407Sobrien	 0,			/* rightshift */
1110179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1111179407Sobrien	 16,			/* bitsize */
1112179407Sobrien	 FALSE,			/* pc_relative */
1113179407Sobrien	 0,			/* bitpos */
1114179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1115179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1116179407Sobrien	 "R_MIPS_GOT_HI16",	/* name */
1117179407Sobrien	 FALSE,			/* partial_inplace */
1118179407Sobrien	 0,			/* src_mask */
1119179407Sobrien	 0x0000ffff,		/* dst_mask */
1120179407Sobrien	 FALSE),		/* pcrel_offset */
1121179407Sobrien
1122179407Sobrien  /* Low 16 bits of displacement in global offset table.  */
1123179407Sobrien  HOWTO (R_MIPS_GOT_LO16,	/* type */
1124179407Sobrien	 0,			/* rightshift */
1125179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1126179407Sobrien	 16,			/* bitsize */
1127179407Sobrien	 FALSE,			/* pc_relative */
1128179407Sobrien	 0,			/* bitpos */
1129179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1130179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1131179407Sobrien	 "R_MIPS_GOT_LO16",	/* name */
1132179407Sobrien	 FALSE,			/* partial_inplace */
1133179407Sobrien	 0,			/* src_mask */
1134179407Sobrien	 0x0000ffff,		/* dst_mask */
1135179407Sobrien	 FALSE),		/* pcrel_offset */
1136179407Sobrien
1137179407Sobrien  /* 64 bit subtraction.  */
1138179407Sobrien  HOWTO (R_MIPS_SUB,		/* type */
1139179407Sobrien	 0,			/* rightshift */
1140179407Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
1141179407Sobrien	 64,			/* bitsize */
1142179407Sobrien	 FALSE,			/* pc_relative */
1143179407Sobrien	 0,			/* bitpos */
1144179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1145179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1146179407Sobrien	 "R_MIPS_SUB",		/* name */
1147179407Sobrien	 FALSE,			/* partial_inplace */
1148179407Sobrien	 0,			/* src_mask */
1149179407Sobrien	 MINUS_ONE,		/* dst_mask */
1150179407Sobrien	 FALSE),		/* pcrel_offset */
1151179407Sobrien
1152179407Sobrien  /* Insert the addend as an instruction.  */
1153179407Sobrien  /* FIXME: Not handled correctly.  */
1154179407Sobrien  HOWTO (R_MIPS_INSERT_A,	/* type */
1155179407Sobrien	 0,			/* rightshift */
1156179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1157179407Sobrien	 32,			/* bitsize */
1158179407Sobrien	 FALSE,			/* pc_relative */
1159179407Sobrien	 0,			/* bitpos */
1160179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1161179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1162179407Sobrien	 "R_MIPS_INSERT_A",	/* name */
1163179407Sobrien	 FALSE,			/* partial_inplace */
1164179407Sobrien	 0,			/* src_mask */
1165179407Sobrien	 0xffffffff,		/* dst_mask */
1166179407Sobrien	 FALSE),		/* pcrel_offset */
1167179407Sobrien
1168179407Sobrien  /* Insert the addend as an instruction, and change all relocations
1169179407Sobrien     to refer to the old instruction at the address.  */
1170179407Sobrien  /* FIXME: Not handled correctly.  */
1171179407Sobrien  HOWTO (R_MIPS_INSERT_B,	/* type */
1172179407Sobrien	 0,			/* rightshift */
1173179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1174179407Sobrien	 32,			/* bitsize */
1175179407Sobrien	 FALSE,			/* pc_relative */
1176179407Sobrien	 0,			/* bitpos */
1177179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1178179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1179179407Sobrien	 "R_MIPS_INSERT_B",	/* name */
1180179407Sobrien	 FALSE,			/* partial_inplace */
1181179407Sobrien	 0,			/* src_mask */
1182179407Sobrien	 0xffffffff,		/* dst_mask */
1183179407Sobrien	 FALSE),		/* pcrel_offset */
1184179407Sobrien
1185179407Sobrien  /* Delete a 32 bit instruction.  */
1186179407Sobrien  /* FIXME: Not handled correctly.  */
1187179407Sobrien  HOWTO (R_MIPS_DELETE,		/* type */
1188179407Sobrien	 0,			/* rightshift */
1189179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1190179407Sobrien	 32,			/* bitsize */
1191179407Sobrien	 FALSE,			/* pc_relative */
1192179407Sobrien	 0,			/* bitpos */
1193179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1194179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1195179407Sobrien	 "R_MIPS_DELETE",	/* name */
1196179407Sobrien	 FALSE,			/* partial_inplace */
1197179407Sobrien	 0,			/* src_mask */
1198179407Sobrien	 0xffffffff,		/* dst_mask */
1199179407Sobrien	 FALSE),		/* pcrel_offset */
1200179407Sobrien
1201179407Sobrien  /* Get the higher value of a 64 bit addend.  */
1202179407Sobrien  HOWTO (R_MIPS_HIGHER,		/* type */
1203179407Sobrien	 0,			/* rightshift */
1204179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1205179407Sobrien	 16,			/* bitsize */
1206179407Sobrien	 FALSE,			/* pc_relative */
1207179407Sobrien	 0,			/* bitpos */
1208179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1209179407Sobrien	 _bfd_mips_elf_generic_reloc, /* special_function */
1210179407Sobrien	 "R_MIPS_HIGHER",	/* name */
1211179407Sobrien	 FALSE,			/* partial_inplace */
1212179407Sobrien	 0,			/* src_mask */
1213179407Sobrien	 0x0000ffff,		/* dst_mask */
1214179407Sobrien	 FALSE),		/* pcrel_offset */
1215179407Sobrien
1216179407Sobrien  /* Get the highest value of a 64 bit addend.  */
1217179407Sobrien  HOWTO (R_MIPS_HIGHEST,	/* type */
1218179407Sobrien	 0,			/* rightshift */
1219179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1220179407Sobrien	 16,			/* bitsize */
1221179407Sobrien	 FALSE,			/* pc_relative */
1222179407Sobrien	 0,			/* bitpos */
1223179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1224179407Sobrien	 _bfd_mips_elf_generic_reloc, /* special_function */
1225179407Sobrien	 "R_MIPS_HIGHEST",	/* name */
1226179407Sobrien	 FALSE,			/* partial_inplace */
1227179407Sobrien	 0,			/* src_mask */
1228179407Sobrien	 0x0000ffff,		/* dst_mask */
1229179407Sobrien	 FALSE),		/* pcrel_offset */
1230179407Sobrien
1231179407Sobrien  /* High 16 bits of displacement in global offset table.  */
1232179407Sobrien  HOWTO (R_MIPS_CALL_HI16,	/* type */
1233179407Sobrien	 0,			/* rightshift */
1234179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1235179407Sobrien	 16,			/* bitsize */
1236179407Sobrien	 FALSE,			/* pc_relative */
1237179407Sobrien	 0,			/* bitpos */
1238179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1239179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1240179407Sobrien	 "R_MIPS_CALL_HI16",	/* name */
1241179407Sobrien	 FALSE,			/* partial_inplace */
1242179407Sobrien	 0,			/* src_mask */
1243179407Sobrien	 0x0000ffff,		/* dst_mask */
1244179407Sobrien	 FALSE),		/* pcrel_offset */
1245179407Sobrien
1246179407Sobrien  /* Low 16 bits of displacement in global offset table.  */
1247179407Sobrien  HOWTO (R_MIPS_CALL_LO16,	/* type */
1248179407Sobrien	 0,			/* rightshift */
1249179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1250179407Sobrien	 16,			/* bitsize */
1251179407Sobrien	 FALSE,			/* pc_relative */
1252179407Sobrien	 0,			/* bitpos */
1253179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1254179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1255179407Sobrien	 "R_MIPS_CALL_LO16",	/* name */
1256179407Sobrien	 FALSE,			/* partial_inplace */
1257179407Sobrien	 0,			/* src_mask */
1258179407Sobrien	 0x0000ffff,		/* dst_mask */
1259179407Sobrien	 FALSE),		/* pcrel_offset */
1260179407Sobrien
1261179407Sobrien  /* Section displacement, used by an associated event location section.  */
1262179407Sobrien  HOWTO (R_MIPS_SCN_DISP,	/* type */
1263179407Sobrien	 0,			/* rightshift */
1264179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1265179407Sobrien	 32,			/* bitsize */
1266179407Sobrien	 FALSE,			/* pc_relative */
1267179407Sobrien	 0,			/* bitpos */
1268179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1269179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1270179407Sobrien	 "R_MIPS_SCN_DISP",	/* name */
1271179407Sobrien	 FALSE,			/* partial_inplace */
1272179407Sobrien	 0,			/* src_mask */
1273179407Sobrien	 0xffffffff,		/* dst_mask */
1274179407Sobrien	 FALSE),		/* pcrel_offset */
1275179407Sobrien
1276179407Sobrien  HOWTO (R_MIPS_REL16,		/* type */
1277179407Sobrien	 0,			/* rightshift */
1278179407Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1279179407Sobrien	 16,			/* bitsize */
1280179407Sobrien	 FALSE,			/* pc_relative */
1281179407Sobrien	 0,			/* bitpos */
1282179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1283179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1284179407Sobrien	 "R_MIPS_REL16",	/* name */
1285179407Sobrien	 FALSE,			/* partial_inplace */
1286179407Sobrien	 0,			/* src_mask */
1287179407Sobrien	 0xffff,		/* dst_mask */
1288179407Sobrien	 FALSE),		/* pcrel_offset */
1289179407Sobrien
1290179407Sobrien  /* These two are obsolete.  */
1291179407Sobrien  EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
1292179407Sobrien  EMPTY_HOWTO (R_MIPS_PJUMP),
1293179407Sobrien
1294179407Sobrien  /* Similiar to R_MIPS_REL32, but used for relocations in a GOT section.
1295179407Sobrien     It must be used for multigot GOT's (and only there).  */
1296179407Sobrien  HOWTO (R_MIPS_RELGOT,		/* type */
1297179407Sobrien	 0,			/* rightshift */
1298179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1299179407Sobrien	 32,			/* bitsize */
1300179407Sobrien	 FALSE,			/* pc_relative */
1301179407Sobrien	 0,			/* bitpos */
1302179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1303179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1304179407Sobrien	 "R_MIPS_RELGOT",	/* name */
1305179407Sobrien	 FALSE,			/* partial_inplace */
1306179407Sobrien	 0,			/* src_mask */
1307179407Sobrien	 0xffffffff,		/* dst_mask */
1308179407Sobrien	 FALSE),		/* pcrel_offset */
1309179407Sobrien
1310179407Sobrien  /* Protected jump conversion.  This is an optimization hint.  No
1311179407Sobrien     relocation is required for correctness.  */
1312218822Sdim  HOWTO (R_MIPS_JALR,		/* type */
1313179407Sobrien	 0,			/* rightshift */
1314179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1315179407Sobrien	 32,			/* bitsize */
1316179407Sobrien	 FALSE,			/* pc_relative */
1317179407Sobrien	 0,			/* bitpos */
1318179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1319179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1320218822Sdim	 "R_MIPS_JALR",		/* name */
1321179407Sobrien	 FALSE,			/* partial_inplace */
1322179407Sobrien	 0,			/* src_mask */
1323179407Sobrien	 0x00000000,		/* dst_mask */
1324179407Sobrien	 FALSE),		/* pcrel_offset */
1325218822Sdim
1326218822Sdim  /* TLS relocations.  */
1327218822Sdim  EMPTY_HOWTO (R_MIPS_TLS_DTPMOD32),
1328218822Sdim  EMPTY_HOWTO (R_MIPS_TLS_DTPREL32),
1329218822Sdim  EMPTY_HOWTO (R_MIPS_TLS_DTPMOD64),
1330218822Sdim
1331218822Sdim  HOWTO (R_MIPS_TLS_DTPREL64,	/* type */
1332218822Sdim	 0,			/* rightshift */
1333218822Sdim	 4,			/* size (0 = byte, 1 = short, 2 = long) */
1334218822Sdim	 64,			/* bitsize */
1335218822Sdim	 FALSE,			/* pc_relative */
1336218822Sdim	 0,			/* bitpos */
1337218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
1338218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1339218822Sdim	 "R_MIPS_TLS_DTPREL64",	/* name */
1340218822Sdim	 TRUE,			/* partial_inplace */
1341218822Sdim	 MINUS_ONE,		/* src_mask */
1342218822Sdim	 MINUS_ONE,		/* dst_mask */
1343218822Sdim	 FALSE),		/* pcrel_offset */
1344218822Sdim
1345218822Sdim  /* TLS general dynamic variable reference.  */
1346218822Sdim  HOWTO (R_MIPS_TLS_GD,		/* type */
1347218822Sdim	 0,			/* rightshift */
1348218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1349218822Sdim	 16,			/* bitsize */
1350218822Sdim	 FALSE,			/* pc_relative */
1351218822Sdim	 0,			/* bitpos */
1352218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
1353218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1354218822Sdim	 "R_MIPS_TLS_GD",	/* name */
1355218822Sdim	 TRUE,			/* partial_inplace */
1356218822Sdim	 0x0000ffff,		/* src_mask */
1357218822Sdim	 0x0000ffff,		/* dst_mask */
1358218822Sdim	 FALSE),		/* pcrel_offset */
1359218822Sdim
1360218822Sdim  /* TLS local dynamic variable reference.  */
1361218822Sdim  HOWTO (R_MIPS_TLS_LDM,	/* type */
1362218822Sdim	 0,			/* rightshift */
1363218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1364218822Sdim	 16,			/* bitsize */
1365218822Sdim	 FALSE,			/* pc_relative */
1366218822Sdim	 0,			/* bitpos */
1367218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
1368218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1369218822Sdim	 "R_MIPS_TLS_LDM",	/* name */
1370218822Sdim	 TRUE,			/* partial_inplace */
1371218822Sdim	 0x0000ffff,		/* src_mask */
1372218822Sdim	 0x0000ffff,		/* dst_mask */
1373218822Sdim	 FALSE),		/* pcrel_offset */
1374218822Sdim
1375218822Sdim  /* TLS local dynamic offset.  */
1376218822Sdim  HOWTO (R_MIPS_TLS_DTPREL_HI16,	/* type */
1377218822Sdim	 0,			/* rightshift */
1378218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1379218822Sdim	 16,			/* bitsize */
1380218822Sdim	 FALSE,			/* pc_relative */
1381218822Sdim	 0,			/* bitpos */
1382218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
1383218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1384218822Sdim	 "R_MIPS_TLS_DTPREL_HI16",	/* name */
1385218822Sdim	 TRUE,			/* partial_inplace */
1386218822Sdim	 0x0000ffff,		/* src_mask */
1387218822Sdim	 0x0000ffff,		/* dst_mask */
1388218822Sdim	 FALSE),		/* pcrel_offset */
1389218822Sdim
1390218822Sdim  /* TLS local dynamic offset.  */
1391218822Sdim  HOWTO (R_MIPS_TLS_DTPREL_LO16,	/* type */
1392218822Sdim	 0,			/* rightshift */
1393218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1394218822Sdim	 16,			/* bitsize */
1395218822Sdim	 FALSE,			/* pc_relative */
1396218822Sdim	 0,			/* bitpos */
1397218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
1398218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1399218822Sdim	 "R_MIPS_TLS_DTPREL_LO16",	/* name */
1400218822Sdim	 TRUE,			/* partial_inplace */
1401218822Sdim	 0x0000ffff,		/* src_mask */
1402218822Sdim	 0x0000ffff,		/* dst_mask */
1403218822Sdim	 FALSE),		/* pcrel_offset */
1404218822Sdim
1405218822Sdim  /* TLS thread pointer offset.  */
1406218822Sdim  HOWTO (R_MIPS_TLS_GOTTPREL,	/* type */
1407218822Sdim	 0,			/* rightshift */
1408218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1409218822Sdim	 16,			/* bitsize */
1410218822Sdim	 FALSE,			/* pc_relative */
1411218822Sdim	 0,			/* bitpos */
1412218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
1413218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1414218822Sdim	 "R_MIPS_TLS_GOTTPREL",	/* name */
1415218822Sdim	 TRUE,			/* partial_inplace */
1416218822Sdim	 0x0000ffff,		/* src_mask */
1417218822Sdim	 0x0000ffff,		/* dst_mask */
1418218822Sdim	 FALSE),		/* pcrel_offset */
1419218822Sdim
1420218822Sdim  EMPTY_HOWTO (R_MIPS_TLS_TPREL32),
1421218822Sdim  EMPTY_HOWTO (R_MIPS_TLS_TPREL64),
1422218822Sdim
1423218822Sdim  /* TLS thread pointer offset.  */
1424218822Sdim  HOWTO (R_MIPS_TLS_TPREL_HI16,	/* type */
1425218822Sdim	 0,			/* rightshift */
1426218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1427218822Sdim	 16,			/* bitsize */
1428218822Sdim	 FALSE,			/* pc_relative */
1429218822Sdim	 0,			/* bitpos */
1430218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
1431218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1432218822Sdim	 "R_MIPS_TLS_TPREL_HI16", /* name */
1433218822Sdim	 TRUE,			/* partial_inplace */
1434218822Sdim	 0x0000ffff,		/* src_mask */
1435218822Sdim	 0x0000ffff,		/* dst_mask */
1436218822Sdim	 FALSE),		/* pcrel_offset */
1437218822Sdim
1438218822Sdim  /* TLS thread pointer offset.  */
1439218822Sdim  HOWTO (R_MIPS_TLS_TPREL_LO16,	/* type */
1440218822Sdim	 0,			/* rightshift */
1441218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1442218822Sdim	 16,			/* bitsize */
1443218822Sdim	 FALSE,			/* pc_relative */
1444218822Sdim	 0,			/* bitpos */
1445218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
1446218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1447218822Sdim	 "R_MIPS_TLS_TPREL_LO16", /* name */
1448218822Sdim	 TRUE,			/* partial_inplace */
1449218822Sdim	 0x0000ffff,		/* src_mask */
1450218822Sdim	 0x0000ffff,		/* dst_mask */
1451218822Sdim	 FALSE),		/* pcrel_offset */
1452218822Sdim
1453218822Sdim  /* 32 bit relocation with no addend.  */
1454218822Sdim  HOWTO (R_MIPS_GLOB_DAT,	/* type */
1455218822Sdim	 0,			/* rightshift */
1456218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1457218822Sdim	 32,			/* bitsize */
1458218822Sdim	 FALSE,			/* pc_relative */
1459218822Sdim	 0,			/* bitpos */
1460218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
1461218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1462218822Sdim	 "R_MIPS_GLOB_DAT",	/* name */
1463218822Sdim	 FALSE,			/* partial_inplace */
1464218822Sdim	 0x0,			/* src_mask */
1465218822Sdim	 0xffffffff,		/* dst_mask */
1466218822Sdim	 FALSE),		/* pcrel_offset */
1467179407Sobrien};
1468179407Sobrien
1469218822Sdimstatic reloc_howto_type mips16_elf64_howto_table_rel[] =
1470218822Sdim{
1471218822Sdim  /* The reloc used for the mips16 jump instruction.  */
1472179407Sobrien  HOWTO (R_MIPS16_26,		/* type */
1473179407Sobrien	 2,			/* rightshift */
1474179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1475179407Sobrien	 26,			/* bitsize */
1476179407Sobrien	 FALSE,			/* pc_relative */
1477179407Sobrien	 0,			/* bitpos */
1478179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1479179407Sobrien	 			/* This needs complex overflow
1480179407Sobrien				   detection, because the upper four
1481179407Sobrien				   bits must match the PC.  */
1482218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1483179407Sobrien	 "R_MIPS16_26",		/* name */
1484179407Sobrien	 TRUE,			/* partial_inplace */
1485179407Sobrien	 0x3ffffff,		/* src_mask */
1486179407Sobrien	 0x3ffffff,		/* dst_mask */
1487218822Sdim	 FALSE),		/* pcrel_offset */
1488179407Sobrien
1489218822Sdim  /* The reloc used for the mips16 gprel instruction.  */
1490179407Sobrien  HOWTO (R_MIPS16_GPREL,	/* type */
1491179407Sobrien	 0,			/* rightshift */
1492179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1493179407Sobrien	 16,			/* bitsize */
1494179407Sobrien	 FALSE,			/* pc_relative */
1495179407Sobrien	 0,			/* bitpos */
1496179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1497179407Sobrien	 mips16_gprel_reloc,	/* special_function */
1498179407Sobrien	 "R_MIPS16_GPREL",	/* name */
1499179407Sobrien	 TRUE,			/* partial_inplace */
1500218822Sdim	 0x0000ffff,		/* src_mask */
1501218822Sdim	 0x0000ffff,	        /* dst_mask */
1502218822Sdim	 FALSE),		/* pcrel_offset */
1503179407Sobrien
1504218822Sdim  /* A placeholder for MIPS16 reference to global offset table.  */
1505218822Sdim  EMPTY_HOWTO (R_MIPS16_GOT16),
1506218822Sdim
1507218822Sdim  /* A placeholder for MIPS16 16 bit call through global offset table.  */
1508218822Sdim  EMPTY_HOWTO (R_MIPS16_CALL16),
1509218822Sdim
1510218822Sdim  /* MIPS16 high 16 bits of symbol value.  */
1511218822Sdim  HOWTO (R_MIPS16_HI16,		/* type */
1512218822Sdim	 16,			/* rightshift */
1513218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1514218822Sdim	 16,			/* bitsize */
1515218822Sdim	 FALSE,			/* pc_relative */
1516218822Sdim	 0,			/* bitpos */
1517218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
1518218822Sdim	 _bfd_mips_elf_hi16_reloc, /* special_function */
1519218822Sdim	 "R_MIPS16_HI16",	/* name */
1520218822Sdim	 TRUE,			/* partial_inplace */
1521218822Sdim	 0x0000ffff,		/* src_mask */
1522218822Sdim	 0x0000ffff,		/* dst_mask */
1523218822Sdim	 FALSE),		/* pcrel_offset */
1524218822Sdim
1525218822Sdim  /* MIPS16 low 16 bits of symbol value.  */
1526218822Sdim  HOWTO (R_MIPS16_LO16,		/* type */
1527218822Sdim	 0,			/* rightshift */
1528218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1529218822Sdim	 16,			/* bitsize */
1530218822Sdim	 FALSE,			/* pc_relative */
1531218822Sdim	 0,			/* bitpos */
1532218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
1533218822Sdim	 _bfd_mips_elf_lo16_reloc, /* special_function */
1534218822Sdim	 "R_MIPS16_LO16",	/* name */
1535218822Sdim	 TRUE,			/* partial_inplace */
1536218822Sdim	 0x0000ffff,		/* src_mask */
1537218822Sdim	 0x0000ffff,		/* dst_mask */
1538218822Sdim	 FALSE),		/* pcrel_offset */
1539218822Sdim};
1540218822Sdim
1541218822Sdimstatic reloc_howto_type mips16_elf64_howto_table_rela[] =
1542218822Sdim{
1543218822Sdim  /* The reloc used for the mips16 jump instruction.  */
1544218822Sdim  HOWTO (R_MIPS16_26,		/* type */
1545218822Sdim	 2,			/* rightshift */
1546218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1547218822Sdim	 26,			/* bitsize */
1548218822Sdim	 FALSE,			/* pc_relative */
1549218822Sdim	 0,			/* bitpos */
1550218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
1551218822Sdim	 			/* This needs complex overflow
1552218822Sdim				   detection, because the upper four
1553218822Sdim				   bits must match the PC.  */
1554218822Sdim	 _bfd_mips_elf_generic_reloc, /* special_function */
1555218822Sdim	 "R_MIPS16_26",		/* name */
1556218822Sdim	 FALSE,			/* partial_inplace */
1557218822Sdim	 0x3ffffff,		/* src_mask */
1558218822Sdim	 0x3ffffff,		/* dst_mask */
1559218822Sdim	 FALSE),		/* pcrel_offset */
1560218822Sdim
1561218822Sdim  /* The reloc used for the mips16 gprel instruction.  */
1562218822Sdim  HOWTO (R_MIPS16_GPREL,	/* type */
1563218822Sdim	 0,			/* rightshift */
1564218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1565218822Sdim	 16,			/* bitsize */
1566218822Sdim	 FALSE,			/* pc_relative */
1567218822Sdim	 0,			/* bitpos */
1568218822Sdim	 complain_overflow_signed, /* complain_on_overflow */
1569218822Sdim	 mips16_gprel_reloc,	/* special_function */
1570218822Sdim	 "R_MIPS16_GPREL",	/* name */
1571218822Sdim	 FALSE,			/* partial_inplace */
1572218822Sdim	 0x0000ffff,		/* src_mask */
1573218822Sdim	 0x0000ffff,	        /* dst_mask */
1574218822Sdim	 FALSE),		/* pcrel_offset */
1575218822Sdim
1576218822Sdim  /* A placeholder for MIPS16 reference to global offset table.  */
1577218822Sdim  EMPTY_HOWTO (R_MIPS16_GOT16),
1578218822Sdim
1579218822Sdim  /* A placeholder for MIPS16 16 bit call through global offset table.  */
1580218822Sdim  EMPTY_HOWTO (R_MIPS16_CALL16),
1581218822Sdim
1582218822Sdim  /* MIPS16 high 16 bits of symbol value.  */
1583218822Sdim  HOWTO (R_MIPS16_HI16,		/* type */
1584218822Sdim	 16,			/* rightshift */
1585218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1586218822Sdim	 16,			/* bitsize */
1587218822Sdim	 FALSE,			/* pc_relative */
1588218822Sdim	 0,			/* bitpos */
1589218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
1590218822Sdim	 _bfd_mips_elf_hi16_reloc, /* special_function */
1591218822Sdim	 "R_MIPS16_HI16",	/* name */
1592218822Sdim	 FALSE,			/* partial_inplace */
1593218822Sdim	 0x0000ffff,		/* src_mask */
1594218822Sdim	 0x0000ffff,		/* dst_mask */
1595218822Sdim	 FALSE),		/* pcrel_offset */
1596218822Sdim
1597218822Sdim  /* MIPS16 low 16 bits of symbol value.  */
1598218822Sdim  HOWTO (R_MIPS16_LO16,		/* type */
1599218822Sdim	 0,			/* rightshift */
1600218822Sdim	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1601218822Sdim	 16,			/* bitsize */
1602218822Sdim	 FALSE,			/* pc_relative */
1603218822Sdim	 0,			/* bitpos */
1604218822Sdim	 complain_overflow_dont, /* complain_on_overflow */
1605218822Sdim	 _bfd_mips_elf_lo16_reloc, /* special_function */
1606218822Sdim	 "R_MIPS16_LO16",	/* name */
1607218822Sdim	 FALSE,			/* partial_inplace */
1608218822Sdim	 0x0000ffff,		/* src_mask */
1609218822Sdim	 0x0000ffff,		/* dst_mask */
1610218822Sdim	 FALSE),		/* pcrel_offset */
1611218822Sdim};
1612218822Sdim
1613179407Sobrien/* GNU extension to record C++ vtable hierarchy */
1614179407Sobrienstatic reloc_howto_type elf_mips_gnu_vtinherit_howto =
1615179407Sobrien  HOWTO (R_MIPS_GNU_VTINHERIT,	/* type */
1616179407Sobrien	 0,			/* rightshift */
1617179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1618179407Sobrien	 0,			/* bitsize */
1619179407Sobrien	 FALSE,			/* pc_relative */
1620179407Sobrien	 0,			/* bitpos */
1621179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1622179407Sobrien	 NULL,			/* special_function */
1623179407Sobrien	 "R_MIPS_GNU_VTINHERIT", /* name */
1624179407Sobrien	 FALSE,			/* partial_inplace */
1625179407Sobrien	 0,			/* src_mask */
1626179407Sobrien	 0,			/* dst_mask */
1627179407Sobrien	 FALSE);		/* pcrel_offset */
1628179407Sobrien
1629179407Sobrien/* GNU extension to record C++ vtable member usage */
1630179407Sobrienstatic reloc_howto_type elf_mips_gnu_vtentry_howto =
1631179407Sobrien  HOWTO (R_MIPS_GNU_VTENTRY,	/* type */
1632179407Sobrien	 0,			/* rightshift */
1633179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1634179407Sobrien	 0,			/* bitsize */
1635179407Sobrien	 FALSE,			/* pc_relative */
1636179407Sobrien	 0,			/* bitpos */
1637179407Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1638179407Sobrien	 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
1639179407Sobrien	 "R_MIPS_GNU_VTENTRY",	/* name */
1640179407Sobrien	 FALSE,			/* partial_inplace */
1641179407Sobrien	 0,			/* src_mask */
1642179407Sobrien	 0,			/* dst_mask */
1643179407Sobrien	 FALSE);		/* pcrel_offset */
1644179407Sobrien
1645179407Sobrien/* 16 bit offset for pc-relative branches.  */
1646179407Sobrienstatic reloc_howto_type elf_mips_gnu_rel16_s2 =
1647179407Sobrien  HOWTO (R_MIPS_GNU_REL16_S2,	/* type */
1648179407Sobrien	 2,			/* rightshift */
1649179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1650179407Sobrien	 16,			/* bitsize */
1651179407Sobrien	 TRUE,			/* pc_relative */
1652179407Sobrien	 0,			/* bitpos */
1653179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1654179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1655179407Sobrien	 "R_MIPS_GNU_REL16_S2",	/* name */
1656179407Sobrien	 TRUE,			/* partial_inplace */
1657179407Sobrien	 0x0000ffff,		/* src_mask */
1658179407Sobrien	 0x0000ffff,		/* dst_mask */
1659179407Sobrien	 TRUE);			/* pcrel_offset */
1660179407Sobrien
1661179407Sobrien/* 16 bit offset for pc-relative branches.  */
1662179407Sobrienstatic reloc_howto_type elf_mips_gnu_rela16_s2 =
1663179407Sobrien  HOWTO (R_MIPS_GNU_REL16_S2,	/* type */
1664179407Sobrien	 2,			/* rightshift */
1665179407Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1666179407Sobrien	 16,			/* bitsize */
1667179407Sobrien	 TRUE,			/* pc_relative */
1668179407Sobrien	 0,			/* bitpos */
1669179407Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1670179407Sobrien	 _bfd_mips_elf_generic_reloc,	/* special_function */
1671179407Sobrien	 "R_MIPS_GNU_REL16_S2",	/* name */
1672179407Sobrien	 FALSE,			/* partial_inplace */
1673179407Sobrien	 0,			/* src_mask */
1674179407Sobrien	 0x0000ffff,		/* dst_mask */
1675179407Sobrien	 TRUE);			/* pcrel_offset */
1676179407Sobrien
1677179407Sobrien/* Swap in a MIPS 64-bit Rel reloc.  */
1678179407Sobrien
1679179407Sobrienstatic void
1680179407Sobrienmips_elf64_swap_reloc_in (bfd *abfd, const Elf64_Mips_External_Rel *src,
1681179407Sobrien			  Elf64_Mips_Internal_Rela *dst)
1682179407Sobrien{
1683179407Sobrien  dst->r_offset = H_GET_64 (abfd, src->r_offset);
1684179407Sobrien  dst->r_sym = H_GET_32 (abfd, src->r_sym);
1685179407Sobrien  dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1686179407Sobrien  dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1687179407Sobrien  dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1688179407Sobrien  dst->r_type = H_GET_8 (abfd, src->r_type);
1689179407Sobrien  dst->r_addend = 0;
1690179407Sobrien}
1691179407Sobrien
1692179407Sobrien/* Swap in a MIPS 64-bit Rela reloc.  */
1693179407Sobrien
1694179407Sobrienstatic void
1695179407Sobrienmips_elf64_swap_reloca_in (bfd *abfd, const Elf64_Mips_External_Rela *src,
1696179407Sobrien			   Elf64_Mips_Internal_Rela *dst)
1697179407Sobrien{
1698179407Sobrien  dst->r_offset = H_GET_64 (abfd, src->r_offset);
1699179407Sobrien  dst->r_sym = H_GET_32 (abfd, src->r_sym);
1700179407Sobrien  dst->r_ssym = H_GET_8 (abfd, src->r_ssym);
1701179407Sobrien  dst->r_type3 = H_GET_8 (abfd, src->r_type3);
1702179407Sobrien  dst->r_type2 = H_GET_8 (abfd, src->r_type2);
1703179407Sobrien  dst->r_type = H_GET_8 (abfd, src->r_type);
1704179407Sobrien  dst->r_addend = H_GET_S64 (abfd, src->r_addend);
1705179407Sobrien}
1706179407Sobrien
1707179407Sobrien/* Swap out a MIPS 64-bit Rel reloc.  */
1708179407Sobrien
1709179407Sobrienstatic void
1710179407Sobrienmips_elf64_swap_reloc_out (bfd *abfd, const Elf64_Mips_Internal_Rela *src,
1711179407Sobrien			   Elf64_Mips_External_Rel *dst)
1712179407Sobrien{
1713179407Sobrien  H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1714179407Sobrien  H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1715179407Sobrien  H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1716179407Sobrien  H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1717179407Sobrien  H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1718179407Sobrien  H_PUT_8 (abfd, src->r_type, dst->r_type);
1719179407Sobrien}
1720179407Sobrien
1721179407Sobrien/* Swap out a MIPS 64-bit Rela reloc.  */
1722179407Sobrien
1723179407Sobrienstatic void
1724179407Sobrienmips_elf64_swap_reloca_out (bfd *abfd, const Elf64_Mips_Internal_Rela *src,
1725179407Sobrien			    Elf64_Mips_External_Rela *dst)
1726179407Sobrien{
1727179407Sobrien  H_PUT_64 (abfd, src->r_offset, dst->r_offset);
1728179407Sobrien  H_PUT_32 (abfd, src->r_sym, dst->r_sym);
1729179407Sobrien  H_PUT_8 (abfd, src->r_ssym, dst->r_ssym);
1730179407Sobrien  H_PUT_8 (abfd, src->r_type3, dst->r_type3);
1731179407Sobrien  H_PUT_8 (abfd, src->r_type2, dst->r_type2);
1732179407Sobrien  H_PUT_8 (abfd, src->r_type, dst->r_type);
1733179407Sobrien  H_PUT_S64 (abfd, src->r_addend, dst->r_addend);
1734179407Sobrien}
1735179407Sobrien
1736179407Sobrien/* Swap in a MIPS 64-bit Rel reloc.  */
1737179407Sobrien
1738179407Sobrienstatic void
1739179407Sobrienmips_elf64_be_swap_reloc_in (bfd *abfd, const bfd_byte *src,
1740179407Sobrien			     Elf_Internal_Rela *dst)
1741179407Sobrien{
1742179407Sobrien  Elf64_Mips_Internal_Rela mirel;
1743179407Sobrien
1744179407Sobrien  mips_elf64_swap_reloc_in (abfd,
1745179407Sobrien			    (const Elf64_Mips_External_Rel *) src,
1746179407Sobrien			    &mirel);
1747179407Sobrien
1748179407Sobrien  dst[0].r_offset = mirel.r_offset;
1749179407Sobrien  dst[0].r_info = ELF64_R_INFO (mirel.r_sym, mirel.r_type);
1750179407Sobrien  dst[0].r_addend = 0;
1751179407Sobrien  dst[1].r_offset = mirel.r_offset;
1752179407Sobrien  dst[1].r_info = ELF64_R_INFO (mirel.r_ssym, mirel.r_type2);
1753179407Sobrien  dst[1].r_addend = 0;
1754179407Sobrien  dst[2].r_offset = mirel.r_offset;
1755179407Sobrien  dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirel.r_type3);
1756179407Sobrien  dst[2].r_addend = 0;
1757179407Sobrien}
1758179407Sobrien
1759179407Sobrien/* Swap in a MIPS 64-bit Rela reloc.  */
1760179407Sobrien
1761179407Sobrienstatic void
1762179407Sobrienmips_elf64_be_swap_reloca_in (bfd *abfd, const bfd_byte *src,
1763179407Sobrien			      Elf_Internal_Rela *dst)
1764179407Sobrien{
1765179407Sobrien  Elf64_Mips_Internal_Rela mirela;
1766179407Sobrien
1767179407Sobrien  mips_elf64_swap_reloca_in (abfd,
1768179407Sobrien			     (const Elf64_Mips_External_Rela *) src,
1769179407Sobrien			     &mirela);
1770179407Sobrien
1771179407Sobrien  dst[0].r_offset = mirela.r_offset;
1772179407Sobrien  dst[0].r_info = ELF64_R_INFO (mirela.r_sym, mirela.r_type);
1773179407Sobrien  dst[0].r_addend = mirela.r_addend;
1774179407Sobrien  dst[1].r_offset = mirela.r_offset;
1775179407Sobrien  dst[1].r_info = ELF64_R_INFO (mirela.r_ssym, mirela.r_type2);
1776179407Sobrien  dst[1].r_addend = 0;
1777179407Sobrien  dst[2].r_offset = mirela.r_offset;
1778179407Sobrien  dst[2].r_info = ELF64_R_INFO (STN_UNDEF, mirela.r_type3);
1779179407Sobrien  dst[2].r_addend = 0;
1780179407Sobrien}
1781179407Sobrien
1782179407Sobrien/* Swap out a MIPS 64-bit Rel reloc.  */
1783179407Sobrien
1784179407Sobrienstatic void
1785179407Sobrienmips_elf64_be_swap_reloc_out (bfd *abfd, const Elf_Internal_Rela *src,
1786179407Sobrien			      bfd_byte *dst)
1787179407Sobrien{
1788179407Sobrien  Elf64_Mips_Internal_Rela mirel;
1789179407Sobrien
1790179407Sobrien  mirel.r_offset = src[0].r_offset;
1791179407Sobrien  BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1792179407Sobrien
1793179407Sobrien  mirel.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1794179407Sobrien  mirel.r_sym = ELF64_R_SYM (src[0].r_info);
1795179407Sobrien  mirel.r_type2 = ELF64_MIPS_R_TYPE (src[1].r_info);
1796179407Sobrien  mirel.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1797179407Sobrien  mirel.r_type3 = ELF64_MIPS_R_TYPE (src[2].r_info);
1798179407Sobrien
1799179407Sobrien  mips_elf64_swap_reloc_out (abfd, &mirel,
1800179407Sobrien			     (Elf64_Mips_External_Rel *) dst);
1801179407Sobrien}
1802179407Sobrien
1803179407Sobrien/* Swap out a MIPS 64-bit Rela reloc.  */
1804179407Sobrien
1805179407Sobrienstatic void
1806179407Sobrienmips_elf64_be_swap_reloca_out (bfd *abfd, const Elf_Internal_Rela *src,
1807179407Sobrien			       bfd_byte *dst)
1808179407Sobrien{
1809179407Sobrien  Elf64_Mips_Internal_Rela mirela;
1810179407Sobrien
1811179407Sobrien  mirela.r_offset = src[0].r_offset;
1812179407Sobrien  BFD_ASSERT(src[0].r_offset == src[1].r_offset);
1813179407Sobrien  BFD_ASSERT(src[0].r_offset == src[2].r_offset);
1814179407Sobrien
1815179407Sobrien  mirela.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
1816179407Sobrien  mirela.r_sym = ELF64_R_SYM (src[0].r_info);
1817179407Sobrien  mirela.r_addend = src[0].r_addend;
1818179407Sobrien  BFD_ASSERT(src[1].r_addend == 0);
1819179407Sobrien  BFD_ASSERT(src[2].r_addend == 0);
1820179407Sobrien
1821179407Sobrien  mirela.r_type2 = ELF64_MIPS_R_TYPE (src[1].r_info);
1822179407Sobrien  mirela.r_ssym = ELF64_MIPS_R_SSYM (src[1].r_info);
1823179407Sobrien  mirela.r_type3 = ELF64_MIPS_R_TYPE (src[2].r_info);
1824179407Sobrien
1825179407Sobrien  mips_elf64_swap_reloca_out (abfd, &mirela,
1826179407Sobrien			      (Elf64_Mips_External_Rela *) dst);
1827179407Sobrien}
1828179407Sobrien
1829179407Sobrien/* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
1830179407Sobrien   dangerous relocation.  */
1831179407Sobrien
1832179407Sobrienstatic bfd_boolean
1833179407Sobrienmips_elf64_assign_gp (bfd *output_bfd, bfd_vma *pgp)
1834179407Sobrien{
1835179407Sobrien  unsigned int count;
1836179407Sobrien  asymbol **sym;
1837179407Sobrien  unsigned int i;
1838179407Sobrien
1839179407Sobrien  /* If we've already figured out what GP will be, just return it.  */
1840179407Sobrien  *pgp = _bfd_get_gp_value (output_bfd);
1841179407Sobrien  if (*pgp)
1842179407Sobrien    return TRUE;
1843179407Sobrien
1844179407Sobrien  count = bfd_get_symcount (output_bfd);
1845179407Sobrien  sym = bfd_get_outsymbols (output_bfd);
1846179407Sobrien
1847179407Sobrien  /* The linker script will have created a symbol named `_gp' with the
1848179407Sobrien     appropriate value.  */
1849179407Sobrien  if (sym == NULL)
1850179407Sobrien    i = count;
1851179407Sobrien  else
1852179407Sobrien    {
1853179407Sobrien      for (i = 0; i < count; i++, sym++)
1854179407Sobrien	{
1855179407Sobrien	  register const char *name;
1856179407Sobrien
1857179407Sobrien	  name = bfd_asymbol_name (*sym);
1858179407Sobrien	  if (*name == '_' && strcmp (name, "_gp") == 0)
1859179407Sobrien	    {
1860179407Sobrien	      *pgp = bfd_asymbol_value (*sym);
1861179407Sobrien	      _bfd_set_gp_value (output_bfd, *pgp);
1862179407Sobrien	      break;
1863179407Sobrien	    }
1864179407Sobrien	}
1865179407Sobrien    }
1866179407Sobrien
1867179407Sobrien  if (i >= count)
1868179407Sobrien    {
1869179407Sobrien      /* Only get the error once.  */
1870179407Sobrien      *pgp = 4;
1871179407Sobrien      _bfd_set_gp_value (output_bfd, *pgp);
1872179407Sobrien      return FALSE;
1873179407Sobrien    }
1874179407Sobrien
1875179407Sobrien  return TRUE;
1876179407Sobrien}
1877179407Sobrien
1878179407Sobrien/* We have to figure out the gp value, so that we can adjust the
1879179407Sobrien   symbol value correctly.  We look up the symbol _gp in the output
1880179407Sobrien   BFD.  If we can't find it, we're stuck.  We cache it in the ELF
1881179407Sobrien   target data.  We don't need to adjust the symbol value for an
1882179407Sobrien   external symbol if we are producing relocatable output.  */
1883179407Sobrien
1884179407Sobrienstatic bfd_reloc_status_type
1885179407Sobrienmips_elf64_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable,
1886179407Sobrien		     char **error_message, bfd_vma *pgp)
1887179407Sobrien{
1888179407Sobrien  if (bfd_is_und_section (symbol->section)
1889179407Sobrien      && ! relocatable)
1890179407Sobrien    {
1891179407Sobrien      *pgp = 0;
1892179407Sobrien      return bfd_reloc_undefined;
1893179407Sobrien    }
1894179407Sobrien
1895179407Sobrien  *pgp = _bfd_get_gp_value (output_bfd);
1896179407Sobrien  if (*pgp == 0
1897179407Sobrien      && (! relocatable
1898179407Sobrien	  || (symbol->flags & BSF_SECTION_SYM) != 0))
1899179407Sobrien    {
1900179407Sobrien      if (relocatable)
1901179407Sobrien	{
1902179407Sobrien	  /* Make up a value.  */
1903179407Sobrien	  *pgp = symbol->section->output_section->vma /*+ 0x4000*/;
1904179407Sobrien	  _bfd_set_gp_value (output_bfd, *pgp);
1905179407Sobrien	}
1906179407Sobrien      else if (!mips_elf64_assign_gp (output_bfd, pgp))
1907179407Sobrien	{
1908179407Sobrien	  *error_message =
1909179407Sobrien	    (char *) _("GP relative relocation when _gp not defined");
1910179407Sobrien	  return bfd_reloc_dangerous;
1911179407Sobrien	}
1912179407Sobrien    }
1913179407Sobrien
1914179407Sobrien  return bfd_reloc_ok;
1915179407Sobrien}
1916179407Sobrien
1917179407Sobrien/* Do a R_MIPS_GPREL16 relocation.  This is a 16 bit value which must
1918179407Sobrien   become the offset from the gp register.  */
1919179407Sobrien
1920179407Sobrienstatic bfd_reloc_status_type
1921179407Sobrienmips_elf64_gprel16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
1922179407Sobrien			  void *data, asection *input_section, bfd *output_bfd,
1923179407Sobrien			  char **error_message)
1924179407Sobrien{
1925179407Sobrien  bfd_boolean relocatable;
1926179407Sobrien  bfd_reloc_status_type ret;
1927179407Sobrien  bfd_vma gp;
1928179407Sobrien
1929179407Sobrien  /* If we're relocating, and this is an external symbol, we don't want
1930179407Sobrien     to change anything.  */
1931179407Sobrien  if (output_bfd != NULL
1932179407Sobrien      && (symbol->flags & BSF_SECTION_SYM) == 0
1933179407Sobrien      && (symbol->flags & BSF_LOCAL) != 0)
1934179407Sobrien    {
1935179407Sobrien      reloc_entry->address += input_section->output_offset;
1936179407Sobrien      return bfd_reloc_ok;
1937179407Sobrien    }
1938179407Sobrien
1939179407Sobrien  if (output_bfd != NULL)
1940179407Sobrien    relocatable = TRUE;
1941179407Sobrien  else
1942179407Sobrien    {
1943179407Sobrien      relocatable = FALSE;
1944179407Sobrien      output_bfd = symbol->section->output_section->owner;
1945179407Sobrien    }
1946179407Sobrien
1947179407Sobrien  ret = mips_elf64_final_gp (output_bfd, symbol, relocatable, error_message,
1948179407Sobrien			     &gp);
1949179407Sobrien  if (ret != bfd_reloc_ok)
1950179407Sobrien    return ret;
1951179407Sobrien
1952179407Sobrien  return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1953179407Sobrien					input_section, relocatable,
1954179407Sobrien					data, gp);
1955179407Sobrien}
1956179407Sobrien
1957179407Sobrien/* Do a R_MIPS_LITERAL relocation.  */
1958179407Sobrien
1959179407Sobrienstatic bfd_reloc_status_type
1960179407Sobrienmips_elf64_literal_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
1961179407Sobrien			  void *data, asection *input_section, bfd *output_bfd,
1962179407Sobrien			  char **error_message)
1963179407Sobrien{
1964179407Sobrien  bfd_boolean relocatable;
1965179407Sobrien  bfd_reloc_status_type ret;
1966179407Sobrien  bfd_vma gp;
1967179407Sobrien
1968218822Sdim  /* R_MIPS_LITERAL relocations are defined for local symbols only.  */
1969179407Sobrien  if (output_bfd != NULL
1970179407Sobrien      && (symbol->flags & BSF_SECTION_SYM) == 0
1971179407Sobrien      && (symbol->flags & BSF_LOCAL) != 0)
1972179407Sobrien    {
1973218822Sdim      *error_message = (char *)
1974218822Sdim	_("literal relocation occurs for an external symbol");
1975218822Sdim      return bfd_reloc_outofrange;
1976179407Sobrien    }
1977179407Sobrien
1978179407Sobrien  /* FIXME: The entries in the .lit8 and .lit4 sections should be merged.  */
1979179407Sobrien  if (output_bfd != NULL)
1980179407Sobrien    relocatable = TRUE;
1981179407Sobrien  else
1982179407Sobrien    {
1983179407Sobrien      relocatable = FALSE;
1984179407Sobrien      output_bfd = symbol->section->output_section->owner;
1985179407Sobrien    }
1986179407Sobrien
1987179407Sobrien  ret = mips_elf64_final_gp (output_bfd, symbol, relocatable, error_message,
1988179407Sobrien			     &gp);
1989179407Sobrien  if (ret != bfd_reloc_ok)
1990179407Sobrien    return ret;
1991179407Sobrien
1992179407Sobrien  return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
1993179407Sobrien					input_section, relocatable,
1994179407Sobrien					data, gp);
1995179407Sobrien}
1996179407Sobrien
1997179407Sobrien/* Do a R_MIPS_GPREL32 relocation.  This is a 32 bit value which must
1998179407Sobrien   become the offset from the gp register.  */
1999179407Sobrien
2000179407Sobrienstatic bfd_reloc_status_type
2001179407Sobrienmips_elf64_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2002179407Sobrien			  void *data, asection *input_section, bfd *output_bfd,
2003179407Sobrien			  char **error_message)
2004179407Sobrien{
2005179407Sobrien  bfd_boolean relocatable;
2006179407Sobrien  bfd_reloc_status_type ret;
2007179407Sobrien  bfd_vma gp;
2008179407Sobrien  bfd_vma relocation;
2009179407Sobrien  bfd_vma val;
2010179407Sobrien
2011218822Sdim  /* R_MIPS_GPREL32 relocations are defined for local symbols only.  */
2012179407Sobrien  if (output_bfd != NULL
2013179407Sobrien      && (symbol->flags & BSF_SECTION_SYM) == 0
2014179407Sobrien      && (symbol->flags & BSF_LOCAL) != 0)
2015179407Sobrien    {
2016179407Sobrien      *error_message = (char *)
2017179407Sobrien	_("32bits gp relative relocation occurs for an external symbol");
2018179407Sobrien      return bfd_reloc_outofrange;
2019179407Sobrien    }
2020179407Sobrien
2021179407Sobrien  if (output_bfd != NULL)
2022179407Sobrien    relocatable = TRUE;
2023179407Sobrien  else
2024179407Sobrien    {
2025179407Sobrien      relocatable = FALSE;
2026179407Sobrien      output_bfd = symbol->section->output_section->owner;
2027179407Sobrien    }
2028179407Sobrien
2029218822Sdim  ret = mips_elf64_final_gp (output_bfd, symbol, relocatable,
2030218822Sdim			     error_message, &gp);
2031218822Sdim  if (ret != bfd_reloc_ok)
2032218822Sdim    return ret;
2033179407Sobrien
2034179407Sobrien  if (bfd_is_com_section (symbol->section))
2035179407Sobrien    relocation = 0;
2036179407Sobrien  else
2037179407Sobrien    relocation = symbol->value;
2038179407Sobrien
2039179407Sobrien  relocation += symbol->section->output_section->vma;
2040179407Sobrien  relocation += symbol->section->output_offset;
2041179407Sobrien
2042218822Sdim  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
2043179407Sobrien    return bfd_reloc_outofrange;
2044179407Sobrien
2045179407Sobrien  /* Set val to the offset into the section or symbol.  */
2046179407Sobrien  val = reloc_entry->addend;
2047179407Sobrien
2048179407Sobrien  if (reloc_entry->howto->partial_inplace)
2049179407Sobrien    val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
2050179407Sobrien
2051179407Sobrien  /* Adjust val for the final section location and GP value.  If we
2052179407Sobrien     are producing relocatable output, we don't want to do this for
2053179407Sobrien     an external symbol.  */
2054179407Sobrien  if (! relocatable
2055179407Sobrien      || (symbol->flags & BSF_SECTION_SYM) != 0)
2056179407Sobrien    val += relocation - gp;
2057179407Sobrien
2058179407Sobrien  if (reloc_entry->howto->partial_inplace)
2059179407Sobrien    bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
2060179407Sobrien  else
2061179407Sobrien    reloc_entry->addend = val;
2062179407Sobrien
2063179407Sobrien  if (relocatable)
2064179407Sobrien    reloc_entry->address += input_section->output_offset;
2065179407Sobrien
2066179407Sobrien  return bfd_reloc_ok;
2067179407Sobrien}
2068179407Sobrien
2069179407Sobrien/* Do a R_MIPS_SHIFT6 relocation. The MSB of the shift is stored at bit 2,
2070179407Sobrien   the rest is at bits 6-10. The bitpos already got right by the howto.  */
2071179407Sobrien
2072179407Sobrienstatic bfd_reloc_status_type
2073179407Sobrienmips_elf64_shift6_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2074179407Sobrien			 void *data, asection *input_section, bfd *output_bfd,
2075179407Sobrien			 char **error_message)
2076179407Sobrien{
2077179407Sobrien  if (reloc_entry->howto->partial_inplace)
2078179407Sobrien    {
2079179407Sobrien      reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
2080179407Sobrien			     | (reloc_entry->addend & 0x00000800) >> 9);
2081179407Sobrien    }
2082179407Sobrien
2083179407Sobrien  return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
2084179407Sobrien				      input_section, output_bfd,
2085179407Sobrien				      error_message);
2086179407Sobrien}
2087179407Sobrien
2088179407Sobrien/* Handle a mips16 GP relative reloc.  */
2089179407Sobrien
2090179407Sobrienstatic bfd_reloc_status_type
2091179407Sobrienmips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2092179407Sobrien		    void *data, asection *input_section, bfd *output_bfd,
2093179407Sobrien		    char **error_message)
2094179407Sobrien{
2095179407Sobrien  bfd_boolean relocatable;
2096179407Sobrien  bfd_reloc_status_type ret;
2097218822Sdim  bfd_byte *location;
2098179407Sobrien  bfd_vma gp;
2099179407Sobrien
2100218822Sdim  /* If we're relocating, and this is an external symbol, we don't want
2101218822Sdim     to change anything.  */
2102179407Sobrien  if (output_bfd != NULL
2103179407Sobrien      && (symbol->flags & BSF_SECTION_SYM) == 0
2104179407Sobrien      && (symbol->flags & BSF_LOCAL) != 0)
2105179407Sobrien    {
2106179407Sobrien      reloc_entry->address += input_section->output_offset;
2107179407Sobrien      return bfd_reloc_ok;
2108179407Sobrien    }
2109179407Sobrien
2110179407Sobrien  if (output_bfd != NULL)
2111179407Sobrien    relocatable = TRUE;
2112179407Sobrien  else
2113179407Sobrien    {
2114179407Sobrien      relocatable = FALSE;
2115179407Sobrien      output_bfd = symbol->section->output_section->owner;
2116179407Sobrien    }
2117179407Sobrien
2118179407Sobrien  ret = mips_elf64_final_gp (output_bfd, symbol, relocatable, error_message,
2119179407Sobrien			     &gp);
2120179407Sobrien  if (ret != bfd_reloc_ok)
2121179407Sobrien    return ret;
2122179407Sobrien
2123218822Sdim  location = (bfd_byte *) data + reloc_entry->address;
2124218822Sdim  _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
2125218822Sdim				   location);
2126218822Sdim  ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
2127218822Sdim				       input_section, relocatable,
2128218822Sdim				       data, gp);
2129218822Sdim  _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, !relocatable,
2130218822Sdim				 location);
2131179407Sobrien
2132218822Sdim  return ret;
2133179407Sobrien}
2134179407Sobrien
2135179407Sobrien/* A mapping from BFD reloc types to MIPS ELF reloc types.  */
2136179407Sobrien
2137179407Sobrienstruct elf_reloc_map {
2138179407Sobrien  bfd_reloc_code_real_type bfd_val;
2139179407Sobrien  enum elf_mips_reloc_type elf_val;
2140179407Sobrien};
2141179407Sobrien
2142179407Sobrienstatic const struct elf_reloc_map mips_reloc_map[] =
2143179407Sobrien{
2144179407Sobrien  { BFD_RELOC_NONE, R_MIPS_NONE },
2145179407Sobrien  { BFD_RELOC_16, R_MIPS_16 },
2146179407Sobrien  { BFD_RELOC_32, R_MIPS_32 },
2147179407Sobrien  /* There is no BFD reloc for R_MIPS_REL32.  */
2148179407Sobrien  { BFD_RELOC_64, R_MIPS_64 },
2149179407Sobrien  { BFD_RELOC_CTOR, R_MIPS_64 },
2150218822Sdim  { BFD_RELOC_16_PCREL_S2, R_MIPS_PC16 },
2151179407Sobrien  { BFD_RELOC_HI16_S, R_MIPS_HI16 },
2152179407Sobrien  { BFD_RELOC_LO16, R_MIPS_LO16 },
2153179407Sobrien  { BFD_RELOC_GPREL16, R_MIPS_GPREL16 },
2154179407Sobrien  { BFD_RELOC_GPREL32, R_MIPS_GPREL32 },
2155179407Sobrien  { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
2156179407Sobrien  { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
2157179407Sobrien  { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
2158179407Sobrien  { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
2159179407Sobrien  { BFD_RELOC_MIPS_SHIFT5, R_MIPS_SHIFT5 },
2160179407Sobrien  { BFD_RELOC_MIPS_SHIFT6, R_MIPS_SHIFT6 },
2161179407Sobrien  { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP },
2162179407Sobrien  { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
2163179407Sobrien  { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
2164179407Sobrien  { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
2165179407Sobrien  { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
2166179407Sobrien  { BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
2167179407Sobrien  { BFD_RELOC_MIPS_INSERT_A, R_MIPS_INSERT_A },
2168179407Sobrien  { BFD_RELOC_MIPS_INSERT_B, R_MIPS_INSERT_B },
2169179407Sobrien  { BFD_RELOC_MIPS_DELETE, R_MIPS_DELETE },
2170179407Sobrien  { BFD_RELOC_MIPS_HIGHEST, R_MIPS_HIGHEST },
2171179407Sobrien  { BFD_RELOC_MIPS_HIGHER, R_MIPS_HIGHER },
2172179407Sobrien  { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
2173179407Sobrien  { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
2174179407Sobrien  { BFD_RELOC_MIPS_SCN_DISP, R_MIPS_SCN_DISP },
2175179407Sobrien  { BFD_RELOC_MIPS_REL16, R_MIPS_REL16 },
2176179407Sobrien  /* Use of R_MIPS_ADD_IMMEDIATE and R_MIPS_PJUMP is deprecated.  */
2177179407Sobrien  { BFD_RELOC_MIPS_RELGOT, R_MIPS_RELGOT },
2178218822Sdim  { BFD_RELOC_MIPS_JALR, R_MIPS_JALR },
2179218822Sdim  { BFD_RELOC_MIPS_TLS_DTPMOD32, R_MIPS_TLS_DTPMOD32 },
2180218822Sdim  { BFD_RELOC_MIPS_TLS_DTPREL32, R_MIPS_TLS_DTPREL32 },
2181218822Sdim  { BFD_RELOC_MIPS_TLS_DTPMOD64, R_MIPS_TLS_DTPMOD64 },
2182218822Sdim  { BFD_RELOC_MIPS_TLS_DTPREL64, R_MIPS_TLS_DTPREL64 },
2183218822Sdim  { BFD_RELOC_MIPS_TLS_GD, R_MIPS_TLS_GD },
2184218822Sdim  { BFD_RELOC_MIPS_TLS_LDM, R_MIPS_TLS_LDM },
2185218822Sdim  { BFD_RELOC_MIPS_TLS_DTPREL_HI16, R_MIPS_TLS_DTPREL_HI16 },
2186218822Sdim  { BFD_RELOC_MIPS_TLS_DTPREL_LO16, R_MIPS_TLS_DTPREL_LO16 },
2187218822Sdim  { BFD_RELOC_MIPS_TLS_GOTTPREL, R_MIPS_TLS_GOTTPREL },
2188218822Sdim  { BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 },
2189218822Sdim  { BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 },
2190218822Sdim  { BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 },
2191218822Sdim  { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }
2192179407Sobrien};
2193179407Sobrien
2194218822Sdimstatic const struct elf_reloc_map mips16_reloc_map[] =
2195218822Sdim{
2196218822Sdim  { BFD_RELOC_MIPS16_JMP, R_MIPS16_26 - R_MIPS16_min },
2197218822Sdim  { BFD_RELOC_MIPS16_GPREL, R_MIPS16_GPREL - R_MIPS16_min },
2198218822Sdim  { BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min },
2199218822Sdim  { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min },
2200218822Sdim};
2201218822Sdim
2202179407Sobrien/* Given a BFD reloc type, return a howto structure.  */
2203179407Sobrien
2204179407Sobrienstatic reloc_howto_type *
2205179407Sobrienbfd_elf64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
2206179407Sobrien				 bfd_reloc_code_real_type code)
2207179407Sobrien{
2208179407Sobrien  unsigned int i;
2209179407Sobrien  /* FIXME: We default to RELA here instead of choosing the right
2210179407Sobrien     relocation variant.  */
2211179407Sobrien  reloc_howto_type *howto_table = mips_elf64_howto_table_rela;
2212218822Sdim  reloc_howto_type *howto16_table = mips16_elf64_howto_table_rela;
2213179407Sobrien
2214179407Sobrien  for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map);
2215179407Sobrien       i++)
2216179407Sobrien    {
2217179407Sobrien      if (mips_reloc_map[i].bfd_val == code)
2218179407Sobrien	return &howto_table[(int) mips_reloc_map[i].elf_val];
2219179407Sobrien    }
2220179407Sobrien
2221218822Sdim  for (i = 0; i < sizeof (mips16_reloc_map) / sizeof (struct elf_reloc_map);
2222218822Sdim       i++)
2223218822Sdim    {
2224218822Sdim      if (mips16_reloc_map[i].bfd_val == code)
2225218822Sdim	return &howto16_table[(int) mips16_reloc_map[i].elf_val];
2226218822Sdim    }
2227218822Sdim
2228179407Sobrien  switch (code)
2229179407Sobrien    {
2230179407Sobrien    case BFD_RELOC_VTABLE_INHERIT:
2231179407Sobrien      return &elf_mips_gnu_vtinherit_howto;
2232179407Sobrien    case BFD_RELOC_VTABLE_ENTRY:
2233179407Sobrien      return &elf_mips_gnu_vtentry_howto;
2234179407Sobrien    default:
2235179407Sobrien      bfd_set_error (bfd_error_bad_value);
2236179407Sobrien      return NULL;
2237179407Sobrien    }
2238179407Sobrien}
2239179407Sobrien
2240218822Sdimstatic reloc_howto_type *
2241218822Sdimbfd_elf64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
2242218822Sdim				 const char *r_name)
2243218822Sdim{
2244218822Sdim  unsigned int i;
2245218822Sdim
2246218822Sdim  for (i = 0;
2247218822Sdim       i < (sizeof (mips_elf64_howto_table_rela)
2248218822Sdim	    / sizeof (mips_elf64_howto_table_rela[0])); i++)
2249218822Sdim    if (mips_elf64_howto_table_rela[i].name != NULL
2250218822Sdim	&& strcasecmp (mips_elf64_howto_table_rela[i].name, r_name) == 0)
2251218822Sdim      return &mips_elf64_howto_table_rela[i];
2252218822Sdim
2253218822Sdim  for (i = 0;
2254218822Sdim       i < (sizeof (mips16_elf64_howto_table_rela)
2255218822Sdim	    / sizeof (mips16_elf64_howto_table_rela[0]));
2256218822Sdim       i++)
2257218822Sdim    if (mips16_elf64_howto_table_rela[i].name != NULL
2258218822Sdim	&& strcasecmp (mips16_elf64_howto_table_rela[i].name, r_name) == 0)
2259218822Sdim      return &mips16_elf64_howto_table_rela[i];
2260218822Sdim
2261218822Sdim  if (strcasecmp (elf_mips_gnu_vtinherit_howto.name, r_name) == 0)
2262218822Sdim    return &elf_mips_gnu_vtinherit_howto;
2263218822Sdim  if (strcasecmp (elf_mips_gnu_vtentry_howto.name, r_name) == 0)
2264218822Sdim    return &elf_mips_gnu_vtentry_howto;
2265218822Sdim  if (strcasecmp (elf_mips_gnu_rel16_s2.name, r_name) == 0)
2266218822Sdim    return &elf_mips_gnu_rel16_s2;
2267218822Sdim  if (strcasecmp (elf_mips_gnu_rela16_s2.name, r_name) == 0)
2268218822Sdim    return &elf_mips_gnu_rela16_s2;
2269218822Sdim
2270218822Sdim  return NULL;
2271218822Sdim}
2272218822Sdim
2273179407Sobrien/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure.  */
2274179407Sobrien
2275179407Sobrienstatic reloc_howto_type *
2276179407Sobrienmips_elf64_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p)
2277179407Sobrien{
2278179407Sobrien  switch (r_type)
2279179407Sobrien    {
2280179407Sobrien    case R_MIPS_GNU_VTINHERIT:
2281179407Sobrien      return &elf_mips_gnu_vtinherit_howto;
2282179407Sobrien    case R_MIPS_GNU_VTENTRY:
2283179407Sobrien      return &elf_mips_gnu_vtentry_howto;
2284179407Sobrien    case R_MIPS_GNU_REL16_S2:
2285179407Sobrien      if (rela_p)
2286179407Sobrien	return &elf_mips_gnu_rela16_s2;
2287179407Sobrien      else
2288179407Sobrien	return &elf_mips_gnu_rel16_s2;
2289179407Sobrien    default:
2290218822Sdim      if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
2291218822Sdim	{
2292218822Sdim	  if (rela_p)
2293218822Sdim	    return &mips16_elf64_howto_table_rela[r_type - R_MIPS16_min];
2294218822Sdim	  else
2295218822Sdim	    return &mips16_elf64_howto_table_rel[r_type - R_MIPS16_min];
2296218822Sdim	}
2297179407Sobrien      BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
2298179407Sobrien      if (rela_p)
2299179407Sobrien	return &mips_elf64_howto_table_rela[r_type];
2300179407Sobrien      else
2301179407Sobrien	return &mips_elf64_howto_table_rel[r_type];
2302179407Sobrien      break;
2303179407Sobrien    }
2304179407Sobrien}
2305179407Sobrien
2306179407Sobrien/* Prevent relocation handling by bfd for MIPS ELF64.  */
2307179407Sobrien
2308179407Sobrienstatic void
2309179407Sobrienmips_elf64_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
2310179407Sobrien			      arelent *cache_ptr ATTRIBUTE_UNUSED,
2311179407Sobrien			      Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
2312179407Sobrien{
2313179407Sobrien  BFD_ASSERT (0);
2314179407Sobrien}
2315179407Sobrien
2316179407Sobrienstatic void
2317179407Sobrienmips_elf64_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
2318179407Sobrien			       arelent *cache_ptr ATTRIBUTE_UNUSED,
2319179407Sobrien			       Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
2320179407Sobrien{
2321179407Sobrien  BFD_ASSERT (0);
2322179407Sobrien}
2323179407Sobrien
2324179407Sobrien/* Since each entry in an SHT_REL or SHT_RELA section can represent up
2325179407Sobrien   to three relocs, we must tell the user to allocate more space.  */
2326179407Sobrien
2327179407Sobrienstatic long
2328179407Sobrienmips_elf64_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
2329179407Sobrien{
2330179407Sobrien  return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
2331179407Sobrien}
2332179407Sobrien
2333179407Sobrienstatic long
2334179407Sobrienmips_elf64_get_dynamic_reloc_upper_bound (bfd *abfd)
2335179407Sobrien{
2336179407Sobrien  return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 3;
2337179407Sobrien}
2338179407Sobrien
2339179407Sobrien/* We must also copy more relocations than the corresponding functions
2340179407Sobrien   in elf.c would, so the two following functions are slightly
2341179407Sobrien   modified from elf.c, that multiply the external relocation count by
2342179407Sobrien   3 to obtain the internal relocation count.  */
2343179407Sobrien
2344179407Sobrienstatic long
2345179407Sobrienmips_elf64_canonicalize_reloc (bfd *abfd, sec_ptr section,
2346179407Sobrien			       arelent **relptr, asymbol **symbols)
2347179407Sobrien{
2348179407Sobrien  arelent *tblptr;
2349179407Sobrien  unsigned int i;
2350179407Sobrien  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
2351179407Sobrien
2352179407Sobrien  if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
2353179407Sobrien    return -1;
2354179407Sobrien
2355179407Sobrien  tblptr = section->relocation;
2356179407Sobrien  for (i = 0; i < section->reloc_count * 3; i++)
2357179407Sobrien    *relptr++ = tblptr++;
2358179407Sobrien
2359179407Sobrien  *relptr = NULL;
2360179407Sobrien
2361179407Sobrien  return section->reloc_count * 3;
2362179407Sobrien}
2363179407Sobrien
2364179407Sobrienstatic long
2365179407Sobrienmips_elf64_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage,
2366179407Sobrien				       asymbol **syms)
2367179407Sobrien{
2368179407Sobrien  bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
2369179407Sobrien  asection *s;
2370179407Sobrien  long ret;
2371179407Sobrien
2372179407Sobrien  if (elf_dynsymtab (abfd) == 0)
2373179407Sobrien    {
2374179407Sobrien      bfd_set_error (bfd_error_invalid_operation);
2375179407Sobrien      return -1;
2376179407Sobrien    }
2377179407Sobrien
2378179407Sobrien  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
2379179407Sobrien  ret = 0;
2380179407Sobrien  for (s = abfd->sections; s != NULL; s = s->next)
2381179407Sobrien    {
2382179407Sobrien      if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
2383179407Sobrien	  && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
2384179407Sobrien	      || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
2385179407Sobrien	{
2386179407Sobrien	  arelent *p;
2387179407Sobrien	  long count, i;
2388179407Sobrien
2389179407Sobrien	  if (! (*slurp_relocs) (abfd, s, syms, TRUE))
2390179407Sobrien	    return -1;
2391218822Sdim	  count = s->size / elf_section_data (s)->this_hdr.sh_entsize * 3;
2392179407Sobrien	  p = s->relocation;
2393179407Sobrien	  for (i = 0; i < count; i++)
2394179407Sobrien	    *storage++ = p++;
2395179407Sobrien	  ret += count;
2396179407Sobrien	}
2397179407Sobrien    }
2398179407Sobrien
2399179407Sobrien  *storage = NULL;
2400179407Sobrien
2401179407Sobrien  return ret;
2402179407Sobrien}
2403179407Sobrien
2404179407Sobrien/* Read the relocations from one reloc section.  This is mostly copied
2405179407Sobrien   from elfcode.h, except for the changes to expand one external
2406179407Sobrien   relocation to 3 internal ones.  We must unfortunately set
2407179407Sobrien   reloc_count to the number of external relocations, because a lot of
2408179407Sobrien   generic code seems to depend on this.  */
2409179407Sobrien
2410179407Sobrienstatic bfd_boolean
2411179407Sobrienmips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
2412179407Sobrien				  Elf_Internal_Shdr *rel_hdr,
2413179407Sobrien				  bfd_size_type reloc_count,
2414179407Sobrien				  arelent *relents, asymbol **symbols,
2415179407Sobrien				  bfd_boolean dynamic)
2416179407Sobrien{
2417179407Sobrien  void *allocated;
2418179407Sobrien  bfd_byte *native_relocs;
2419179407Sobrien  arelent *relent;
2420179407Sobrien  bfd_vma i;
2421179407Sobrien  int entsize;
2422179407Sobrien  bfd_boolean rela_p;
2423179407Sobrien
2424179407Sobrien  allocated = bfd_malloc (rel_hdr->sh_size);
2425179407Sobrien  if (allocated == NULL)
2426179407Sobrien    return FALSE;
2427179407Sobrien
2428179407Sobrien  if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
2429179407Sobrien      || (bfd_bread (allocated, rel_hdr->sh_size, abfd)
2430179407Sobrien	  != rel_hdr->sh_size))
2431179407Sobrien    goto error_return;
2432179407Sobrien
2433179407Sobrien  native_relocs = allocated;
2434179407Sobrien
2435179407Sobrien  entsize = rel_hdr->sh_entsize;
2436179407Sobrien  BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
2437179407Sobrien	      || entsize == sizeof (Elf64_Mips_External_Rela));
2438179407Sobrien
2439179407Sobrien  if (entsize == sizeof (Elf64_Mips_External_Rel))
2440179407Sobrien    rela_p = FALSE;
2441179407Sobrien  else
2442179407Sobrien    rela_p = TRUE;
2443179407Sobrien
2444179407Sobrien  for (i = 0, relent = relents;
2445179407Sobrien       i < reloc_count;
2446179407Sobrien       i++, native_relocs += entsize)
2447179407Sobrien    {
2448179407Sobrien      Elf64_Mips_Internal_Rela rela;
2449179407Sobrien      bfd_boolean used_sym, used_ssym;
2450179407Sobrien      int ir;
2451179407Sobrien
2452179407Sobrien      if (entsize == sizeof (Elf64_Mips_External_Rela))
2453179407Sobrien	mips_elf64_swap_reloca_in (abfd,
2454179407Sobrien				   (Elf64_Mips_External_Rela *) native_relocs,
2455179407Sobrien				   &rela);
2456179407Sobrien      else
2457179407Sobrien	mips_elf64_swap_reloc_in (abfd,
2458179407Sobrien				  (Elf64_Mips_External_Rel *) native_relocs,
2459179407Sobrien				  &rela);
2460179407Sobrien
2461179407Sobrien      /* Each entry represents exactly three actual relocations.  */
2462179407Sobrien
2463179407Sobrien      used_sym = FALSE;
2464179407Sobrien      used_ssym = FALSE;
2465179407Sobrien      for (ir = 0; ir < 3; ir++)
2466179407Sobrien	{
2467179407Sobrien	  enum elf_mips_reloc_type type;
2468179407Sobrien
2469179407Sobrien	  switch (ir)
2470179407Sobrien	    {
2471179407Sobrien	    default:
2472179407Sobrien	      abort ();
2473179407Sobrien	    case 0:
2474179407Sobrien	      type = (enum elf_mips_reloc_type) rela.r_type;
2475179407Sobrien	      break;
2476179407Sobrien	    case 1:
2477179407Sobrien	      type = (enum elf_mips_reloc_type) rela.r_type2;
2478179407Sobrien	      break;
2479179407Sobrien	    case 2:
2480179407Sobrien	      type = (enum elf_mips_reloc_type) rela.r_type3;
2481179407Sobrien	      break;
2482179407Sobrien	    }
2483179407Sobrien
2484179407Sobrien	  /* Some types require symbols, whereas some do not.  */
2485179407Sobrien	  switch (type)
2486179407Sobrien	    {
2487179407Sobrien	    case R_MIPS_NONE:
2488179407Sobrien	    case R_MIPS_LITERAL:
2489179407Sobrien	    case R_MIPS_INSERT_A:
2490179407Sobrien	    case R_MIPS_INSERT_B:
2491179407Sobrien	    case R_MIPS_DELETE:
2492179407Sobrien	      relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2493179407Sobrien	      break;
2494179407Sobrien
2495179407Sobrien	    default:
2496179407Sobrien	      if (! used_sym)
2497179407Sobrien		{
2498179407Sobrien		  if (rela.r_sym == 0)
2499179407Sobrien		    relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2500179407Sobrien		  else
2501179407Sobrien		    {
2502179407Sobrien		      asymbol **ps, *s;
2503179407Sobrien
2504179407Sobrien		      ps = symbols + rela.r_sym - 1;
2505179407Sobrien		      s = *ps;
2506179407Sobrien		      if ((s->flags & BSF_SECTION_SYM) == 0)
2507179407Sobrien			relent->sym_ptr_ptr = ps;
2508179407Sobrien		      else
2509179407Sobrien			relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
2510179407Sobrien		    }
2511179407Sobrien
2512179407Sobrien		  used_sym = TRUE;
2513179407Sobrien		}
2514179407Sobrien	      else if (! used_ssym)
2515179407Sobrien		{
2516179407Sobrien		  switch (rela.r_ssym)
2517179407Sobrien		    {
2518179407Sobrien		    case RSS_UNDEF:
2519179407Sobrien		      relent->sym_ptr_ptr =
2520179407Sobrien			bfd_abs_section_ptr->symbol_ptr_ptr;
2521179407Sobrien		      break;
2522179407Sobrien
2523179407Sobrien		    case RSS_GP:
2524179407Sobrien		    case RSS_GP0:
2525179407Sobrien		    case RSS_LOC:
2526179407Sobrien		      /* FIXME: I think these need to be handled using
2527218822Sdim			 special howto structures.  */
2528179407Sobrien		      BFD_ASSERT (0);
2529179407Sobrien		      break;
2530179407Sobrien
2531179407Sobrien		    default:
2532179407Sobrien		      BFD_ASSERT (0);
2533179407Sobrien		      break;
2534179407Sobrien		    }
2535179407Sobrien
2536179407Sobrien		  used_ssym = TRUE;
2537179407Sobrien		}
2538179407Sobrien	      else
2539179407Sobrien		relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
2540179407Sobrien
2541179407Sobrien	      break;
2542179407Sobrien	    }
2543179407Sobrien
2544179407Sobrien	  /* The address of an ELF reloc is section relative for an
2545179407Sobrien	     object file, and absolute for an executable file or
2546179407Sobrien	     shared library.  The address of a BFD reloc is always
2547179407Sobrien	     section relative.  */
2548179407Sobrien	  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
2549179407Sobrien	    relent->address = rela.r_offset;
2550179407Sobrien	  else
2551179407Sobrien	    relent->address = rela.r_offset - asect->vma;
2552179407Sobrien
2553179407Sobrien	  relent->addend = rela.r_addend;
2554179407Sobrien
2555179407Sobrien	  relent->howto = mips_elf64_rtype_to_howto (type, rela_p);
2556179407Sobrien
2557179407Sobrien	  ++relent;
2558179407Sobrien	}
2559179407Sobrien    }
2560179407Sobrien
2561179407Sobrien  asect->reloc_count += (relent - relents) / 3;
2562179407Sobrien
2563179407Sobrien  if (allocated != NULL)
2564179407Sobrien    free (allocated);
2565179407Sobrien
2566179407Sobrien  return TRUE;
2567179407Sobrien
2568179407Sobrien error_return:
2569179407Sobrien  if (allocated != NULL)
2570179407Sobrien    free (allocated);
2571179407Sobrien  return FALSE;
2572179407Sobrien}
2573179407Sobrien
2574179407Sobrien/* Read the relocations.  On Irix 6, there can be two reloc sections
2575179407Sobrien   associated with a single data section.  This is copied from
2576179407Sobrien   elfcode.h as well, with changes as small as accounting for 3
2577179407Sobrien   internal relocs per external reloc and resetting reloc_count to
2578179407Sobrien   zero before processing the relocs of a section.  */
2579179407Sobrien
2580179407Sobrienstatic bfd_boolean
2581179407Sobrienmips_elf64_slurp_reloc_table (bfd *abfd, asection *asect,
2582179407Sobrien			      asymbol **symbols, bfd_boolean dynamic)
2583179407Sobrien{
2584179407Sobrien  struct bfd_elf_section_data * const d = elf_section_data (asect);
2585179407Sobrien  Elf_Internal_Shdr *rel_hdr;
2586179407Sobrien  Elf_Internal_Shdr *rel_hdr2;
2587179407Sobrien  bfd_size_type reloc_count;
2588179407Sobrien  bfd_size_type reloc_count2;
2589179407Sobrien  arelent *relents;
2590179407Sobrien  bfd_size_type amt;
2591179407Sobrien
2592179407Sobrien  if (asect->relocation != NULL)
2593179407Sobrien    return TRUE;
2594179407Sobrien
2595179407Sobrien  if (! dynamic)
2596179407Sobrien    {
2597179407Sobrien      if ((asect->flags & SEC_RELOC) == 0
2598179407Sobrien	  || asect->reloc_count == 0)
2599179407Sobrien	return TRUE;
2600179407Sobrien
2601179407Sobrien      rel_hdr = &d->rel_hdr;
2602179407Sobrien      reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
2603179407Sobrien      rel_hdr2 = d->rel_hdr2;
2604179407Sobrien      reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0);
2605179407Sobrien
2606179407Sobrien      BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
2607179407Sobrien      BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
2608179407Sobrien		  || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
2609179407Sobrien
2610179407Sobrien    }
2611179407Sobrien  else
2612179407Sobrien    {
2613179407Sobrien      /* Note that ASECT->RELOC_COUNT tends not to be accurate in this
2614179407Sobrien	 case because relocations against this section may use the
2615179407Sobrien	 dynamic symbol table, and in that case bfd_section_from_shdr
2616179407Sobrien	 in elf.c does not update the RELOC_COUNT.  */
2617218822Sdim      if (asect->size == 0)
2618179407Sobrien	return TRUE;
2619179407Sobrien
2620179407Sobrien      rel_hdr = &d->this_hdr;
2621179407Sobrien      reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
2622179407Sobrien      rel_hdr2 = NULL;
2623179407Sobrien      reloc_count2 = 0;
2624179407Sobrien    }
2625179407Sobrien
2626179407Sobrien  /* Allocate space for 3 arelent structures for each Rel structure.  */
2627179407Sobrien  amt = (reloc_count + reloc_count2) * 3 * sizeof (arelent);
2628179407Sobrien  relents = bfd_alloc (abfd, amt);
2629179407Sobrien  if (relents == NULL)
2630179407Sobrien    return FALSE;
2631179407Sobrien
2632179407Sobrien  /* The slurp_one_reloc_table routine increments reloc_count.  */
2633179407Sobrien  asect->reloc_count = 0;
2634179407Sobrien
2635179407Sobrien  if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
2636179407Sobrien					  rel_hdr, reloc_count,
2637179407Sobrien					  relents,
2638179407Sobrien					  symbols, dynamic))
2639179407Sobrien    return FALSE;
2640179407Sobrien  if (d->rel_hdr2 != NULL)
2641179407Sobrien    {
2642179407Sobrien      if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
2643179407Sobrien					      rel_hdr2, reloc_count2,
2644179407Sobrien					      relents + reloc_count * 3,
2645179407Sobrien					      symbols, dynamic))
2646179407Sobrien	return FALSE;
2647179407Sobrien    }
2648179407Sobrien
2649179407Sobrien  asect->relocation = relents;
2650179407Sobrien  return TRUE;
2651179407Sobrien}
2652179407Sobrien
2653179407Sobrien/* Write out the relocations.  */
2654179407Sobrien
2655179407Sobrienstatic void
2656179407Sobrienmips_elf64_write_relocs (bfd *abfd, asection *sec, void *data)
2657179407Sobrien{
2658179407Sobrien  bfd_boolean *failedp = data;
2659179407Sobrien  int count;
2660179407Sobrien  Elf_Internal_Shdr *rel_hdr;
2661179407Sobrien  unsigned int idx;
2662179407Sobrien
2663179407Sobrien  /* If we have already failed, don't do anything.  */
2664179407Sobrien  if (*failedp)
2665179407Sobrien    return;
2666179407Sobrien
2667179407Sobrien  if ((sec->flags & SEC_RELOC) == 0)
2668179407Sobrien    return;
2669179407Sobrien
2670179407Sobrien  /* The linker backend writes the relocs out itself, and sets the
2671179407Sobrien     reloc_count field to zero to inhibit writing them here.  Also,
2672179407Sobrien     sometimes the SEC_RELOC flag gets set even when there aren't any
2673179407Sobrien     relocs.  */
2674179407Sobrien  if (sec->reloc_count == 0)
2675179407Sobrien    return;
2676179407Sobrien
2677179407Sobrien  /* We can combine up to three relocs that refer to the same address
2678179407Sobrien     if the latter relocs have no associated symbol.  */
2679179407Sobrien  count = 0;
2680179407Sobrien  for (idx = 0; idx < sec->reloc_count; idx++)
2681179407Sobrien    {
2682179407Sobrien      bfd_vma addr;
2683179407Sobrien      unsigned int i;
2684179407Sobrien
2685179407Sobrien      ++count;
2686179407Sobrien
2687179407Sobrien      addr = sec->orelocation[idx]->address;
2688179407Sobrien      for (i = 0; i < 2; i++)
2689179407Sobrien	{
2690179407Sobrien	  arelent *r;
2691179407Sobrien
2692179407Sobrien	  if (idx + 1 >= sec->reloc_count)
2693179407Sobrien	    break;
2694179407Sobrien	  r = sec->orelocation[idx + 1];
2695179407Sobrien	  if (r->address != addr
2696179407Sobrien	      || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2697179407Sobrien	      || (*r->sym_ptr_ptr)->value != 0)
2698179407Sobrien	    break;
2699179407Sobrien
2700179407Sobrien	  /* We can merge the reloc at IDX + 1 with the reloc at IDX.  */
2701179407Sobrien
2702179407Sobrien	  ++idx;
2703179407Sobrien	}
2704179407Sobrien    }
2705179407Sobrien
2706179407Sobrien  rel_hdr = &elf_section_data (sec)->rel_hdr;
2707179407Sobrien
2708179407Sobrien  /* Do the actual relocation.  */
2709179407Sobrien
2710179407Sobrien  if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rel))
2711179407Sobrien    mips_elf64_write_rel (abfd, sec, rel_hdr, &count, data);
2712179407Sobrien  else if (rel_hdr->sh_entsize == sizeof(Elf64_Mips_External_Rela))
2713179407Sobrien    mips_elf64_write_rela (abfd, sec, rel_hdr, &count, data);
2714179407Sobrien  else
2715179407Sobrien    BFD_ASSERT (0);
2716179407Sobrien}
2717179407Sobrien
2718179407Sobrienstatic void
2719179407Sobrienmips_elf64_write_rel (bfd *abfd, asection *sec,
2720179407Sobrien		      Elf_Internal_Shdr *rel_hdr,
2721179407Sobrien		      int *count, void *data)
2722179407Sobrien{
2723179407Sobrien  bfd_boolean *failedp = data;
2724179407Sobrien  Elf64_Mips_External_Rel *ext_rel;
2725179407Sobrien  unsigned int idx;
2726179407Sobrien  asymbol *last_sym = 0;
2727179407Sobrien  int last_sym_idx = 0;
2728179407Sobrien
2729179407Sobrien  rel_hdr->sh_size = rel_hdr->sh_entsize * *count;
2730179407Sobrien  rel_hdr->contents = bfd_alloc (abfd, rel_hdr->sh_size);
2731179407Sobrien  if (rel_hdr->contents == NULL)
2732179407Sobrien    {
2733179407Sobrien      *failedp = TRUE;
2734179407Sobrien      return;
2735179407Sobrien    }
2736179407Sobrien
2737179407Sobrien  ext_rel = (Elf64_Mips_External_Rel *) rel_hdr->contents;
2738179407Sobrien  for (idx = 0; idx < sec->reloc_count; idx++, ext_rel++)
2739179407Sobrien    {
2740179407Sobrien      arelent *ptr;
2741179407Sobrien      Elf64_Mips_Internal_Rela int_rel;
2742179407Sobrien      asymbol *sym;
2743179407Sobrien      int n;
2744179407Sobrien      unsigned int i;
2745179407Sobrien
2746179407Sobrien      ptr = sec->orelocation[idx];
2747179407Sobrien
2748179407Sobrien      /* The address of an ELF reloc is section relative for an object
2749179407Sobrien	 file, and absolute for an executable file or shared library.
2750179407Sobrien	 The address of a BFD reloc is always section relative.  */
2751179407Sobrien      if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2752179407Sobrien	int_rel.r_offset = ptr->address;
2753179407Sobrien      else
2754179407Sobrien	int_rel.r_offset = ptr->address + sec->vma;
2755179407Sobrien
2756179407Sobrien      sym = *ptr->sym_ptr_ptr;
2757179407Sobrien      if (sym == last_sym)
2758179407Sobrien	n = last_sym_idx;
2759218822Sdim      else if (bfd_is_abs_section (sym->section) && sym->value == 0)
2760218822Sdim	n = STN_UNDEF;
2761179407Sobrien      else
2762179407Sobrien	{
2763179407Sobrien	  last_sym = sym;
2764179407Sobrien	  n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2765179407Sobrien	  if (n < 0)
2766179407Sobrien	    {
2767179407Sobrien	      *failedp = TRUE;
2768179407Sobrien	      return;
2769179407Sobrien	    }
2770179407Sobrien	  last_sym_idx = n;
2771179407Sobrien	}
2772179407Sobrien
2773179407Sobrien      int_rel.r_sym = n;
2774179407Sobrien      int_rel.r_ssym = RSS_UNDEF;
2775179407Sobrien
2776179407Sobrien      if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2777179407Sobrien	  && ! _bfd_elf_validate_reloc (abfd, ptr))
2778179407Sobrien	{
2779179407Sobrien	  *failedp = TRUE;
2780179407Sobrien	  return;
2781179407Sobrien	}
2782179407Sobrien
2783179407Sobrien      int_rel.r_type = ptr->howto->type;
2784179407Sobrien      int_rel.r_type2 = (int) R_MIPS_NONE;
2785179407Sobrien      int_rel.r_type3 = (int) R_MIPS_NONE;
2786179407Sobrien
2787179407Sobrien      for (i = 0; i < 2; i++)
2788179407Sobrien	{
2789179407Sobrien	  arelent *r;
2790179407Sobrien
2791179407Sobrien	  if (idx + 1 >= sec->reloc_count)
2792179407Sobrien	    break;
2793179407Sobrien	  r = sec->orelocation[idx + 1];
2794179407Sobrien	  if (r->address != ptr->address
2795179407Sobrien	      || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2796179407Sobrien	      || (*r->sym_ptr_ptr)->value != 0)
2797179407Sobrien	    break;
2798179407Sobrien
2799179407Sobrien	  /* We can merge the reloc at IDX + 1 with the reloc at IDX.  */
2800179407Sobrien
2801179407Sobrien	  if (i == 0)
2802179407Sobrien	    int_rel.r_type2 = r->howto->type;
2803179407Sobrien	  else
2804179407Sobrien	    int_rel.r_type3 = r->howto->type;
2805179407Sobrien
2806179407Sobrien	  ++idx;
2807179407Sobrien	}
2808179407Sobrien
2809179407Sobrien      mips_elf64_swap_reloc_out (abfd, &int_rel, ext_rel);
2810179407Sobrien    }
2811179407Sobrien
2812179407Sobrien  BFD_ASSERT (ext_rel - (Elf64_Mips_External_Rel *) rel_hdr->contents
2813179407Sobrien	      == *count);
2814179407Sobrien}
2815179407Sobrien
2816179407Sobrienstatic void
2817179407Sobrienmips_elf64_write_rela (bfd *abfd, asection *sec,
2818179407Sobrien		       Elf_Internal_Shdr *rela_hdr,
2819179407Sobrien		       int *count, void *data)
2820179407Sobrien{
2821179407Sobrien  bfd_boolean *failedp = data;
2822179407Sobrien  Elf64_Mips_External_Rela *ext_rela;
2823179407Sobrien  unsigned int idx;
2824179407Sobrien  asymbol *last_sym = 0;
2825179407Sobrien  int last_sym_idx = 0;
2826179407Sobrien
2827179407Sobrien  rela_hdr->sh_size = rela_hdr->sh_entsize * *count;
2828179407Sobrien  rela_hdr->contents = bfd_alloc (abfd, rela_hdr->sh_size);
2829179407Sobrien  if (rela_hdr->contents == NULL)
2830179407Sobrien    {
2831179407Sobrien      *failedp = TRUE;
2832179407Sobrien      return;
2833179407Sobrien    }
2834179407Sobrien
2835179407Sobrien  ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents;
2836179407Sobrien  for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++)
2837179407Sobrien    {
2838179407Sobrien      arelent *ptr;
2839179407Sobrien      Elf64_Mips_Internal_Rela int_rela;
2840179407Sobrien      asymbol *sym;
2841179407Sobrien      int n;
2842179407Sobrien      unsigned int i;
2843179407Sobrien
2844179407Sobrien      ptr = sec->orelocation[idx];
2845179407Sobrien
2846179407Sobrien      /* The address of an ELF reloc is section relative for an object
2847179407Sobrien	 file, and absolute for an executable file or shared library.
2848179407Sobrien	 The address of a BFD reloc is always section relative.  */
2849179407Sobrien      if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
2850179407Sobrien	int_rela.r_offset = ptr->address;
2851179407Sobrien      else
2852179407Sobrien	int_rela.r_offset = ptr->address + sec->vma;
2853179407Sobrien
2854179407Sobrien      sym = *ptr->sym_ptr_ptr;
2855179407Sobrien      if (sym == last_sym)
2856179407Sobrien	n = last_sym_idx;
2857218822Sdim      else if (bfd_is_abs_section (sym->section) && sym->value == 0)
2858218822Sdim	n = STN_UNDEF;
2859179407Sobrien      else
2860179407Sobrien	{
2861179407Sobrien	  last_sym = sym;
2862179407Sobrien	  n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
2863179407Sobrien	  if (n < 0)
2864179407Sobrien	    {
2865179407Sobrien	      *failedp = TRUE;
2866179407Sobrien	      return;
2867179407Sobrien	    }
2868179407Sobrien	  last_sym_idx = n;
2869179407Sobrien	}
2870179407Sobrien
2871179407Sobrien      int_rela.r_sym = n;
2872179407Sobrien      int_rela.r_addend = ptr->addend;
2873179407Sobrien      int_rela.r_ssym = RSS_UNDEF;
2874179407Sobrien
2875179407Sobrien      if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
2876179407Sobrien	  && ! _bfd_elf_validate_reloc (abfd, ptr))
2877179407Sobrien	{
2878179407Sobrien	  *failedp = TRUE;
2879179407Sobrien	  return;
2880179407Sobrien	}
2881179407Sobrien
2882179407Sobrien      int_rela.r_type = ptr->howto->type;
2883179407Sobrien      int_rela.r_type2 = (int) R_MIPS_NONE;
2884179407Sobrien      int_rela.r_type3 = (int) R_MIPS_NONE;
2885179407Sobrien
2886179407Sobrien      for (i = 0; i < 2; i++)
2887179407Sobrien	{
2888179407Sobrien	  arelent *r;
2889179407Sobrien
2890179407Sobrien	  if (idx + 1 >= sec->reloc_count)
2891179407Sobrien	    break;
2892179407Sobrien	  r = sec->orelocation[idx + 1];
2893179407Sobrien	  if (r->address != ptr->address
2894179407Sobrien	      || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
2895179407Sobrien	      || (*r->sym_ptr_ptr)->value != 0)
2896179407Sobrien	    break;
2897179407Sobrien
2898179407Sobrien	  /* We can merge the reloc at IDX + 1 with the reloc at IDX.  */
2899179407Sobrien
2900179407Sobrien	  if (i == 0)
2901179407Sobrien	    int_rela.r_type2 = r->howto->type;
2902179407Sobrien	  else
2903179407Sobrien	    int_rela.r_type3 = r->howto->type;
2904179407Sobrien
2905179407Sobrien	  ++idx;
2906179407Sobrien	}
2907179407Sobrien
2908179407Sobrien      mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela);
2909179407Sobrien    }
2910179407Sobrien
2911179407Sobrien  BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents
2912179407Sobrien	      == *count);
2913179407Sobrien}
2914179407Sobrien
2915179407Sobrien/* Set the right machine number for a MIPS ELF file.  */
2916179407Sobrien
2917179407Sobrienstatic bfd_boolean
2918179407Sobrienmips_elf64_object_p (bfd *abfd)
2919179407Sobrien{
2920179407Sobrien  unsigned long mach;
2921179407Sobrien
2922179407Sobrien  /* Irix 6 is broken.  Object file symbol tables are not always
2923179407Sobrien     sorted correctly such that local symbols precede global symbols,
2924179407Sobrien     and the sh_info field in the symbol table is not always right.  */
2925179407Sobrien  if (elf64_mips_irix_compat (abfd) != ict_none)
2926179407Sobrien    elf_bad_symtab (abfd) = TRUE;
2927179407Sobrien
2928179407Sobrien  mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags);
2929179407Sobrien  bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach);
2930179407Sobrien  return TRUE;
2931179407Sobrien}
2932179407Sobrien
2933179407Sobrien/* Depending on the target vector we generate some version of Irix
2934179407Sobrien   executables or "normal" MIPS ELF ABI executables.  */
2935179407Sobrienstatic irix_compat_t
2936179407Sobrienelf64_mips_irix_compat (bfd *abfd)
2937179407Sobrien{
2938179407Sobrien  if ((abfd->xvec == &bfd_elf64_bigmips_vec)
2939179407Sobrien      || (abfd->xvec == &bfd_elf64_littlemips_vec))
2940179407Sobrien    return ict_irix6;
2941179407Sobrien  else
2942179407Sobrien    return ict_none;
2943179407Sobrien}
2944179407Sobrien
2945179407Sobrien/* Support for core dump NOTE sections.  */
2946179407Sobrienstatic bfd_boolean
2947179407Sobrienelf64_mips_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
2948179407Sobrien{
2949179407Sobrien  int offset;
2950218822Sdim  unsigned int size;
2951179407Sobrien
2952179407Sobrien  switch (note->descsz)
2953179407Sobrien    {
2954179407Sobrien      default:
2955179407Sobrien	return FALSE;
2956179407Sobrien
2957179407Sobrien      case 480:		/* Linux/MIPS - N64 kernel */
2958179407Sobrien	/* pr_cursig */
2959179407Sobrien	elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
2960179407Sobrien
2961179407Sobrien	/* pr_pid */
2962179407Sobrien	elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 32);
2963179407Sobrien
2964179407Sobrien	/* pr_reg */
2965179407Sobrien	offset = 112;
2966218822Sdim	size = 360;
2967179407Sobrien
2968179407Sobrien	break;
2969179407Sobrien    }
2970179407Sobrien
2971179407Sobrien  /* Make a ".reg/999" section.  */
2972179407Sobrien  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
2973218822Sdim					  size, note->descpos + offset);
2974179407Sobrien}
2975179407Sobrien
2976179407Sobrienstatic bfd_boolean
2977179407Sobrienelf64_mips_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
2978179407Sobrien{
2979179407Sobrien  switch (note->descsz)
2980179407Sobrien    {
2981179407Sobrien      default:
2982179407Sobrien	return FALSE;
2983179407Sobrien
2984179407Sobrien      case 136:		/* Linux/MIPS - N64 kernel elf_prpsinfo */
2985179407Sobrien	elf_tdata (abfd)->core_program
2986179407Sobrien	 = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
2987179407Sobrien	elf_tdata (abfd)->core_command
2988179407Sobrien	 = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
2989179407Sobrien    }
2990179407Sobrien
2991179407Sobrien  /* Note that for some reason, a spurious space is tacked
2992179407Sobrien     onto the end of the args in some (at least one anyway)
2993179407Sobrien     implementations, so strip it off if it exists.  */
2994179407Sobrien
2995179407Sobrien  {
2996179407Sobrien    char *command = elf_tdata (abfd)->core_command;
2997179407Sobrien    int n = strlen (command);
2998179407Sobrien
2999179407Sobrien    if (0 < n && command[n - 1] == ' ')
3000179407Sobrien      command[n - 1] = '\0';
3001179407Sobrien  }
3002179407Sobrien
3003179407Sobrien  return TRUE;
3004179407Sobrien}
3005179407Sobrien
3006179407Sobrien/* ECOFF swapping routines.  These are used when dealing with the
3007179407Sobrien   .mdebug section, which is in the ECOFF debugging format.  */
3008179407Sobrienstatic const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap =
3009179407Sobrien{
3010179407Sobrien  /* Symbol table magic number.  */
3011179407Sobrien  magicSym2,
3012179407Sobrien  /* Alignment of debugging information.  E.g., 4.  */
3013179407Sobrien  8,
3014179407Sobrien  /* Sizes of external symbolic information.  */
3015179407Sobrien  sizeof (struct hdr_ext),
3016179407Sobrien  sizeof (struct dnr_ext),
3017179407Sobrien  sizeof (struct pdr_ext),
3018179407Sobrien  sizeof (struct sym_ext),
3019179407Sobrien  sizeof (struct opt_ext),
3020179407Sobrien  sizeof (struct fdr_ext),
3021179407Sobrien  sizeof (struct rfd_ext),
3022179407Sobrien  sizeof (struct ext_ext),
3023179407Sobrien  /* Functions to swap in external symbolic data.  */
3024179407Sobrien  ecoff_swap_hdr_in,
3025179407Sobrien  ecoff_swap_dnr_in,
3026179407Sobrien  ecoff_swap_pdr_in,
3027179407Sobrien  ecoff_swap_sym_in,
3028179407Sobrien  ecoff_swap_opt_in,
3029179407Sobrien  ecoff_swap_fdr_in,
3030179407Sobrien  ecoff_swap_rfd_in,
3031179407Sobrien  ecoff_swap_ext_in,
3032179407Sobrien  _bfd_ecoff_swap_tir_in,
3033179407Sobrien  _bfd_ecoff_swap_rndx_in,
3034179407Sobrien  /* Functions to swap out external symbolic data.  */
3035179407Sobrien  ecoff_swap_hdr_out,
3036179407Sobrien  ecoff_swap_dnr_out,
3037179407Sobrien  ecoff_swap_pdr_out,
3038179407Sobrien  ecoff_swap_sym_out,
3039179407Sobrien  ecoff_swap_opt_out,
3040179407Sobrien  ecoff_swap_fdr_out,
3041179407Sobrien  ecoff_swap_rfd_out,
3042179407Sobrien  ecoff_swap_ext_out,
3043179407Sobrien  _bfd_ecoff_swap_tir_out,
3044179407Sobrien  _bfd_ecoff_swap_rndx_out,
3045179407Sobrien  /* Function to read in symbolic data.  */
3046179407Sobrien  _bfd_mips_elf_read_ecoff_info
3047179407Sobrien};
3048179407Sobrien
3049179407Sobrien/* Relocations in the 64 bit MIPS ELF ABI are more complex than in
3050179407Sobrien   standard ELF.  This structure is used to redirect the relocation
3051179407Sobrien   handling routines.  */
3052179407Sobrien
3053179407Sobrienconst struct elf_size_info mips_elf64_size_info =
3054179407Sobrien{
3055179407Sobrien  sizeof (Elf64_External_Ehdr),
3056179407Sobrien  sizeof (Elf64_External_Phdr),
3057179407Sobrien  sizeof (Elf64_External_Shdr),
3058179407Sobrien  sizeof (Elf64_Mips_External_Rel),
3059179407Sobrien  sizeof (Elf64_Mips_External_Rela),
3060179407Sobrien  sizeof (Elf64_External_Sym),
3061179407Sobrien  sizeof (Elf64_External_Dyn),
3062179407Sobrien  sizeof (Elf_External_Note),
3063218822Sdim  4,		/* hash-table entry size */
3064218822Sdim  3,		/* internal relocations per external relocations */
3065179407Sobrien  64,		/* arch_size */
3066179407Sobrien  3,		/* log_file_align */
3067179407Sobrien  ELFCLASS64,
3068179407Sobrien  EV_CURRENT,
3069179407Sobrien  bfd_elf64_write_out_phdrs,
3070179407Sobrien  bfd_elf64_write_shdrs_and_ehdr,
3071179407Sobrien  mips_elf64_write_relocs,
3072179407Sobrien  bfd_elf64_swap_symbol_in,
3073179407Sobrien  bfd_elf64_swap_symbol_out,
3074179407Sobrien  mips_elf64_slurp_reloc_table,
3075179407Sobrien  bfd_elf64_slurp_symbol_table,
3076179407Sobrien  bfd_elf64_swap_dyn_in,
3077179407Sobrien  bfd_elf64_swap_dyn_out,
3078179407Sobrien  mips_elf64_be_swap_reloc_in,
3079179407Sobrien  mips_elf64_be_swap_reloc_out,
3080179407Sobrien  mips_elf64_be_swap_reloca_in,
3081179407Sobrien  mips_elf64_be_swap_reloca_out
3082179407Sobrien};
3083179407Sobrien
3084179407Sobrien#define ELF_ARCH			bfd_arch_mips
3085179407Sobrien#define ELF_MACHINE_CODE		EM_MIPS
3086179407Sobrien
3087179407Sobrien#define elf_backend_collect		TRUE
3088179407Sobrien#define elf_backend_type_change_ok	TRUE
3089179407Sobrien#define elf_backend_can_gc_sections	TRUE
3090179407Sobrien#define elf_info_to_howto		mips_elf64_info_to_howto_rela
3091179407Sobrien#define elf_info_to_howto_rel		mips_elf64_info_to_howto_rel
3092179407Sobrien#define elf_backend_object_p		mips_elf64_object_p
3093179407Sobrien#define elf_backend_symbol_processing	_bfd_mips_elf_symbol_processing
3094179407Sobrien#define elf_backend_section_processing	_bfd_mips_elf_section_processing
3095179407Sobrien#define elf_backend_section_from_shdr	_bfd_mips_elf_section_from_shdr
3096179407Sobrien#define elf_backend_fake_sections	_bfd_mips_elf_fake_sections
3097179407Sobrien#define elf_backend_section_from_bfd_section \
3098179407Sobrien				_bfd_mips_elf_section_from_bfd_section
3099179407Sobrien#define elf_backend_add_symbol_hook	_bfd_mips_elf_add_symbol_hook
3100179407Sobrien#define elf_backend_link_output_symbol_hook \
3101179407Sobrien				_bfd_mips_elf_link_output_symbol_hook
3102179407Sobrien#define elf_backend_create_dynamic_sections \
3103179407Sobrien				_bfd_mips_elf_create_dynamic_sections
3104179407Sobrien#define elf_backend_check_relocs	_bfd_mips_elf_check_relocs
3105218822Sdim#define elf_backend_merge_symbol_attribute \
3106218822Sdim				_bfd_mips_elf_merge_symbol_attribute
3107179407Sobrien#define elf_backend_adjust_dynamic_symbol \
3108179407Sobrien				_bfd_mips_elf_adjust_dynamic_symbol
3109179407Sobrien#define elf_backend_always_size_sections \
3110179407Sobrien				_bfd_mips_elf_always_size_sections
3111179407Sobrien#define elf_backend_size_dynamic_sections \
3112179407Sobrien				_bfd_mips_elf_size_dynamic_sections
3113218822Sdim#define elf_backend_init_index_section	_bfd_elf_init_1_index_section
3114179407Sobrien#define elf_backend_relocate_section    _bfd_mips_elf_relocate_section
3115179407Sobrien#define elf_backend_finish_dynamic_symbol \
3116179407Sobrien				_bfd_mips_elf_finish_dynamic_symbol
3117179407Sobrien#define elf_backend_finish_dynamic_sections \
3118179407Sobrien				_bfd_mips_elf_finish_dynamic_sections
3119179407Sobrien#define elf_backend_final_write_processing \
3120179407Sobrien				_bfd_mips_elf_final_write_processing
3121179407Sobrien#define elf_backend_additional_program_headers \
3122179407Sobrien				_bfd_mips_elf_additional_program_headers
3123179407Sobrien#define elf_backend_modify_segment_map	_bfd_mips_elf_modify_segment_map
3124179407Sobrien#define elf_backend_gc_mark_hook	_bfd_mips_elf_gc_mark_hook
3125179407Sobrien#define elf_backend_gc_sweep_hook	_bfd_mips_elf_gc_sweep_hook
3126179407Sobrien#define elf_backend_copy_indirect_symbol \
3127179407Sobrien					_bfd_mips_elf_copy_indirect_symbol
3128179407Sobrien#define elf_backend_hide_symbol		_bfd_mips_elf_hide_symbol
3129179407Sobrien#define elf_backend_ignore_discarded_relocs \
3130179407Sobrien					_bfd_mips_elf_ignore_discarded_relocs
3131179407Sobrien#define elf_backend_mips_irix_compat	elf64_mips_irix_compat
3132179407Sobrien#define elf_backend_mips_rtype_to_howto	mips_elf64_rtype_to_howto
3133179407Sobrien#define elf_backend_ecoff_debug_swap	&mips_elf64_ecoff_debug_swap
3134179407Sobrien#define elf_backend_size_info		mips_elf64_size_info
3135179407Sobrien
3136179407Sobrien#define elf_backend_grok_prstatus	elf64_mips_grok_prstatus
3137179407Sobrien#define elf_backend_grok_psinfo		elf64_mips_grok_psinfo
3138179407Sobrien
3139179407Sobrien#define elf_backend_got_header_size	(4 * MIPS_RESERVED_GOTNO)
3140179407Sobrien
3141179407Sobrien/* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
3142179407Sobrien   work better/work only in RELA, so we default to this.  */
3143179407Sobrien#define elf_backend_may_use_rel_p	1
3144179407Sobrien#define elf_backend_may_use_rela_p	1
3145179407Sobrien#define elf_backend_default_use_rela_p	1
3146179407Sobrien
3147179407Sobrien#define elf_backend_write_section	_bfd_mips_elf_write_section
3148179407Sobrien
3149179407Sobrien/* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit
3150179407Sobrien   MIPS-specific function only applies to IRIX5, which had no 64-bit
3151179407Sobrien   ABI.  */
3152179407Sobrien#define bfd_elf64_find_nearest_line	_bfd_mips_elf_find_nearest_line
3153218822Sdim#define bfd_elf64_find_inliner_info	_bfd_mips_elf_find_inliner_info
3154179407Sobrien#define bfd_elf64_new_section_hook	_bfd_mips_elf_new_section_hook
3155179407Sobrien#define bfd_elf64_set_section_contents	_bfd_mips_elf_set_section_contents
3156179407Sobrien#define bfd_elf64_bfd_get_relocated_section_contents \
3157179407Sobrien				_bfd_elf_mips_get_relocated_section_contents
3158179407Sobrien#define bfd_elf64_bfd_link_hash_table_create \
3159179407Sobrien				_bfd_mips_elf_link_hash_table_create
3160179407Sobrien#define bfd_elf64_bfd_final_link	_bfd_mips_elf_final_link
3161179407Sobrien#define bfd_elf64_bfd_merge_private_bfd_data \
3162179407Sobrien				_bfd_mips_elf_merge_private_bfd_data
3163179407Sobrien#define bfd_elf64_bfd_set_private_flags	_bfd_mips_elf_set_private_flags
3164179407Sobrien#define bfd_elf64_bfd_print_private_bfd_data \
3165179407Sobrien				_bfd_mips_elf_print_private_bfd_data
3166179407Sobrien
3167179407Sobrien#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
3168179407Sobrien#define bfd_elf64_canonicalize_reloc mips_elf64_canonicalize_reloc
3169179407Sobrien#define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
3170179407Sobrien#define bfd_elf64_canonicalize_dynamic_reloc mips_elf64_canonicalize_dynamic_reloc
3171179407Sobrien#define bfd_elf64_bfd_relax_section     _bfd_mips_relax_section
3172179407Sobrien
3173179407Sobrien/* MIPS ELF64 archive functions.  */
3174179407Sobrien#define bfd_elf64_archive_functions
3175179407Sobrienextern bfd_boolean bfd_elf64_archive_slurp_armap
3176179407Sobrien  (bfd *);
3177179407Sobrienextern bfd_boolean bfd_elf64_archive_write_armap
3178179407Sobrien  (bfd *, unsigned int, struct orl *, unsigned int, int);
3179179407Sobrien#define bfd_elf64_archive_slurp_extended_name_table \
3180179407Sobrien			_bfd_archive_coff_slurp_extended_name_table
3181179407Sobrien#define bfd_elf64_archive_construct_extended_name_table \
3182179407Sobrien			_bfd_archive_coff_construct_extended_name_table
3183179407Sobrien#define bfd_elf64_archive_truncate_arname \
3184179407Sobrien			_bfd_archive_coff_truncate_arname
3185179407Sobrien#define bfd_elf64_archive_read_ar_hdr	_bfd_archive_coff_read_ar_hdr
3186179407Sobrien#define bfd_elf64_archive_openr_next_archived_file \
3187179407Sobrien			_bfd_archive_coff_openr_next_archived_file
3188179407Sobrien#define bfd_elf64_archive_get_elt_at_index \
3189179407Sobrien			_bfd_archive_coff_get_elt_at_index
3190179407Sobrien#define bfd_elf64_archive_generic_stat_arch_elt \
3191179407Sobrien			_bfd_archive_coff_generic_stat_arch_elt
3192179407Sobrien#define bfd_elf64_archive_update_armap_timestamp \
3193179407Sobrien			_bfd_archive_coff_update_armap_timestamp
3194179407Sobrien
3195179407Sobrien/* The SGI style (n)64 NewABI.  */
3196179407Sobrien#define TARGET_LITTLE_SYM		bfd_elf64_littlemips_vec
3197179407Sobrien#define TARGET_LITTLE_NAME		"elf64-littlemips"
3198179407Sobrien#define TARGET_BIG_SYM			bfd_elf64_bigmips_vec
3199179407Sobrien#define TARGET_BIG_NAME			"elf64-bigmips"
3200179407Sobrien
3201218822Sdim#define ELF_MAXPAGESIZE			0x10000
3202218822Sdim#define ELF_COMMONPAGESIZE		0x1000
3203179407Sobrien
3204179407Sobrien#include "elf64-target.h"
3205179407Sobrien
3206179407Sobrien/* The SYSV-style 'traditional' (n)64 NewABI.  */
3207179407Sobrien#undef TARGET_LITTLE_SYM
3208179407Sobrien#undef TARGET_LITTLE_NAME
3209179407Sobrien#undef TARGET_BIG_SYM
3210179407Sobrien#undef TARGET_BIG_NAME
3211179407Sobrien
3212179407Sobrien#undef ELF_MAXPAGESIZE
3213218822Sdim#undef ELF_COMMONPAGESIZE
3214179407Sobrien
3215218822Sdim#define TARGET_LITTLE_SYM		bfd_elf64_tradlittlemips_vec
3216218822Sdim#define TARGET_LITTLE_NAME		"elf64-tradlittlemips"
3217218822Sdim#define TARGET_BIG_SYM			bfd_elf64_tradbigmips_vec
3218218822Sdim#define TARGET_BIG_NAME			"elf64-tradbigmips"
3219179407Sobrien
3220179407Sobrien#define ELF_MAXPAGESIZE			0x10000
3221218822Sdim#define ELF_COMMONPAGESIZE		0x1000
3222179407Sobrien#define elf64_bed			elf64_tradbed
3223179407Sobrien
3224179407Sobrien/* Include the target file again for this target.  */
3225179407Sobrien#include "elf64-target.h"
3226