12159047fSniklas /* MIPS-specific support for 32-bit ELF
2c074d1c9Sdrahn Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3c074d1c9Sdrahn 2003 Free Software Foundation, Inc.
42159047fSniklas
52159047fSniklas Most of the information added by Ian Lance Taylor, Cygnus Support,
62159047fSniklas <ian@cygnus.com>.
7b305b0f1Sespie N32/64 ABI support added by Mark Mitchell, CodeSourcery, LLC.
8b305b0f1Sespie <mark@codesourcery.com>
9b55d4692Sfgsch Traditional MIPS targets support added by Koundinya.K, Dansk Data
10b55d4692Sfgsch Elektronik & Operations Research Group. <kk@ddeorg.soft.net>
112159047fSniklas
122159047fSniklas This file is part of BFD, the Binary File Descriptor library.
132159047fSniklas
142159047fSniklas This program is free software; you can redistribute it and/or modify
152159047fSniklas it under the terms of the GNU General Public License as published by
162159047fSniklas the Free Software Foundation; either version 2 of the License, or
172159047fSniklas (at your option) any later version.
182159047fSniklas
192159047fSniklas This program is distributed in the hope that it will be useful,
202159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
212159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
222159047fSniklas GNU General Public License for more details.
232159047fSniklas
242159047fSniklas You should have received a copy of the GNU General Public License
252159047fSniklas along with this program; if not, write to the Free Software
262159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
272159047fSniklas
28c88b1d6cSniklas /* This file handles MIPS ELF targets. SGI Irix 5 uses a slightly
29c88b1d6cSniklas different MIPS ELF from other targets. This matters when linking.
30c88b1d6cSniklas This file supports both, switching at runtime. */
31c88b1d6cSniklas
322159047fSniklas #include "bfd.h"
332159047fSniklas #include "sysdep.h"
342159047fSniklas #include "libbfd.h"
352159047fSniklas #include "bfdlink.h"
362159047fSniklas #include "genlink.h"
372159047fSniklas #include "elf-bfd.h"
38c074d1c9Sdrahn #include "elfxx-mips.h"
392159047fSniklas #include "elf/mips.h"
402159047fSniklas
412159047fSniklas /* Get the ECOFF swapping routines. */
422159047fSniklas #include "coff/sym.h"
432159047fSniklas #include "coff/symconst.h"
442159047fSniklas #include "coff/internal.h"
452159047fSniklas #include "coff/ecoff.h"
462159047fSniklas #include "coff/mips.h"
47b55d4692Sfgsch #define ECOFF_SIGNED_32
482159047fSniklas #include "ecoffswap.h"
492159047fSniklas
50*007c2a45Smiod static bfd_reloc_status_type gprel32_with_gp
51*007c2a45Smiod (bfd *, asymbol *, arelent *, asection *, bfd_boolean, void *, bfd_vma);
52c074d1c9Sdrahn static bfd_reloc_status_type mips_elf_gprel32_reloc
53*007c2a45Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
54b305b0f1Sespie static bfd_reloc_status_type mips32_64bit_reloc
55*007c2a45Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
56b305b0f1Sespie static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
57*007c2a45Smiod (bfd *, bfd_reloc_code_real_type);
58c074d1c9Sdrahn static reloc_howto_type *mips_elf32_rtype_to_howto
59*007c2a45Smiod (unsigned int, bfd_boolean);
60b305b0f1Sespie static void mips_info_to_howto_rel
61*007c2a45Smiod (bfd *, arelent *, Elf_Internal_Rela *);
62b305b0f1Sespie static void mips_info_to_howto_rela
63*007c2a45Smiod (bfd *, arelent *, Elf_Internal_Rela *);
64c074d1c9Sdrahn static bfd_boolean mips_elf_sym_is_global
65*007c2a45Smiod (bfd *, asymbol *);
66c074d1c9Sdrahn static bfd_boolean mips_elf32_object_p
67*007c2a45Smiod (bfd *);
68c074d1c9Sdrahn static bfd_boolean mips_elf_is_local_label_name
69*007c2a45Smiod (bfd *, const char *);
70b305b0f1Sespie static bfd_reloc_status_type mips16_jump_reloc
71*007c2a45Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
72b305b0f1Sespie static bfd_reloc_status_type mips16_gprel_reloc
73*007c2a45Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
74b305b0f1Sespie static bfd_reloc_status_type mips_elf_final_gp
75*007c2a45Smiod (bfd *, asymbol *, bfd_boolean, char **, bfd_vma *);
76c074d1c9Sdrahn static bfd_boolean mips_elf_assign_gp
77*007c2a45Smiod (bfd *, bfd_vma *);
78c074d1c9Sdrahn static bfd_boolean elf32_mips_grok_prstatus
79*007c2a45Smiod (bfd *, Elf_Internal_Note *);
80c074d1c9Sdrahn static bfd_boolean elf32_mips_grok_psinfo
81*007c2a45Smiod (bfd *, Elf_Internal_Note *);
82c074d1c9Sdrahn static irix_compat_t elf32_mips_irix_compat
83*007c2a45Smiod (bfd *);
84b55d4692Sfgsch
85c074d1c9Sdrahn extern const bfd_target bfd_elf32_bigmips_vec;
86c074d1c9Sdrahn extern const bfd_target bfd_elf32_littlemips_vec;
87b55d4692Sfgsch
88b305b0f1Sespie /* Nonzero if ABFD is using the N32 ABI. */
89b305b0f1Sespie #define ABI_N32_P(abfd) \
90b305b0f1Sespie ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
91b305b0f1Sespie
92b305b0f1Sespie /* Whether we are trying to be compatible with IRIX at all. */
93b305b0f1Sespie #define SGI_COMPAT(abfd) \
94c074d1c9Sdrahn (elf32_mips_irix_compat (abfd) != ict_none)
95b305b0f1Sespie
96c88b1d6cSniklas /* The number of local .got entries we reserve. */
97c88b1d6cSniklas #define MIPS_RESERVED_GOTNO (2)
98c88b1d6cSniklas
99b305b0f1Sespie /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
100b305b0f1Sespie from smaller values. Start with zero, widen, *then* decrement. */
101b305b0f1Sespie #define MINUS_ONE (((bfd_vma)0) - 1)
1022159047fSniklas
103c074d1c9Sdrahn /* The relocation table used for SHT_REL sections. */
104c074d1c9Sdrahn
105c074d1c9Sdrahn static reloc_howto_type elf_mips_howto_table_rel[] =
1062159047fSniklas {
1072159047fSniklas /* No relocation. */
1082159047fSniklas HOWTO (R_MIPS_NONE, /* type */
1092159047fSniklas 0, /* rightshift */
1102159047fSniklas 0, /* size (0 = byte, 1 = short, 2 = long) */
1112159047fSniklas 0, /* bitsize */
112c074d1c9Sdrahn FALSE, /* pc_relative */
1132159047fSniklas 0, /* bitpos */
1142159047fSniklas complain_overflow_dont, /* complain_on_overflow */
115*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
1162159047fSniklas "R_MIPS_NONE", /* name */
117c074d1c9Sdrahn FALSE, /* partial_inplace */
1182159047fSniklas 0, /* src_mask */
1192159047fSniklas 0, /* dst_mask */
120c074d1c9Sdrahn FALSE), /* pcrel_offset */
1212159047fSniklas
1222159047fSniklas /* 16 bit relocation. */
1232159047fSniklas HOWTO (R_MIPS_16, /* type */
1242159047fSniklas 0, /* rightshift */
125c074d1c9Sdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
1262159047fSniklas 16, /* bitsize */
127c074d1c9Sdrahn FALSE, /* pc_relative */
1282159047fSniklas 0, /* bitpos */
129c074d1c9Sdrahn complain_overflow_signed, /* complain_on_overflow */
130*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
1312159047fSniklas "R_MIPS_16", /* name */
132c074d1c9Sdrahn TRUE, /* partial_inplace */
133c074d1c9Sdrahn 0x0000ffff, /* src_mask */
134c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
135c074d1c9Sdrahn FALSE), /* pcrel_offset */
1362159047fSniklas
1372159047fSniklas /* 32 bit relocation. */
1382159047fSniklas HOWTO (R_MIPS_32, /* type */
1392159047fSniklas 0, /* rightshift */
1402159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
1412159047fSniklas 32, /* bitsize */
142c074d1c9Sdrahn FALSE, /* pc_relative */
1432159047fSniklas 0, /* bitpos */
144c074d1c9Sdrahn complain_overflow_dont, /* complain_on_overflow */
145*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
1462159047fSniklas "R_MIPS_32", /* name */
147c074d1c9Sdrahn TRUE, /* partial_inplace */
1482159047fSniklas 0xffffffff, /* src_mask */
1492159047fSniklas 0xffffffff, /* dst_mask */
150c074d1c9Sdrahn FALSE), /* pcrel_offset */
1512159047fSniklas
1522159047fSniklas /* 32 bit symbol relative relocation. */
1532159047fSniklas HOWTO (R_MIPS_REL32, /* type */
1542159047fSniklas 0, /* rightshift */
1552159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
1562159047fSniklas 32, /* bitsize */
157c074d1c9Sdrahn FALSE, /* pc_relative */
1582159047fSniklas 0, /* bitpos */
159c074d1c9Sdrahn complain_overflow_dont, /* complain_on_overflow */
160*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
1612159047fSniklas "R_MIPS_REL32", /* name */
162c074d1c9Sdrahn TRUE, /* partial_inplace */
1632159047fSniklas 0xffffffff, /* src_mask */
1642159047fSniklas 0xffffffff, /* dst_mask */
165c074d1c9Sdrahn FALSE), /* pcrel_offset */
1662159047fSniklas
167b55d4692Sfgsch /* 26 bit jump address. */
1682159047fSniklas HOWTO (R_MIPS_26, /* type */
1692159047fSniklas 2, /* rightshift */
1702159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
1712159047fSniklas 26, /* bitsize */
172c074d1c9Sdrahn FALSE, /* pc_relative */
1732159047fSniklas 0, /* bitpos */
1742159047fSniklas complain_overflow_dont, /* complain_on_overflow */
1752159047fSniklas /* This needs complex overflow
1762159047fSniklas detection, because the upper four
177b55d4692Sfgsch bits must match the PC + 4. */
178*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
1792159047fSniklas "R_MIPS_26", /* name */
180c074d1c9Sdrahn TRUE, /* partial_inplace */
181c074d1c9Sdrahn 0x03ffffff, /* src_mask */
182c074d1c9Sdrahn 0x03ffffff, /* dst_mask */
183c074d1c9Sdrahn FALSE), /* pcrel_offset */
1842159047fSniklas
1852159047fSniklas /* High 16 bits of symbol value. */
1862159047fSniklas HOWTO (R_MIPS_HI16, /* type */
187*007c2a45Smiod 16, /* rightshift */
1882159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
1892159047fSniklas 16, /* bitsize */
190c074d1c9Sdrahn FALSE, /* pc_relative */
1912159047fSniklas 0, /* bitpos */
1922159047fSniklas complain_overflow_dont, /* complain_on_overflow */
193*007c2a45Smiod _bfd_mips_elf_hi16_reloc, /* special_function */
1942159047fSniklas "R_MIPS_HI16", /* name */
195c074d1c9Sdrahn TRUE, /* partial_inplace */
196c074d1c9Sdrahn 0x0000ffff, /* src_mask */
197c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
198c074d1c9Sdrahn FALSE), /* pcrel_offset */
1992159047fSniklas
2002159047fSniklas /* Low 16 bits of symbol value. */
2012159047fSniklas HOWTO (R_MIPS_LO16, /* type */
2022159047fSniklas 0, /* rightshift */
2032159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2042159047fSniklas 16, /* bitsize */
205c074d1c9Sdrahn FALSE, /* pc_relative */
2062159047fSniklas 0, /* bitpos */
2072159047fSniklas complain_overflow_dont, /* complain_on_overflow */
208*007c2a45Smiod _bfd_mips_elf_lo16_reloc, /* special_function */
2092159047fSniklas "R_MIPS_LO16", /* name */
210c074d1c9Sdrahn TRUE, /* partial_inplace */
211c074d1c9Sdrahn 0x0000ffff, /* src_mask */
212c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
213c074d1c9Sdrahn FALSE), /* pcrel_offset */
2142159047fSniklas
2152159047fSniklas /* GP relative reference. */
2162159047fSniklas HOWTO (R_MIPS_GPREL16, /* type */
2172159047fSniklas 0, /* rightshift */
2182159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2192159047fSniklas 16, /* bitsize */
220c074d1c9Sdrahn FALSE, /* pc_relative */
2212159047fSniklas 0, /* bitpos */
2222159047fSniklas complain_overflow_signed, /* complain_on_overflow */
223c074d1c9Sdrahn _bfd_mips_elf32_gprel16_reloc, /* special_function */
2242159047fSniklas "R_MIPS_GPREL16", /* name */
225c074d1c9Sdrahn TRUE, /* partial_inplace */
226c074d1c9Sdrahn 0x0000ffff, /* src_mask */
227c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
228c074d1c9Sdrahn FALSE), /* pcrel_offset */
2292159047fSniklas
2302159047fSniklas /* Reference to literal section. */
2312159047fSniklas HOWTO (R_MIPS_LITERAL, /* type */
2322159047fSniklas 0, /* rightshift */
2332159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2342159047fSniklas 16, /* bitsize */
235c074d1c9Sdrahn FALSE, /* pc_relative */
2362159047fSniklas 0, /* bitpos */
2372159047fSniklas complain_overflow_signed, /* complain_on_overflow */
238c074d1c9Sdrahn _bfd_mips_elf32_gprel16_reloc, /* special_function */
2392159047fSniklas "R_MIPS_LITERAL", /* name */
240c074d1c9Sdrahn TRUE, /* partial_inplace */
241c074d1c9Sdrahn 0x0000ffff, /* src_mask */
242c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
243c074d1c9Sdrahn FALSE), /* pcrel_offset */
2442159047fSniklas
2452159047fSniklas /* Reference to global offset table. */
2462159047fSniklas HOWTO (R_MIPS_GOT16, /* type */
2472159047fSniklas 0, /* rightshift */
2482159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2492159047fSniklas 16, /* bitsize */
250c074d1c9Sdrahn FALSE, /* pc_relative */
2512159047fSniklas 0, /* bitpos */
2522159047fSniklas complain_overflow_signed, /* complain_on_overflow */
253*007c2a45Smiod _bfd_mips_elf_got16_reloc, /* special_function */
2542159047fSniklas "R_MIPS_GOT16", /* name */
255c074d1c9Sdrahn TRUE, /* partial_inplace */
256c074d1c9Sdrahn 0x0000ffff, /* src_mask */
257c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
258c074d1c9Sdrahn FALSE), /* pcrel_offset */
2592159047fSniklas
2602159047fSniklas /* 16 bit PC relative reference. */
2612159047fSniklas HOWTO (R_MIPS_PC16, /* type */
2622159047fSniklas 0, /* rightshift */
2632159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2642159047fSniklas 16, /* bitsize */
265c074d1c9Sdrahn TRUE, /* pc_relative */
2662159047fSniklas 0, /* bitpos */
2672159047fSniklas complain_overflow_signed, /* complain_on_overflow */
268*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
2692159047fSniklas "R_MIPS_PC16", /* name */
270c074d1c9Sdrahn TRUE, /* partial_inplace */
271c074d1c9Sdrahn 0x0000ffff, /* src_mask */
272c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
273c074d1c9Sdrahn TRUE), /* pcrel_offset */
2742159047fSniklas
2752159047fSniklas /* 16 bit call through global offset table. */
2762159047fSniklas HOWTO (R_MIPS_CALL16, /* type */
2772159047fSniklas 0, /* rightshift */
2782159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2792159047fSniklas 16, /* bitsize */
280c074d1c9Sdrahn FALSE, /* pc_relative */
2812159047fSniklas 0, /* bitpos */
2822159047fSniklas complain_overflow_signed, /* complain_on_overflow */
283*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
2842159047fSniklas "R_MIPS_CALL16", /* name */
285c074d1c9Sdrahn TRUE, /* partial_inplace */
286c074d1c9Sdrahn 0x0000ffff, /* src_mask */
287c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
288c074d1c9Sdrahn FALSE), /* pcrel_offset */
2892159047fSniklas
2902159047fSniklas /* 32 bit GP relative reference. */
2912159047fSniklas HOWTO (R_MIPS_GPREL32, /* type */
2922159047fSniklas 0, /* rightshift */
2932159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2942159047fSniklas 32, /* bitsize */
295c074d1c9Sdrahn FALSE, /* pc_relative */
2962159047fSniklas 0, /* bitpos */
297c074d1c9Sdrahn complain_overflow_dont, /* complain_on_overflow */
298c074d1c9Sdrahn mips_elf_gprel32_reloc, /* special_function */
2992159047fSniklas "R_MIPS_GPREL32", /* name */
300c074d1c9Sdrahn TRUE, /* partial_inplace */
3012159047fSniklas 0xffffffff, /* src_mask */
3022159047fSniklas 0xffffffff, /* dst_mask */
303c074d1c9Sdrahn FALSE), /* pcrel_offset */
3042159047fSniklas
3052159047fSniklas /* The remaining relocs are defined on Irix 5, although they are
3062159047fSniklas not defined by the ABI. */
307b305b0f1Sespie EMPTY_HOWTO (13),
308b305b0f1Sespie EMPTY_HOWTO (14),
309b305b0f1Sespie EMPTY_HOWTO (15),
3102159047fSniklas
3112159047fSniklas /* A 5 bit shift field. */
3122159047fSniklas HOWTO (R_MIPS_SHIFT5, /* type */
3132159047fSniklas 0, /* rightshift */
3142159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3152159047fSniklas 5, /* bitsize */
316c074d1c9Sdrahn FALSE, /* pc_relative */
3172159047fSniklas 6, /* bitpos */
3182159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
319*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
3202159047fSniklas "R_MIPS_SHIFT5", /* name */
321c074d1c9Sdrahn TRUE, /* partial_inplace */
3222159047fSniklas 0x000007c0, /* src_mask */
3232159047fSniklas 0x000007c0, /* dst_mask */
324c074d1c9Sdrahn FALSE), /* pcrel_offset */
3252159047fSniklas
3262159047fSniklas /* A 6 bit shift field. */
3272159047fSniklas /* FIXME: This is not handled correctly; a special function is
3282159047fSniklas needed to put the most significant bit in the right place. */
3292159047fSniklas HOWTO (R_MIPS_SHIFT6, /* type */
3302159047fSniklas 0, /* rightshift */
3312159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3322159047fSniklas 6, /* bitsize */
333c074d1c9Sdrahn FALSE, /* pc_relative */
3342159047fSniklas 6, /* bitpos */
3352159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
336*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
3372159047fSniklas "R_MIPS_SHIFT6", /* name */
338c074d1c9Sdrahn TRUE, /* partial_inplace */
3392159047fSniklas 0x000007c4, /* src_mask */
3402159047fSniklas 0x000007c4, /* dst_mask */
341c074d1c9Sdrahn FALSE), /* pcrel_offset */
3422159047fSniklas
343b305b0f1Sespie /* A 64 bit relocation. */
344e93f7393Sniklas HOWTO (R_MIPS_64, /* type */
345e93f7393Sniklas 0, /* rightshift */
346b305b0f1Sespie 4, /* size (0 = byte, 1 = short, 2 = long) */
347b305b0f1Sespie 64, /* bitsize */
348c074d1c9Sdrahn FALSE, /* pc_relative */
349e93f7393Sniklas 0, /* bitpos */
350c074d1c9Sdrahn complain_overflow_dont, /* complain_on_overflow */
351e93f7393Sniklas mips32_64bit_reloc, /* special_function */
352e93f7393Sniklas "R_MIPS_64", /* name */
353c074d1c9Sdrahn TRUE, /* partial_inplace */
354b305b0f1Sespie MINUS_ONE, /* src_mask */
355b305b0f1Sespie MINUS_ONE, /* dst_mask */
356c074d1c9Sdrahn FALSE), /* pcrel_offset */
3572159047fSniklas
3582159047fSniklas /* Displacement in the global offset table. */
3592159047fSniklas HOWTO (R_MIPS_GOT_DISP, /* type */
3602159047fSniklas 0, /* rightshift */
3612159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3622159047fSniklas 16, /* bitsize */
363c074d1c9Sdrahn FALSE, /* pc_relative */
3642159047fSniklas 0, /* bitpos */
365c074d1c9Sdrahn complain_overflow_signed, /* complain_on_overflow */
366*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
3672159047fSniklas "R_MIPS_GOT_DISP", /* name */
368c074d1c9Sdrahn TRUE, /* partial_inplace */
3692159047fSniklas 0x0000ffff, /* src_mask */
3702159047fSniklas 0x0000ffff, /* dst_mask */
371c074d1c9Sdrahn FALSE), /* pcrel_offset */
3722159047fSniklas
3732159047fSniklas /* Displacement to page pointer in the global offset table. */
3742159047fSniklas HOWTO (R_MIPS_GOT_PAGE, /* type */
3752159047fSniklas 0, /* rightshift */
3762159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3772159047fSniklas 16, /* bitsize */
378c074d1c9Sdrahn FALSE, /* pc_relative */
3792159047fSniklas 0, /* bitpos */
380c074d1c9Sdrahn complain_overflow_signed, /* complain_on_overflow */
381*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
3822159047fSniklas "R_MIPS_GOT_PAGE", /* name */
383c074d1c9Sdrahn TRUE, /* partial_inplace */
3842159047fSniklas 0x0000ffff, /* src_mask */
3852159047fSniklas 0x0000ffff, /* dst_mask */
386c074d1c9Sdrahn FALSE), /* pcrel_offset */
3872159047fSniklas
3882159047fSniklas /* Offset from page pointer in the global offset table. */
3892159047fSniklas HOWTO (R_MIPS_GOT_OFST, /* type */
3902159047fSniklas 0, /* rightshift */
3912159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3922159047fSniklas 16, /* bitsize */
393c074d1c9Sdrahn FALSE, /* pc_relative */
3942159047fSniklas 0, /* bitpos */
395c074d1c9Sdrahn complain_overflow_signed, /* complain_on_overflow */
396*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
3972159047fSniklas "R_MIPS_GOT_OFST", /* name */
398c074d1c9Sdrahn TRUE, /* partial_inplace */
3992159047fSniklas 0x0000ffff, /* src_mask */
4002159047fSniklas 0x0000ffff, /* dst_mask */
401c074d1c9Sdrahn FALSE), /* pcrel_offset */
4022159047fSniklas
4032159047fSniklas /* High 16 bits of displacement in global offset table. */
4042159047fSniklas HOWTO (R_MIPS_GOT_HI16, /* type */
4052159047fSniklas 0, /* rightshift */
4062159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4072159047fSniklas 16, /* bitsize */
408c074d1c9Sdrahn FALSE, /* pc_relative */
4092159047fSniklas 0, /* bitpos */
4102159047fSniklas complain_overflow_dont, /* complain_on_overflow */
411*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
4122159047fSniklas "R_MIPS_GOT_HI16", /* name */
413c074d1c9Sdrahn TRUE, /* partial_inplace */
4142159047fSniklas 0x0000ffff, /* src_mask */
4152159047fSniklas 0x0000ffff, /* dst_mask */
416c074d1c9Sdrahn FALSE), /* pcrel_offset */
4172159047fSniklas
4182159047fSniklas /* Low 16 bits of displacement in global offset table. */
4192159047fSniklas HOWTO (R_MIPS_GOT_LO16, /* type */
4202159047fSniklas 0, /* rightshift */
4212159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4222159047fSniklas 16, /* bitsize */
423c074d1c9Sdrahn FALSE, /* pc_relative */
4242159047fSniklas 0, /* bitpos */
4252159047fSniklas complain_overflow_dont, /* complain_on_overflow */
426*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
4272159047fSniklas "R_MIPS_GOT_LO16", /* name */
428c074d1c9Sdrahn TRUE, /* partial_inplace */
4292159047fSniklas 0x0000ffff, /* src_mask */
4302159047fSniklas 0x0000ffff, /* dst_mask */
431c074d1c9Sdrahn FALSE), /* pcrel_offset */
4322159047fSniklas
433b305b0f1Sespie /* 64 bit subtraction. Used in the N32 ABI. */
434b305b0f1Sespie HOWTO (R_MIPS_SUB, /* type */
435b305b0f1Sespie 0, /* rightshift */
436b305b0f1Sespie 4, /* size (0 = byte, 1 = short, 2 = long) */
437b305b0f1Sespie 64, /* bitsize */
438c074d1c9Sdrahn FALSE, /* pc_relative */
439b305b0f1Sespie 0, /* bitpos */
440c074d1c9Sdrahn complain_overflow_dont, /* complain_on_overflow */
441*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
442b305b0f1Sespie "R_MIPS_SUB", /* name */
443c074d1c9Sdrahn TRUE, /* partial_inplace */
444b305b0f1Sespie MINUS_ONE, /* src_mask */
445b305b0f1Sespie MINUS_ONE, /* dst_mask */
446c074d1c9Sdrahn FALSE), /* pcrel_offset */
4472159047fSniklas
4482159047fSniklas /* Used to cause the linker to insert and delete instructions? */
449b305b0f1Sespie EMPTY_HOWTO (R_MIPS_INSERT_A),
450b305b0f1Sespie EMPTY_HOWTO (R_MIPS_INSERT_B),
451b305b0f1Sespie EMPTY_HOWTO (R_MIPS_DELETE),
4522159047fSniklas
453b305b0f1Sespie /* Get the higher value of a 64 bit addend. */
454b305b0f1Sespie HOWTO (R_MIPS_HIGHER, /* type */
455b305b0f1Sespie 0, /* rightshift */
456b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
457b305b0f1Sespie 16, /* bitsize */
458c074d1c9Sdrahn FALSE, /* pc_relative */
459b305b0f1Sespie 0, /* bitpos */
460b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
461*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
462b305b0f1Sespie "R_MIPS_HIGHER", /* name */
463c074d1c9Sdrahn TRUE, /* partial_inplace */
464c074d1c9Sdrahn 0x0000ffff, /* src_mask */
465c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
466c074d1c9Sdrahn FALSE), /* pcrel_offset */
467b305b0f1Sespie
468b305b0f1Sespie /* Get the highest value of a 64 bit addend. */
469b305b0f1Sespie HOWTO (R_MIPS_HIGHEST, /* type */
470b305b0f1Sespie 0, /* rightshift */
471b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
472b305b0f1Sespie 16, /* bitsize */
473c074d1c9Sdrahn FALSE, /* pc_relative */
474b305b0f1Sespie 0, /* bitpos */
475b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
476*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
477b305b0f1Sespie "R_MIPS_HIGHEST", /* name */
478c074d1c9Sdrahn TRUE, /* partial_inplace */
479c074d1c9Sdrahn 0x0000ffff, /* src_mask */
480c074d1c9Sdrahn 0x0000ffff, /* dst_mask */
481c074d1c9Sdrahn FALSE), /* pcrel_offset */
4822159047fSniklas
4832159047fSniklas /* High 16 bits of displacement in global offset table. */
4842159047fSniklas HOWTO (R_MIPS_CALL_HI16, /* type */
4852159047fSniklas 0, /* rightshift */
4862159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4872159047fSniklas 16, /* bitsize */
488c074d1c9Sdrahn FALSE, /* pc_relative */
4892159047fSniklas 0, /* bitpos */
4902159047fSniklas complain_overflow_dont, /* complain_on_overflow */
491*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
4922159047fSniklas "R_MIPS_CALL_HI16", /* name */
493c074d1c9Sdrahn TRUE, /* partial_inplace */
4942159047fSniklas 0x0000ffff, /* src_mask */
4952159047fSniklas 0x0000ffff, /* dst_mask */
496c074d1c9Sdrahn FALSE), /* pcrel_offset */
4972159047fSniklas
4982159047fSniklas /* Low 16 bits of displacement in global offset table. */
4992159047fSniklas HOWTO (R_MIPS_CALL_LO16, /* type */
5002159047fSniklas 0, /* rightshift */
5012159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
5022159047fSniklas 16, /* bitsize */
503c074d1c9Sdrahn FALSE, /* pc_relative */
5042159047fSniklas 0, /* bitpos */
5052159047fSniklas complain_overflow_dont, /* complain_on_overflow */
506*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
5072159047fSniklas "R_MIPS_CALL_LO16", /* name */
508c074d1c9Sdrahn TRUE, /* partial_inplace */
5092159047fSniklas 0x0000ffff, /* src_mask */
5102159047fSniklas 0x0000ffff, /* dst_mask */
511c074d1c9Sdrahn FALSE), /* pcrel_offset */
512b305b0f1Sespie
513b305b0f1Sespie /* Section displacement. */
514b305b0f1Sespie HOWTO (R_MIPS_SCN_DISP, /* type */
515b305b0f1Sespie 0, /* rightshift */
516b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
517b305b0f1Sespie 32, /* bitsize */
518c074d1c9Sdrahn FALSE, /* pc_relative */
519b305b0f1Sespie 0, /* bitpos */
520b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
521*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
522b305b0f1Sespie "R_MIPS_SCN_DISP", /* name */
523c074d1c9Sdrahn TRUE, /* partial_inplace */
524b305b0f1Sespie 0xffffffff, /* src_mask */
525b305b0f1Sespie 0xffffffff, /* dst_mask */
526c074d1c9Sdrahn FALSE), /* pcrel_offset */
527b305b0f1Sespie
528b305b0f1Sespie EMPTY_HOWTO (R_MIPS_REL16),
529b305b0f1Sespie EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
530b305b0f1Sespie EMPTY_HOWTO (R_MIPS_PJUMP),
531b305b0f1Sespie EMPTY_HOWTO (R_MIPS_RELGOT),
532b305b0f1Sespie
533b305b0f1Sespie /* Protected jump conversion. This is an optimization hint. No
534b305b0f1Sespie relocation is required for correctness. */
535b305b0f1Sespie HOWTO (R_MIPS_JALR, /* type */
536b305b0f1Sespie 0, /* rightshift */
537c074d1c9Sdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
538c074d1c9Sdrahn 32, /* bitsize */
539c074d1c9Sdrahn FALSE, /* pc_relative */
540b305b0f1Sespie 0, /* bitpos */
541b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
542*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
543b305b0f1Sespie "R_MIPS_JALR", /* name */
544c074d1c9Sdrahn FALSE, /* partial_inplace */
545b305b0f1Sespie 0x00000000, /* src_mask */
546b305b0f1Sespie 0x00000000, /* dst_mask */
547c074d1c9Sdrahn FALSE), /* pcrel_offset */
5482159047fSniklas };
5492159047fSniklas
550b305b0f1Sespie /* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This
551b305b0f1Sespie is a hack to make the linker think that we need 64 bit values. */
552b305b0f1Sespie static reloc_howto_type elf_mips_ctor64_howto =
553b305b0f1Sespie HOWTO (R_MIPS_64, /* type */
554b305b0f1Sespie 0, /* rightshift */
555b305b0f1Sespie 4, /* size (0 = byte, 1 = short, 2 = long) */
556b305b0f1Sespie 32, /* bitsize */
557c074d1c9Sdrahn FALSE, /* pc_relative */
558b305b0f1Sespie 0, /* bitpos */
559b305b0f1Sespie complain_overflow_signed, /* complain_on_overflow */
560b305b0f1Sespie mips32_64bit_reloc, /* special_function */
561b305b0f1Sespie "R_MIPS_64", /* name */
562c074d1c9Sdrahn TRUE, /* partial_inplace */
563b305b0f1Sespie 0xffffffff, /* src_mask */
564b305b0f1Sespie 0xffffffff, /* dst_mask */
565c074d1c9Sdrahn FALSE); /* pcrel_offset */
566b305b0f1Sespie
567b305b0f1Sespie /* The reloc used for the mips16 jump instruction. */
568b305b0f1Sespie static reloc_howto_type elf_mips16_jump_howto =
569b305b0f1Sespie HOWTO (R_MIPS16_26, /* type */
570b305b0f1Sespie 2, /* rightshift */
571b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
572b305b0f1Sespie 26, /* bitsize */
573c074d1c9Sdrahn FALSE, /* pc_relative */
574b305b0f1Sespie 0, /* bitpos */
575b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
576b305b0f1Sespie /* This needs complex overflow
577b305b0f1Sespie detection, because the upper four
578b305b0f1Sespie bits must match the PC. */
579b305b0f1Sespie mips16_jump_reloc, /* special_function */
580b305b0f1Sespie "R_MIPS16_26", /* name */
581c074d1c9Sdrahn TRUE, /* partial_inplace */
582b305b0f1Sespie 0x3ffffff, /* src_mask */
583b305b0f1Sespie 0x3ffffff, /* dst_mask */
584c074d1c9Sdrahn FALSE); /* pcrel_offset */
585b305b0f1Sespie
586b305b0f1Sespie /* The reloc used for the mips16 gprel instruction. */
587b305b0f1Sespie static reloc_howto_type elf_mips16_gprel_howto =
588b305b0f1Sespie HOWTO (R_MIPS16_GPREL, /* type */
589b305b0f1Sespie 0, /* rightshift */
590b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
591b305b0f1Sespie 16, /* bitsize */
592c074d1c9Sdrahn FALSE, /* pc_relative */
593b305b0f1Sespie 0, /* bitpos */
594b305b0f1Sespie complain_overflow_signed, /* complain_on_overflow */
595b305b0f1Sespie mips16_gprel_reloc, /* special_function */
596b305b0f1Sespie "R_MIPS16_GPREL", /* name */
597c074d1c9Sdrahn TRUE, /* partial_inplace */
598b305b0f1Sespie 0x07ff001f, /* src_mask */
599b305b0f1Sespie 0x07ff001f, /* dst_mask */
600c074d1c9Sdrahn FALSE); /* pcrel_offset */
601b305b0f1Sespie
602b305b0f1Sespie /* GNU extensions for embedded-pic. */
603b305b0f1Sespie /* High 16 bits of symbol value, pc-relative. */
604b305b0f1Sespie static reloc_howto_type elf_mips_gnu_rel_hi16 =
605b305b0f1Sespie HOWTO (R_MIPS_GNU_REL_HI16, /* type */
606*007c2a45Smiod 16, /* rightshift */
607b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
608b305b0f1Sespie 16, /* bitsize */
609c074d1c9Sdrahn TRUE, /* pc_relative */
610b305b0f1Sespie 0, /* bitpos */
611b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
612*007c2a45Smiod _bfd_mips_elf_hi16_reloc, /* special_function */
613b305b0f1Sespie "R_MIPS_GNU_REL_HI16", /* name */
614c074d1c9Sdrahn TRUE, /* partial_inplace */
615b305b0f1Sespie 0xffff, /* src_mask */
616b305b0f1Sespie 0xffff, /* dst_mask */
617c074d1c9Sdrahn TRUE); /* pcrel_offset */
618b305b0f1Sespie
619b305b0f1Sespie /* Low 16 bits of symbol value, pc-relative. */
620b305b0f1Sespie static reloc_howto_type elf_mips_gnu_rel_lo16 =
621b305b0f1Sespie HOWTO (R_MIPS_GNU_REL_LO16, /* type */
622b305b0f1Sespie 0, /* rightshift */
623b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
624b305b0f1Sespie 16, /* bitsize */
625c074d1c9Sdrahn TRUE, /* pc_relative */
626b305b0f1Sespie 0, /* bitpos */
627b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
628*007c2a45Smiod _bfd_mips_elf_lo16_reloc, /* special_function */
629b305b0f1Sespie "R_MIPS_GNU_REL_LO16", /* name */
630c074d1c9Sdrahn TRUE, /* partial_inplace */
631b305b0f1Sespie 0xffff, /* src_mask */
632b305b0f1Sespie 0xffff, /* dst_mask */
633c074d1c9Sdrahn TRUE); /* pcrel_offset */
634b305b0f1Sespie
635b305b0f1Sespie /* 16 bit offset for pc-relative branches. */
636b305b0f1Sespie static reloc_howto_type elf_mips_gnu_rel16_s2 =
637b305b0f1Sespie HOWTO (R_MIPS_GNU_REL16_S2, /* type */
638b305b0f1Sespie 2, /* rightshift */
639b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
640b305b0f1Sespie 16, /* bitsize */
641c074d1c9Sdrahn TRUE, /* pc_relative */
642b305b0f1Sespie 0, /* bitpos */
643b305b0f1Sespie complain_overflow_signed, /* complain_on_overflow */
644*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
645b305b0f1Sespie "R_MIPS_GNU_REL16_S2", /* name */
646c074d1c9Sdrahn TRUE, /* partial_inplace */
647b305b0f1Sespie 0xffff, /* src_mask */
648b305b0f1Sespie 0xffff, /* dst_mask */
649c074d1c9Sdrahn TRUE); /* pcrel_offset */
650b305b0f1Sespie
651b305b0f1Sespie /* 64 bit pc-relative. */
652b305b0f1Sespie static reloc_howto_type elf_mips_gnu_pcrel64 =
653b305b0f1Sespie HOWTO (R_MIPS_PC64, /* type */
654b305b0f1Sespie 0, /* rightshift */
655b305b0f1Sespie 4, /* size (0 = byte, 1 = short, 2 = long) */
656b305b0f1Sespie 64, /* bitsize */
657c074d1c9Sdrahn TRUE, /* pc_relative */
658b305b0f1Sespie 0, /* bitpos */
659b305b0f1Sespie complain_overflow_signed, /* complain_on_overflow */
660*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
661b305b0f1Sespie "R_MIPS_PC64", /* name */
662c074d1c9Sdrahn TRUE, /* partial_inplace */
663b305b0f1Sespie MINUS_ONE, /* src_mask */
664b305b0f1Sespie MINUS_ONE, /* dst_mask */
665c074d1c9Sdrahn TRUE); /* pcrel_offset */
666b305b0f1Sespie
667b305b0f1Sespie /* 32 bit pc-relative. */
668b305b0f1Sespie static reloc_howto_type elf_mips_gnu_pcrel32 =
669b305b0f1Sespie HOWTO (R_MIPS_PC32, /* type */
670b305b0f1Sespie 0, /* rightshift */
671b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
672b305b0f1Sespie 32, /* bitsize */
673c074d1c9Sdrahn TRUE, /* pc_relative */
674b305b0f1Sespie 0, /* bitpos */
675b305b0f1Sespie complain_overflow_signed, /* complain_on_overflow */
676*007c2a45Smiod _bfd_mips_elf_generic_reloc, /* special_function */
677b305b0f1Sespie "R_MIPS_PC32", /* name */
678c074d1c9Sdrahn TRUE, /* partial_inplace */
679b305b0f1Sespie 0xffffffff, /* src_mask */
680b305b0f1Sespie 0xffffffff, /* dst_mask */
681c074d1c9Sdrahn TRUE); /* pcrel_offset */
682b305b0f1Sespie
683b305b0f1Sespie /* GNU extension to record C++ vtable hierarchy */
684b305b0f1Sespie static reloc_howto_type elf_mips_gnu_vtinherit_howto =
685b305b0f1Sespie HOWTO (R_MIPS_GNU_VTINHERIT, /* type */
686b305b0f1Sespie 0, /* rightshift */
687b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
688b305b0f1Sespie 0, /* bitsize */
689c074d1c9Sdrahn FALSE, /* pc_relative */
690b305b0f1Sespie 0, /* bitpos */
691b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
692b305b0f1Sespie NULL, /* special_function */
693b305b0f1Sespie "R_MIPS_GNU_VTINHERIT", /* name */
694c074d1c9Sdrahn FALSE, /* partial_inplace */
695b305b0f1Sespie 0, /* src_mask */
696b305b0f1Sespie 0, /* dst_mask */
697c074d1c9Sdrahn FALSE); /* pcrel_offset */
698b305b0f1Sespie
699b305b0f1Sespie /* GNU extension to record C++ vtable member usage */
700b305b0f1Sespie static reloc_howto_type elf_mips_gnu_vtentry_howto =
701b305b0f1Sespie HOWTO (R_MIPS_GNU_VTENTRY, /* type */
702b305b0f1Sespie 0, /* rightshift */
703b305b0f1Sespie 2, /* size (0 = byte, 1 = short, 2 = long) */
704b305b0f1Sespie 0, /* bitsize */
705c074d1c9Sdrahn FALSE, /* pc_relative */
706b305b0f1Sespie 0, /* bitpos */
707b305b0f1Sespie complain_overflow_dont, /* complain_on_overflow */
708b305b0f1Sespie _bfd_elf_rel_vtable_reloc_fn, /* special_function */
709b305b0f1Sespie "R_MIPS_GNU_VTENTRY", /* name */
710c074d1c9Sdrahn FALSE, /* partial_inplace */
711b305b0f1Sespie 0, /* src_mask */
712b305b0f1Sespie 0, /* dst_mask */
713c074d1c9Sdrahn FALSE); /* pcrel_offset */
714b305b0f1Sespie
715c074d1c9Sdrahn /* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a
716b305b0f1Sespie dangerous relocation. */
717b305b0f1Sespie
718c074d1c9Sdrahn static bfd_boolean
mips_elf_assign_gp(bfd * output_bfd,bfd_vma * pgp)719*007c2a45Smiod mips_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp)
720b305b0f1Sespie {
721b305b0f1Sespie unsigned int count;
722b305b0f1Sespie asymbol **sym;
723b305b0f1Sespie unsigned int i;
724b305b0f1Sespie
725b305b0f1Sespie /* If we've already figured out what GP will be, just return it. */
726b305b0f1Sespie *pgp = _bfd_get_gp_value (output_bfd);
727b305b0f1Sespie if (*pgp)
728c074d1c9Sdrahn return TRUE;
729b305b0f1Sespie
730b305b0f1Sespie count = bfd_get_symcount (output_bfd);
731b305b0f1Sespie sym = bfd_get_outsymbols (output_bfd);
732b305b0f1Sespie
733b305b0f1Sespie /* The linker script will have created a symbol named `_gp' with the
734b305b0f1Sespie appropriate value. */
735*007c2a45Smiod if (sym == NULL)
736b305b0f1Sespie i = count;
737b305b0f1Sespie else
738b305b0f1Sespie {
739b305b0f1Sespie for (i = 0; i < count; i++, sym++)
740b305b0f1Sespie {
741c074d1c9Sdrahn register const char *name;
742b305b0f1Sespie
743b305b0f1Sespie name = bfd_asymbol_name (*sym);
744b305b0f1Sespie if (*name == '_' && strcmp (name, "_gp") == 0)
745b305b0f1Sespie {
746b305b0f1Sespie *pgp = bfd_asymbol_value (*sym);
747b305b0f1Sespie _bfd_set_gp_value (output_bfd, *pgp);
748b305b0f1Sespie break;
749b305b0f1Sespie }
750b305b0f1Sespie }
751b305b0f1Sespie }
752b305b0f1Sespie
753b305b0f1Sespie if (i >= count)
754b305b0f1Sespie {
755b305b0f1Sespie /* Only get the error once. */
756b305b0f1Sespie *pgp = 4;
757b305b0f1Sespie _bfd_set_gp_value (output_bfd, *pgp);
758c074d1c9Sdrahn return FALSE;
759b305b0f1Sespie }
760b305b0f1Sespie
761c074d1c9Sdrahn return TRUE;
762b305b0f1Sespie }
763b305b0f1Sespie
7642159047fSniklas /* We have to figure out the gp value, so that we can adjust the
7652159047fSniklas symbol value correctly. We look up the symbol _gp in the output
7662159047fSniklas BFD. If we can't find it, we're stuck. We cache it in the ELF
7672159047fSniklas target data. We don't need to adjust the symbol value for an
768*007c2a45Smiod external symbol if we are producing relocatable output. */
769c88b1d6cSniklas
770c88b1d6cSniklas static bfd_reloc_status_type
mips_elf_final_gp(bfd * output_bfd,asymbol * symbol,bfd_boolean relocatable,char ** error_message,bfd_vma * pgp)771*007c2a45Smiod mips_elf_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable,
772*007c2a45Smiod char **error_message, bfd_vma *pgp)
773c88b1d6cSniklas {
774c88b1d6cSniklas if (bfd_is_und_section (symbol->section)
775*007c2a45Smiod && ! relocatable)
776c88b1d6cSniklas {
777c88b1d6cSniklas *pgp = 0;
778c88b1d6cSniklas return bfd_reloc_undefined;
779c88b1d6cSniklas }
780c88b1d6cSniklas
781c88b1d6cSniklas *pgp = _bfd_get_gp_value (output_bfd);
782c88b1d6cSniklas if (*pgp == 0
783*007c2a45Smiod && (! relocatable
7842159047fSniklas || (symbol->flags & BSF_SECTION_SYM) != 0))
7852159047fSniklas {
786*007c2a45Smiod if (relocatable)
7872159047fSniklas {
7882159047fSniklas /* Make up a value. */
789c88b1d6cSniklas *pgp = symbol->section->output_section->vma + 0x4000;
790c88b1d6cSniklas _bfd_set_gp_value (output_bfd, *pgp);
7912159047fSniklas }
792b305b0f1Sespie else if (!mips_elf_assign_gp (output_bfd, pgp))
7932159047fSniklas {
7942159047fSniklas *error_message =
795b305b0f1Sespie (char *) _("GP relative relocation when _gp not defined");
7962159047fSniklas return bfd_reloc_dangerous;
7972159047fSniklas }
7982159047fSniklas }
7992159047fSniklas
800c88b1d6cSniklas return bfd_reloc_ok;
801c88b1d6cSniklas }
802c88b1d6cSniklas
803c88b1d6cSniklas /* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must
804c88b1d6cSniklas become the offset from the gp register. This function also handles
805c88b1d6cSniklas R_MIPS_LITERAL relocations, although those can be handled more
806c88b1d6cSniklas cleverly because the entries in the .lit8 and .lit4 sections can be
807c88b1d6cSniklas merged. */
808c88b1d6cSniklas
809c88b1d6cSniklas bfd_reloc_status_type
_bfd_mips_elf32_gprel16_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message)810*007c2a45Smiod _bfd_mips_elf32_gprel16_reloc (bfd *abfd, arelent *reloc_entry,
811*007c2a45Smiod asymbol *symbol, void *data,
812*007c2a45Smiod asection *input_section, bfd *output_bfd,
813*007c2a45Smiod char **error_message)
814c88b1d6cSniklas {
815*007c2a45Smiod bfd_boolean relocatable;
816c88b1d6cSniklas bfd_reloc_status_type ret;
817c88b1d6cSniklas bfd_vma gp;
818c88b1d6cSniklas
819*007c2a45Smiod if (output_bfd != NULL)
820*007c2a45Smiod relocatable = TRUE;
821c88b1d6cSniklas else
822c88b1d6cSniklas {
823*007c2a45Smiod relocatable = FALSE;
824c88b1d6cSniklas output_bfd = symbol->section->output_section->owner;
825c88b1d6cSniklas }
826c88b1d6cSniklas
827*007c2a45Smiod ret = mips_elf_final_gp (output_bfd, symbol, relocatable, error_message,
828c88b1d6cSniklas &gp);
829c88b1d6cSniklas if (ret != bfd_reloc_ok)
830c88b1d6cSniklas return ret;
831c88b1d6cSniklas
832c074d1c9Sdrahn return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
833*007c2a45Smiod input_section, relocatable,
834c074d1c9Sdrahn data, gp);
8352159047fSniklas }
8362159047fSniklas
837c074d1c9Sdrahn /* Do a R_MIPS_GPREL32 relocation. This is a 32 bit value which must
838c074d1c9Sdrahn become the offset from the gp register. */
839c074d1c9Sdrahn
8402159047fSniklas static bfd_reloc_status_type
mips_elf_gprel32_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message)841*007c2a45Smiod mips_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
842*007c2a45Smiod void *data, asection *input_section, bfd *output_bfd,
843*007c2a45Smiod char **error_message)
844c88b1d6cSniklas {
845*007c2a45Smiod bfd_boolean relocatable;
846c88b1d6cSniklas bfd_reloc_status_type ret;
847c88b1d6cSniklas bfd_vma gp;
848c88b1d6cSniklas
849*007c2a45Smiod if (output_bfd != NULL)
850*007c2a45Smiod relocatable = TRUE;
851c88b1d6cSniklas else
852c88b1d6cSniklas {
853*007c2a45Smiod relocatable = FALSE;
854c88b1d6cSniklas output_bfd = symbol->section->output_section->owner;
855*007c2a45Smiod }
856c88b1d6cSniklas
857*007c2a45Smiod ret = mips_elf_final_gp (output_bfd, symbol, relocatable,
858c88b1d6cSniklas error_message, &gp);
859c88b1d6cSniklas if (ret != bfd_reloc_ok)
860c88b1d6cSniklas return ret;
861c88b1d6cSniklas
862c88b1d6cSniklas return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
863*007c2a45Smiod relocatable, data, gp);
864c88b1d6cSniklas }
865c88b1d6cSniklas
866c88b1d6cSniklas static bfd_reloc_status_type
gprel32_with_gp(bfd * abfd,asymbol * symbol,arelent * reloc_entry,asection * input_section,bfd_boolean relocatable,void * data,bfd_vma gp)867*007c2a45Smiod gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry,
868*007c2a45Smiod asection *input_section, bfd_boolean relocatable,
869*007c2a45Smiod void *data, bfd_vma gp)
870c88b1d6cSniklas {
871c88b1d6cSniklas bfd_vma relocation;
872*007c2a45Smiod bfd_vma val;
873c88b1d6cSniklas
874c88b1d6cSniklas if (bfd_is_com_section (symbol->section))
875c88b1d6cSniklas relocation = 0;
876c88b1d6cSniklas else
877c88b1d6cSniklas relocation = symbol->value;
878c88b1d6cSniklas
879c88b1d6cSniklas relocation += symbol->section->output_section->vma;
880c88b1d6cSniklas relocation += symbol->section->output_offset;
881c88b1d6cSniklas
882c88b1d6cSniklas if (reloc_entry->address > input_section->_cooked_size)
883c88b1d6cSniklas return bfd_reloc_outofrange;
884c88b1d6cSniklas
885c88b1d6cSniklas /* Set val to the offset into the section or symbol. */
886*007c2a45Smiod val = reloc_entry->addend;
887*007c2a45Smiod
888*007c2a45Smiod if (reloc_entry->howto->partial_inplace)
889*007c2a45Smiod val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
890c88b1d6cSniklas
891c88b1d6cSniklas /* Adjust val for the final section location and GP value. If we
892*007c2a45Smiod are producing relocatable output, we don't want to do this for
893c88b1d6cSniklas an external symbol. */
894*007c2a45Smiod if (! relocatable
895c88b1d6cSniklas || (symbol->flags & BSF_SECTION_SYM) != 0)
896c88b1d6cSniklas val += relocation - gp;
897c88b1d6cSniklas
898*007c2a45Smiod if (reloc_entry->howto->partial_inplace)
899*007c2a45Smiod bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
900*007c2a45Smiod else
901*007c2a45Smiod reloc_entry->addend = val;
902c88b1d6cSniklas
903*007c2a45Smiod if (relocatable)
904c88b1d6cSniklas reloc_entry->address += input_section->output_offset;
905c88b1d6cSniklas
906c88b1d6cSniklas return bfd_reloc_ok;
907c88b1d6cSniklas }
908c88b1d6cSniklas
909e93f7393Sniklas /* Handle a 64 bit reloc in a 32 bit MIPS ELF file. These are
910b55d4692Sfgsch generated when addresses are 64 bits. The upper 32 bits are a simple
911e93f7393Sniklas sign extension. */
912e93f7393Sniklas
913e93f7393Sniklas static bfd_reloc_status_type
mips32_64bit_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol ATTRIBUTE_UNUSED,void * data,asection * input_section,bfd * output_bfd,char ** error_message)914*007c2a45Smiod mips32_64bit_reloc (bfd *abfd, arelent *reloc_entry,
915*007c2a45Smiod asymbol *symbol ATTRIBUTE_UNUSED,
916*007c2a45Smiod void *data, asection *input_section,
917*007c2a45Smiod bfd *output_bfd, char **error_message)
918e93f7393Sniklas {
919e93f7393Sniklas bfd_reloc_status_type r;
920e93f7393Sniklas arelent reloc32;
921e93f7393Sniklas unsigned long val;
922e93f7393Sniklas bfd_size_type addr;
923e93f7393Sniklas
924e93f7393Sniklas /* Do a normal 32 bit relocation on the lower 32 bits. */
925e93f7393Sniklas reloc32 = *reloc_entry;
926e93f7393Sniklas if (bfd_big_endian (abfd))
927e93f7393Sniklas reloc32.address += 4;
928c074d1c9Sdrahn reloc32.howto = &elf_mips_howto_table_rel[R_MIPS_32];
929e93f7393Sniklas r = bfd_perform_relocation (abfd, &reloc32, data, input_section,
930e93f7393Sniklas output_bfd, error_message);
931e93f7393Sniklas
932e93f7393Sniklas /* Sign extend into the upper 32 bits. */
933e93f7393Sniklas val = bfd_get_32 (abfd, (bfd_byte *) data + reloc32.address);
934e93f7393Sniklas if ((val & 0x80000000) != 0)
935e93f7393Sniklas val = 0xffffffff;
936e93f7393Sniklas else
937e93f7393Sniklas val = 0;
938e93f7393Sniklas addr = reloc_entry->address;
939e93f7393Sniklas if (bfd_little_endian (abfd))
940e93f7393Sniklas addr += 4;
941*007c2a45Smiod bfd_put_32 (abfd, val, (bfd_byte *) data + addr);
942e93f7393Sniklas
943e93f7393Sniklas return r;
944e93f7393Sniklas }
945e93f7393Sniklas
946b305b0f1Sespie /* Handle a mips16 jump. */
947b305b0f1Sespie
948b305b0f1Sespie static bfd_reloc_status_type
mips16_jump_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry,asymbol * symbol,void * data ATTRIBUTE_UNUSED,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)949*007c2a45Smiod mips16_jump_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
950*007c2a45Smiod asymbol *symbol, void *data ATTRIBUTE_UNUSED,
951*007c2a45Smiod asection *input_section, bfd *output_bfd,
952*007c2a45Smiod char **error_message ATTRIBUTE_UNUSED)
953b305b0f1Sespie {
954*007c2a45Smiod if (output_bfd != NULL
955b305b0f1Sespie && (symbol->flags & BSF_SECTION_SYM) == 0
956b305b0f1Sespie && reloc_entry->addend == 0)
957b305b0f1Sespie {
958b305b0f1Sespie reloc_entry->address += input_section->output_offset;
959b305b0f1Sespie return bfd_reloc_ok;
960b305b0f1Sespie }
961b305b0f1Sespie
962b305b0f1Sespie /* FIXME. */
963b305b0f1Sespie {
964c074d1c9Sdrahn static bfd_boolean warned;
965b305b0f1Sespie
966b305b0f1Sespie if (! warned)
967b305b0f1Sespie (*_bfd_error_handler)
968b305b0f1Sespie (_("Linking mips16 objects into %s format is not supported"),
969b305b0f1Sespie bfd_get_target (input_section->output_section->owner));
970c074d1c9Sdrahn warned = TRUE;
971b305b0f1Sespie }
972b305b0f1Sespie
973b305b0f1Sespie return bfd_reloc_undefined;
974b305b0f1Sespie }
975b305b0f1Sespie
976b305b0f1Sespie /* Handle a mips16 GP relative reloc. */
977b305b0f1Sespie
978b305b0f1Sespie static bfd_reloc_status_type
mips16_gprel_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message)979*007c2a45Smiod mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
980*007c2a45Smiod void *data, asection *input_section, bfd *output_bfd,
981*007c2a45Smiod char **error_message)
982b305b0f1Sespie {
983*007c2a45Smiod bfd_boolean relocatable;
984b305b0f1Sespie bfd_reloc_status_type ret;
985b305b0f1Sespie bfd_vma gp;
986*007c2a45Smiod unsigned short extend = 0;
987*007c2a45Smiod unsigned short insn = 0;
988*007c2a45Smiod bfd_signed_vma val;
989*007c2a45Smiod bfd_vma relocation;
990b305b0f1Sespie
991*007c2a45Smiod /* If we're relocating, and this is an external symbol, we don't want
992*007c2a45Smiod to change anything. */
993b305b0f1Sespie if (output_bfd != NULL
994b305b0f1Sespie && (symbol->flags & BSF_SECTION_SYM) == 0
995*007c2a45Smiod && (symbol->flags & BSF_LOCAL) != 0)
996b305b0f1Sespie {
997b305b0f1Sespie reloc_entry->address += input_section->output_offset;
998b305b0f1Sespie return bfd_reloc_ok;
999b305b0f1Sespie }
1000b305b0f1Sespie
1001b305b0f1Sespie if (output_bfd != NULL)
1002*007c2a45Smiod relocatable = TRUE;
1003b305b0f1Sespie else
1004b305b0f1Sespie {
1005*007c2a45Smiod relocatable = FALSE;
1006b305b0f1Sespie output_bfd = symbol->section->output_section->owner;
1007b305b0f1Sespie }
1008b305b0f1Sespie
1009*007c2a45Smiod ret = mips_elf_final_gp (output_bfd, symbol, relocatable, error_message,
1010b305b0f1Sespie &gp);
1011b305b0f1Sespie if (ret != bfd_reloc_ok)
1012b305b0f1Sespie return ret;
1013b305b0f1Sespie
1014b305b0f1Sespie if (reloc_entry->address > input_section->_cooked_size)
1015b305b0f1Sespie return bfd_reloc_outofrange;
1016b305b0f1Sespie
1017*007c2a45Smiod if (bfd_is_com_section (symbol->section))
1018*007c2a45Smiod relocation = 0;
1019*007c2a45Smiod else
1020*007c2a45Smiod relocation = symbol->value;
1021*007c2a45Smiod
1022*007c2a45Smiod relocation += symbol->section->output_section->vma;
1023*007c2a45Smiod relocation += symbol->section->output_offset;
1024*007c2a45Smiod
1025*007c2a45Smiod /* Set val to the offset into the section or symbol. */
1026*007c2a45Smiod val = reloc_entry->addend;
1027*007c2a45Smiod
1028*007c2a45Smiod if (reloc_entry->howto->partial_inplace)
1029*007c2a45Smiod {
1030b305b0f1Sespie /* Pick up the mips16 extend instruction and the real instruction. */
1031b305b0f1Sespie extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
1032b305b0f1Sespie insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
1033*007c2a45Smiod val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
1034*007c2a45Smiod }
1035b305b0f1Sespie
1036*007c2a45Smiod _bfd_mips_elf_sign_extend(val, 16);
1037b305b0f1Sespie
1038*007c2a45Smiod /* Adjust val for the final section location and GP value. If we
1039*007c2a45Smiod are producing relocatable output, we don't want to do this for
1040*007c2a45Smiod an external symbol. */
1041*007c2a45Smiod if (! relocatable
1042*007c2a45Smiod || (symbol->flags & BSF_SECTION_SYM) != 0)
1043*007c2a45Smiod val += relocation - gp;
1044b305b0f1Sespie
1045*007c2a45Smiod if (reloc_entry->howto->partial_inplace)
1046*007c2a45Smiod {
1047b305b0f1Sespie bfd_put_16 (abfd,
1048*007c2a45Smiod (extend & 0xf800) | ((val >> 11) & 0x1f) | (val & 0x7e0),
1049b305b0f1Sespie (bfd_byte *) data + reloc_entry->address);
1050b305b0f1Sespie bfd_put_16 (abfd,
1051*007c2a45Smiod (insn & 0xffe0) | (val & 0x1f),
1052b305b0f1Sespie (bfd_byte *) data + reloc_entry->address + 2);
1053*007c2a45Smiod }
1054*007c2a45Smiod else
1055*007c2a45Smiod reloc_entry->addend = val;
1056b305b0f1Sespie
1057*007c2a45Smiod if (relocatable)
1058*007c2a45Smiod reloc_entry->address += input_section->output_offset;
1059*007c2a45Smiod else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
1060*007c2a45Smiod return bfd_reloc_overflow;
1061*007c2a45Smiod
1062*007c2a45Smiod return bfd_reloc_ok;
1063b305b0f1Sespie }
1064b305b0f1Sespie
10652159047fSniklas /* A mapping from BFD reloc types to MIPS ELF reloc types. */
10662159047fSniklas
10672159047fSniklas struct elf_reloc_map {
1068c074d1c9Sdrahn bfd_reloc_code_real_type bfd_val;
1069c074d1c9Sdrahn enum elf_mips_reloc_type elf_val;
10702159047fSniklas };
10712159047fSniklas
1072c074d1c9Sdrahn static const struct elf_reloc_map mips_reloc_map[] =
10732159047fSniklas {
1074c074d1c9Sdrahn { BFD_RELOC_NONE, R_MIPS_NONE },
10752159047fSniklas { BFD_RELOC_16, R_MIPS_16 },
10762159047fSniklas { BFD_RELOC_32, R_MIPS_32 },
1077c074d1c9Sdrahn /* There is no BFD reloc for R_MIPS_REL32. */
1078e93f7393Sniklas { BFD_RELOC_64, R_MIPS_64 },
10792159047fSniklas { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
10802159047fSniklas { BFD_RELOC_HI16_S, R_MIPS_HI16 },
10812159047fSniklas { BFD_RELOC_LO16, R_MIPS_LO16 },
1082c074d1c9Sdrahn { BFD_RELOC_GPREL16, R_MIPS_GPREL16 },
10832159047fSniklas { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
10842159047fSniklas { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
10852159047fSniklas { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
10862159047fSniklas { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
1087c074d1c9Sdrahn { BFD_RELOC_GPREL32, R_MIPS_GPREL32 },
1088c88b1d6cSniklas { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
1089c88b1d6cSniklas { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
1090c88b1d6cSniklas { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
1091b305b0f1Sespie { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
1092b305b0f1Sespie { BFD_RELOC_MIPS_SUB, R_MIPS_SUB },
1093b305b0f1Sespie { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE },
1094b305b0f1Sespie { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST },
1095b305b0f1Sespie { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP }
10962159047fSniklas };
10972159047fSniklas
10982159047fSniklas /* Given a BFD reloc type, return a howto structure. */
10992159047fSniklas
11002159047fSniklas static reloc_howto_type *
bfd_elf32_bfd_reloc_type_lookup(bfd * abfd,bfd_reloc_code_real_type code)1101*007c2a45Smiod bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
11022159047fSniklas {
11032159047fSniklas unsigned int i;
1104c074d1c9Sdrahn reloc_howto_type *howto_table = elf_mips_howto_table_rel;
11052159047fSniklas
1106c074d1c9Sdrahn for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map);
1107c074d1c9Sdrahn i++)
11082159047fSniklas {
1109c074d1c9Sdrahn if (mips_reloc_map[i].bfd_val == code)
1110c074d1c9Sdrahn return &howto_table[(int) mips_reloc_map[i].elf_val];
11112159047fSniklas }
1112b305b0f1Sespie
1113b305b0f1Sespie switch (code)
1114b305b0f1Sespie {
1115b305b0f1Sespie default:
1116b305b0f1Sespie bfd_set_error (bfd_error_bad_value);
11172159047fSniklas return NULL;
1118b305b0f1Sespie
1119b305b0f1Sespie case BFD_RELOC_CTOR:
1120b305b0f1Sespie /* We need to handle BFD_RELOC_CTOR specially.
1121b305b0f1Sespie Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the
1122c074d1c9Sdrahn size of addresses of the ABI. */
1123c074d1c9Sdrahn if ((elf_elfheader (abfd)->e_flags & (E_MIPS_ABI_O64
1124c074d1c9Sdrahn | E_MIPS_ABI_EABI64)) != 0)
1125b305b0f1Sespie return &elf_mips_ctor64_howto;
1126c074d1c9Sdrahn else
1127c074d1c9Sdrahn return &howto_table[(int) R_MIPS_32];
1128b305b0f1Sespie
1129b305b0f1Sespie case BFD_RELOC_MIPS16_JMP:
1130b305b0f1Sespie return &elf_mips16_jump_howto;
1131b305b0f1Sespie case BFD_RELOC_MIPS16_GPREL:
1132b305b0f1Sespie return &elf_mips16_gprel_howto;
1133b305b0f1Sespie case BFD_RELOC_VTABLE_INHERIT:
1134b305b0f1Sespie return &elf_mips_gnu_vtinherit_howto;
1135b305b0f1Sespie case BFD_RELOC_VTABLE_ENTRY:
1136b305b0f1Sespie return &elf_mips_gnu_vtentry_howto;
1137b305b0f1Sespie case BFD_RELOC_PCREL_HI16_S:
1138b305b0f1Sespie return &elf_mips_gnu_rel_hi16;
1139b305b0f1Sespie case BFD_RELOC_PCREL_LO16:
1140b305b0f1Sespie return &elf_mips_gnu_rel_lo16;
1141b305b0f1Sespie case BFD_RELOC_16_PCREL_S2:
1142b305b0f1Sespie return &elf_mips_gnu_rel16_s2;
1143b305b0f1Sespie case BFD_RELOC_64_PCREL:
1144b305b0f1Sespie return &elf_mips_gnu_pcrel64;
1145b305b0f1Sespie case BFD_RELOC_32_PCREL:
1146b305b0f1Sespie return &elf_mips_gnu_pcrel32;
1147b305b0f1Sespie }
11482159047fSniklas }
11492159047fSniklas
1150c074d1c9Sdrahn /* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */
1151b305b0f1Sespie
1152b305b0f1Sespie static reloc_howto_type *
mips_elf32_rtype_to_howto(unsigned int r_type,bfd_boolean rela_p ATTRIBUTE_UNUSED)1153*007c2a45Smiod mips_elf32_rtype_to_howto (unsigned int r_type,
1154*007c2a45Smiod bfd_boolean rela_p ATTRIBUTE_UNUSED)
1155b305b0f1Sespie {
1156b305b0f1Sespie switch (r_type)
1157b305b0f1Sespie {
1158b305b0f1Sespie case R_MIPS16_26:
1159b305b0f1Sespie return &elf_mips16_jump_howto;
1160b305b0f1Sespie case R_MIPS16_GPREL:
1161b305b0f1Sespie return &elf_mips16_gprel_howto;
1162b305b0f1Sespie case R_MIPS_GNU_VTINHERIT:
1163b305b0f1Sespie return &elf_mips_gnu_vtinherit_howto;
1164b305b0f1Sespie case R_MIPS_GNU_VTENTRY:
1165b305b0f1Sespie return &elf_mips_gnu_vtentry_howto;
1166b305b0f1Sespie case R_MIPS_GNU_REL_HI16:
1167b305b0f1Sespie return &elf_mips_gnu_rel_hi16;
1168b305b0f1Sespie case R_MIPS_GNU_REL_LO16:
1169b305b0f1Sespie return &elf_mips_gnu_rel_lo16;
1170b305b0f1Sespie case R_MIPS_GNU_REL16_S2:
1171b305b0f1Sespie return &elf_mips_gnu_rel16_s2;
1172b305b0f1Sespie case R_MIPS_PC64:
1173b305b0f1Sespie return &elf_mips_gnu_pcrel64;
1174b305b0f1Sespie case R_MIPS_PC32:
1175b305b0f1Sespie return &elf_mips_gnu_pcrel32;
1176b305b0f1Sespie default:
1177b305b0f1Sespie BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
1178c074d1c9Sdrahn return &elf_mips_howto_table_rel[r_type];
1179b305b0f1Sespie }
1180b305b0f1Sespie }
1181b305b0f1Sespie
1182c074d1c9Sdrahn /* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */
11832159047fSniklas
11842159047fSniklas static void
mips_info_to_howto_rel(bfd * abfd,arelent * cache_ptr,Elf_Internal_Rela * dst)1185*007c2a45Smiod mips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
11862159047fSniklas {
11872159047fSniklas unsigned int r_type;
11882159047fSniklas
11892159047fSniklas r_type = ELF32_R_TYPE (dst->r_info);
1190c074d1c9Sdrahn cache_ptr->howto = mips_elf32_rtype_to_howto (r_type, FALSE);
11912159047fSniklas
11922159047fSniklas /* The addend for a GPREL16 or LITERAL relocation comes from the GP
11932159047fSniklas value for the object file. We get the addend now, rather than
11942159047fSniklas when we do the relocation, because the symbol manipulations done
11952159047fSniklas by the linker may cause us to lose track of the input BFD. */
11962159047fSniklas if (((*cache_ptr->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0
11972159047fSniklas && (r_type == (unsigned int) R_MIPS_GPREL16
11982159047fSniklas || r_type == (unsigned int) R_MIPS_LITERAL))
11992159047fSniklas cache_ptr->addend = elf_gp (abfd);
12002159047fSniklas }
1201b305b0f1Sespie
1202c074d1c9Sdrahn /* Given a MIPS Elf_Internal_Rela, fill in an arelent structure. */
1203b305b0f1Sespie
1204b305b0f1Sespie static void
mips_info_to_howto_rela(bfd * abfd,arelent * cache_ptr,Elf_Internal_Rela * dst)1205*007c2a45Smiod mips_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
1206b305b0f1Sespie {
1207c074d1c9Sdrahn mips_info_to_howto_rel (abfd, cache_ptr, dst);
1208b305b0f1Sespie
1209b305b0f1Sespie /* If we ever need to do any extra processing with dst->r_addend
1210c074d1c9Sdrahn (the field omitted in an Elf_Internal_Rel) we can do it here. */
1211b305b0f1Sespie }
12122159047fSniklas
12132159047fSniklas /* Determine whether a symbol is global for the purposes of splitting
12142159047fSniklas the symbol table into global symbols and local symbols. At least
12152159047fSniklas on Irix 5, this split must be between section symbols and all other
12162159047fSniklas symbols. On most ELF targets the split is between static symbols
12172159047fSniklas and externally visible symbols. */
12182159047fSniklas
1219c074d1c9Sdrahn static bfd_boolean
mips_elf_sym_is_global(bfd * abfd ATTRIBUTE_UNUSED,asymbol * sym)1220*007c2a45Smiod mips_elf_sym_is_global (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
12212159047fSniklas {
1222b55d4692Sfgsch if (SGI_COMPAT (abfd))
1223c074d1c9Sdrahn return (sym->flags & BSF_SECTION_SYM) == 0;
1224b55d4692Sfgsch else
1225b55d4692Sfgsch return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
1226b55d4692Sfgsch || bfd_is_und_section (bfd_get_section (sym))
1227b55d4692Sfgsch || bfd_is_com_section (bfd_get_section (sym)));
12282159047fSniklas }
12292159047fSniklas
1230c074d1c9Sdrahn /* Set the right machine number for a MIPS ELF file. */
12312159047fSniklas
1232c074d1c9Sdrahn static bfd_boolean
mips_elf32_object_p(bfd * abfd)1233*007c2a45Smiod mips_elf32_object_p (bfd *abfd)
12342159047fSniklas {
1235c074d1c9Sdrahn unsigned long mach;
1236c074d1c9Sdrahn
1237c074d1c9Sdrahn /* Irix 5 and 6 are broken. Object file symbol tables are not always
12382159047fSniklas sorted correctly such that local symbols precede global symbols,
12392159047fSniklas and the sh_info field in the symbol table is not always right. */
1240b55d4692Sfgsch if (SGI_COMPAT (abfd))
1241c074d1c9Sdrahn elf_bad_symtab (abfd) = TRUE;
1242b305b0f1Sespie
1243c074d1c9Sdrahn if (ABI_N32_P (abfd))
1244c074d1c9Sdrahn return FALSE;
1245b305b0f1Sespie
1246c074d1c9Sdrahn mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags);
1247c074d1c9Sdrahn bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach);
12482159047fSniklas
1249c074d1c9Sdrahn return TRUE;
12502159047fSniklas }
12512159047fSniklas
12522159047fSniklas /* MIPS ELF local labels start with '$', not 'L'. */
12532159047fSniklas
1254c074d1c9Sdrahn static bfd_boolean
mips_elf_is_local_label_name(bfd * abfd,const char * name)1255*007c2a45Smiod mips_elf_is_local_label_name (bfd *abfd, const char *name)
12562159047fSniklas {
1257b305b0f1Sespie if (name[0] == '$')
1258c074d1c9Sdrahn return TRUE;
1259b305b0f1Sespie
1260b305b0f1Sespie /* On Irix 6, the labels go back to starting with '.', so we accept
1261b305b0f1Sespie the generic ELF local label syntax as well. */
1262b305b0f1Sespie return _bfd_elf_is_local_label_name (abfd, name);
12632159047fSniklas }
1264c074d1c9Sdrahn
1265c074d1c9Sdrahn /* Support for core dump NOTE sections. */
1266c074d1c9Sdrahn static bfd_boolean
elf32_mips_grok_prstatus(bfd * abfd,Elf_Internal_Note * note)1267*007c2a45Smiod elf32_mips_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
12682159047fSniklas {
1269c074d1c9Sdrahn int offset;
1270c074d1c9Sdrahn unsigned int raw_size;
12712159047fSniklas
1272c074d1c9Sdrahn switch (note->descsz)
12732159047fSniklas {
1274c074d1c9Sdrahn default:
1275c074d1c9Sdrahn return FALSE;
12762159047fSniklas
1277c074d1c9Sdrahn case 256: /* Linux/MIPS */
1278c074d1c9Sdrahn /* pr_cursig */
1279c074d1c9Sdrahn elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
12802159047fSniklas
1281c074d1c9Sdrahn /* pr_pid */
1282c074d1c9Sdrahn elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
12832159047fSniklas
1284c074d1c9Sdrahn /* pr_reg */
1285c074d1c9Sdrahn offset = 72;
1286c074d1c9Sdrahn raw_size = 180;
1287c074d1c9Sdrahn
1288c074d1c9Sdrahn break;
12892159047fSniklas }
12902159047fSniklas
1291c074d1c9Sdrahn /* Make a ".reg/999" section. */
1292c074d1c9Sdrahn return _bfd_elfcore_make_pseudosection (abfd, ".reg",
1293c074d1c9Sdrahn raw_size, note->descpos + offset);
1294c074d1c9Sdrahn }
1295c074d1c9Sdrahn
1296c074d1c9Sdrahn static bfd_boolean
elf32_mips_grok_psinfo(bfd * abfd,Elf_Internal_Note * note)1297*007c2a45Smiod elf32_mips_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
12982159047fSniklas {
1299c074d1c9Sdrahn switch (note->descsz)
13002159047fSniklas {
1301c074d1c9Sdrahn default:
1302c074d1c9Sdrahn return FALSE;
13032159047fSniklas
1304c074d1c9Sdrahn case 128: /* Linux/MIPS elf_prpsinfo */
1305c074d1c9Sdrahn elf_tdata (abfd)->core_program
1306c074d1c9Sdrahn = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
1307c074d1c9Sdrahn elf_tdata (abfd)->core_command
1308c074d1c9Sdrahn = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
13092159047fSniklas }
13102159047fSniklas
1311c074d1c9Sdrahn /* Note that for some reason, a spurious space is tacked
1312c074d1c9Sdrahn onto the end of the args in some (at least one anyway)
1313c074d1c9Sdrahn implementations, so strip it off if it exists. */
1314c074d1c9Sdrahn
13152159047fSniklas {
1316c074d1c9Sdrahn char *command = elf_tdata (abfd)->core_command;
1317c074d1c9Sdrahn int n = strlen (command);
1318c074d1c9Sdrahn
1319c074d1c9Sdrahn if (0 < n && command[n - 1] == ' ')
1320c074d1c9Sdrahn command[n - 1] = '\0';
13212159047fSniklas }
13222159047fSniklas
1323c074d1c9Sdrahn return TRUE;
13242159047fSniklas }
13252159047fSniklas
1326c074d1c9Sdrahn /* Depending on the target vector we generate some version of Irix
1327c074d1c9Sdrahn executables or "normal" MIPS ELF ABI executables. */
1328c074d1c9Sdrahn static irix_compat_t
elf32_mips_irix_compat(bfd * abfd)1329*007c2a45Smiod elf32_mips_irix_compat (bfd *abfd)
13302159047fSniklas {
1331c074d1c9Sdrahn if ((abfd->xvec == &bfd_elf32_bigmips_vec)
1332c074d1c9Sdrahn || (abfd->xvec == &bfd_elf32_littlemips_vec))
1333c074d1c9Sdrahn return ict_irix5;
13342159047fSniklas else
1335c074d1c9Sdrahn return ict_none;
13362159047fSniklas }
13372159047fSniklas
1338c074d1c9Sdrahn /* Given a data section and an in-memory embedded reloc section, store
1339c074d1c9Sdrahn relocation information into the embedded reloc section which can be
1340c074d1c9Sdrahn used at runtime to relocate the data section. This is called by the
1341c074d1c9Sdrahn linker when the --embedded-relocs switch is used. This is called
1342c074d1c9Sdrahn after the add_symbols entry point has been called for all the
1343c074d1c9Sdrahn objects, and before the final_link entry point is called. */
1344c88b1d6cSniklas
1345c074d1c9Sdrahn bfd_boolean
bfd_mips_elf32_create_embedded_relocs(bfd * abfd,struct bfd_link_info * info,asection * datasec,asection * relsec,char ** errmsg)1346*007c2a45Smiod bfd_mips_elf32_create_embedded_relocs (bfd *abfd, struct bfd_link_info *info,
1347*007c2a45Smiod asection *datasec, asection *relsec,
1348*007c2a45Smiod char **errmsg)
1349c88b1d6cSniklas {
1350c88b1d6cSniklas Elf_Internal_Shdr *symtab_hdr;
1351c074d1c9Sdrahn Elf_Internal_Sym *isymbuf = NULL;
1352c074d1c9Sdrahn Elf_Internal_Rela *internal_relocs = NULL;
1353c074d1c9Sdrahn Elf_Internal_Rela *irel, *irelend;
1354c88b1d6cSniklas bfd_byte *p;
1355c88b1d6cSniklas
1356*007c2a45Smiod BFD_ASSERT (! info->relocatable);
1357c88b1d6cSniklas
1358c074d1c9Sdrahn *errmsg = NULL;
1359c88b1d6cSniklas
1360c074d1c9Sdrahn if (datasec->reloc_count == 0)
1361c074d1c9Sdrahn return TRUE;
1362c88b1d6cSniklas
1363c074d1c9Sdrahn /* Read this BFD's symbols if we haven't done so already, or get the cached
1364c074d1c9Sdrahn copy if it exists. */
1365c074d1c9Sdrahn symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1366c074d1c9Sdrahn if (symtab_hdr->sh_info != 0)
1367c88b1d6cSniklas {
1368c074d1c9Sdrahn isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1369c074d1c9Sdrahn if (isymbuf == NULL)
1370c074d1c9Sdrahn isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1371c074d1c9Sdrahn symtab_hdr->sh_info, 0,
1372c074d1c9Sdrahn NULL, NULL, NULL);
1373c074d1c9Sdrahn if (isymbuf == NULL)
1374c074d1c9Sdrahn goto error_return;
1375c88b1d6cSniklas }
1376b305b0f1Sespie
1377c074d1c9Sdrahn /* Get a copy of the native relocations. */
1378*007c2a45Smiod internal_relocs = _bfd_elf_link_read_relocs (abfd, datasec, NULL, NULL,
1379*007c2a45Smiod info->keep_memory);
1380c074d1c9Sdrahn if (internal_relocs == NULL)
13812159047fSniklas goto error_return;
13822159047fSniklas
1383*007c2a45Smiod relsec->contents = bfd_alloc (abfd, datasec->reloc_count * 12);
1384c074d1c9Sdrahn if (relsec->contents == NULL)
13852159047fSniklas goto error_return;
13862159047fSniklas
1387c074d1c9Sdrahn p = relsec->contents;
13882159047fSniklas
1389c074d1c9Sdrahn irelend = internal_relocs + datasec->reloc_count;
13902159047fSniklas
1391c074d1c9Sdrahn for (irel = internal_relocs; irel < irelend; irel++, p += 12)
13922159047fSniklas {
1393c074d1c9Sdrahn asection *targetsec;
13942159047fSniklas
1395c074d1c9Sdrahn /* We are going to write a four byte longword into the runtime
1396c074d1c9Sdrahn reloc section. The longword will be the address in the data
1397c074d1c9Sdrahn section which must be relocated. It is followed by the name
1398c074d1c9Sdrahn of the target section NUL-padded or truncated to 8
1399c074d1c9Sdrahn characters. */
1400c074d1c9Sdrahn
1401c074d1c9Sdrahn /* We can only relocate absolute longword relocs at run time. */
1402c074d1c9Sdrahn if ((ELF32_R_TYPE (irel->r_info) != (int) R_MIPS_32) &&
1403c074d1c9Sdrahn (ELF32_R_TYPE (irel->r_info) != (int) R_MIPS_64))
14042159047fSniklas {
1405c074d1c9Sdrahn *errmsg = _("unsupported reloc type");
1406c074d1c9Sdrahn bfd_set_error (bfd_error_bad_value);
1407c074d1c9Sdrahn goto error_return;
1408c074d1c9Sdrahn }
1409c074d1c9Sdrahn /* Get the target section referred to by the reloc. */
1410c074d1c9Sdrahn if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1411c074d1c9Sdrahn {
1412c074d1c9Sdrahn Elf_Internal_Sym *isym;
1413c074d1c9Sdrahn
1414c074d1c9Sdrahn /* A local symbol. */
1415c074d1c9Sdrahn isym = isymbuf + ELF32_R_SYM (irel->r_info);
1416c074d1c9Sdrahn targetsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1417c074d1c9Sdrahn }
14182159047fSniklas else
14192159047fSniklas {
1420c074d1c9Sdrahn unsigned long indx;
1421c074d1c9Sdrahn struct elf_link_hash_entry *h;
14222159047fSniklas
1423c074d1c9Sdrahn /* An external symbol. */
1424c074d1c9Sdrahn indx = ELF32_R_SYM (irel->r_info);
1425c074d1c9Sdrahn h = elf_sym_hashes (abfd)[indx];
1426c074d1c9Sdrahn targetsec = NULL;
1427c074d1c9Sdrahn /*
1428c074d1c9Sdrahn For some reason, in certain programs, the symbol will
1429c074d1c9Sdrahn not be in the hash table. It seems to happen when you
1430c074d1c9Sdrahn declare a static table of pointers to const external structures.
1431c074d1c9Sdrahn In this case, the relocs are relative to data, not
1432c074d1c9Sdrahn text, so just treating it like an undefined link
1433c074d1c9Sdrahn should be sufficient. */
1434c074d1c9Sdrahn BFD_ASSERT(h != NULL);
1435c074d1c9Sdrahn if (h->root.type == bfd_link_hash_defined
1436c074d1c9Sdrahn || h->root.type == bfd_link_hash_defweak)
1437c074d1c9Sdrahn targetsec = h->root.u.def.section;
14382159047fSniklas }
14392159047fSniklas
1440c074d1c9Sdrahn
1441c074d1c9Sdrahn /*
1442c074d1c9Sdrahn Set the low bit of the relocation offset if it's a MIPS64 reloc.
1443c074d1c9Sdrahn Relocations will always be on (at least) 32-bit boundaries. */
1444c074d1c9Sdrahn
1445c074d1c9Sdrahn bfd_put_32 (abfd, ((irel->r_offset + datasec->output_offset) +
1446c074d1c9Sdrahn ((ELF32_R_TYPE (irel->r_info) == (int) R_MIPS_64) ? 1 : 0)),
1447c074d1c9Sdrahn p);
1448c074d1c9Sdrahn memset (p + 4, 0, 8);
1449c074d1c9Sdrahn if (targetsec != NULL)
1450c074d1c9Sdrahn strncpy (p + 4, targetsec->output_section->name, 8);
14512159047fSniklas }
14522159047fSniklas
1453c074d1c9Sdrahn if (internal_relocs != NULL
1454c074d1c9Sdrahn && elf_section_data (datasec)->relocs != internal_relocs)
1455c074d1c9Sdrahn free (internal_relocs);
1456c074d1c9Sdrahn if (isymbuf != NULL
1457c074d1c9Sdrahn && symtab_hdr->contents != (unsigned char *) isymbuf)
1458c074d1c9Sdrahn free (isymbuf);
1459c074d1c9Sdrahn return TRUE;
14602159047fSniklas
14612159047fSniklas error_return:
1462c074d1c9Sdrahn if (internal_relocs != NULL
1463c074d1c9Sdrahn && elf_section_data (datasec)->relocs != internal_relocs)
1464c074d1c9Sdrahn free (internal_relocs);
1465c074d1c9Sdrahn if (isymbuf != NULL
1466c074d1c9Sdrahn && symtab_hdr->contents != (unsigned char *) isymbuf)
1467c074d1c9Sdrahn free (isymbuf);
1468c074d1c9Sdrahn return FALSE;
14692159047fSniklas }
14702159047fSniklas
14712159047fSniklas /* ECOFF swapping routines. These are used when dealing with the
14722159047fSniklas .mdebug section, which is in the ECOFF debugging format. */
1473b55d4692Sfgsch static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
14742159047fSniklas /* Symbol table magic number. */
14752159047fSniklas magicSym,
14762159047fSniklas /* Alignment of debugging information. E.g., 4. */
14772159047fSniklas 4,
14782159047fSniklas /* Sizes of external symbolic information. */
14792159047fSniklas sizeof (struct hdr_ext),
14802159047fSniklas sizeof (struct dnr_ext),
14812159047fSniklas sizeof (struct pdr_ext),
14822159047fSniklas sizeof (struct sym_ext),
14832159047fSniklas sizeof (struct opt_ext),
14842159047fSniklas sizeof (struct fdr_ext),
14852159047fSniklas sizeof (struct rfd_ext),
14862159047fSniklas sizeof (struct ext_ext),
14872159047fSniklas /* Functions to swap in external symbolic data. */
14882159047fSniklas ecoff_swap_hdr_in,
14892159047fSniklas ecoff_swap_dnr_in,
14902159047fSniklas ecoff_swap_pdr_in,
14912159047fSniklas ecoff_swap_sym_in,
14922159047fSniklas ecoff_swap_opt_in,
14932159047fSniklas ecoff_swap_fdr_in,
14942159047fSniklas ecoff_swap_rfd_in,
14952159047fSniklas ecoff_swap_ext_in,
14962159047fSniklas _bfd_ecoff_swap_tir_in,
14972159047fSniklas _bfd_ecoff_swap_rndx_in,
14982159047fSniklas /* Functions to swap out external symbolic data. */
14992159047fSniklas ecoff_swap_hdr_out,
15002159047fSniklas ecoff_swap_dnr_out,
15012159047fSniklas ecoff_swap_pdr_out,
15022159047fSniklas ecoff_swap_sym_out,
15032159047fSniklas ecoff_swap_opt_out,
15042159047fSniklas ecoff_swap_fdr_out,
15052159047fSniklas ecoff_swap_rfd_out,
15062159047fSniklas ecoff_swap_ext_out,
15072159047fSniklas _bfd_ecoff_swap_tir_out,
15082159047fSniklas _bfd_ecoff_swap_rndx_out,
15092159047fSniklas /* Function to read in symbolic data. */
1510c88b1d6cSniklas _bfd_mips_elf_read_ecoff_info
15112159047fSniklas };
15122159047fSniklas
15132159047fSniklas #define ELF_ARCH bfd_arch_mips
15142159047fSniklas #define ELF_MACHINE_CODE EM_MIPS
15150c6d0228Sniklas
1516c074d1c9Sdrahn #define elf_backend_collect TRUE
1517c074d1c9Sdrahn #define elf_backend_type_change_ok TRUE
1518c074d1c9Sdrahn #define elf_backend_can_gc_sections TRUE
1519b305b0f1Sespie #define elf_info_to_howto mips_info_to_howto_rela
15202159047fSniklas #define elf_info_to_howto_rel mips_info_to_howto_rel
15212159047fSniklas #define elf_backend_sym_is_global mips_elf_sym_is_global
1522c074d1c9Sdrahn #define elf_backend_object_p mips_elf32_object_p
1523c074d1c9Sdrahn #define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing
1524c074d1c9Sdrahn #define elf_backend_section_processing _bfd_mips_elf_section_processing
1525b305b0f1Sespie #define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr
1526c88b1d6cSniklas #define elf_backend_fake_sections _bfd_mips_elf_fake_sections
15272159047fSniklas #define elf_backend_section_from_bfd_section \
1528c88b1d6cSniklas _bfd_mips_elf_section_from_bfd_section
1529b305b0f1Sespie #define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook
1530c074d1c9Sdrahn #define elf_backend_link_output_symbol_hook \
1531c074d1c9Sdrahn _bfd_mips_elf_link_output_symbol_hook
1532b305b0f1Sespie #define elf_backend_create_dynamic_sections \
1533b305b0f1Sespie _bfd_mips_elf_create_dynamic_sections
1534b305b0f1Sespie #define elf_backend_check_relocs _bfd_mips_elf_check_relocs
1535b305b0f1Sespie #define elf_backend_adjust_dynamic_symbol \
1536b305b0f1Sespie _bfd_mips_elf_adjust_dynamic_symbol
1537b305b0f1Sespie #define elf_backend_always_size_sections \
1538b305b0f1Sespie _bfd_mips_elf_always_size_sections
1539b305b0f1Sespie #define elf_backend_size_dynamic_sections \
1540b305b0f1Sespie _bfd_mips_elf_size_dynamic_sections
1541b305b0f1Sespie #define elf_backend_relocate_section _bfd_mips_elf_relocate_section
1542b305b0f1Sespie #define elf_backend_finish_dynamic_symbol \
1543b305b0f1Sespie _bfd_mips_elf_finish_dynamic_symbol
1544b305b0f1Sespie #define elf_backend_finish_dynamic_sections \
1545b305b0f1Sespie _bfd_mips_elf_finish_dynamic_sections
1546c074d1c9Sdrahn #define elf_backend_final_write_processing \
1547c074d1c9Sdrahn _bfd_mips_elf_final_write_processing
1548c074d1c9Sdrahn #define elf_backend_additional_program_headers \
1549c074d1c9Sdrahn _bfd_mips_elf_additional_program_headers
1550c074d1c9Sdrahn #define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
1551b305b0f1Sespie #define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook
1552b305b0f1Sespie #define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
1553c074d1c9Sdrahn #define elf_backend_copy_indirect_symbol \
1554c074d1c9Sdrahn _bfd_mips_elf_copy_indirect_symbol
1555c074d1c9Sdrahn #define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
1556c074d1c9Sdrahn #define elf_backend_grok_prstatus elf32_mips_grok_prstatus
1557c074d1c9Sdrahn #define elf_backend_grok_psinfo elf32_mips_grok_psinfo
1558c074d1c9Sdrahn #define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap
15592159047fSniklas
1560b305b0f1Sespie #define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
1561c074d1c9Sdrahn #define elf_backend_may_use_rel_p 1
1562c074d1c9Sdrahn #define elf_backend_may_use_rela_p 0
1563c074d1c9Sdrahn #define elf_backend_default_use_rela_p 0
1564c074d1c9Sdrahn #define elf_backend_sign_extend_vma TRUE
1565b305b0f1Sespie
1566c074d1c9Sdrahn #define elf_backend_discard_info _bfd_mips_elf_discard_info
1567c074d1c9Sdrahn #define elf_backend_ignore_discarded_relocs \
1568c074d1c9Sdrahn _bfd_mips_elf_ignore_discarded_relocs
1569c074d1c9Sdrahn #define elf_backend_mips_irix_compat elf32_mips_irix_compat
1570c074d1c9Sdrahn #define elf_backend_mips_rtype_to_howto mips_elf32_rtype_to_howto
1571b305b0f1Sespie #define bfd_elf32_bfd_is_local_label_name \
1572b305b0f1Sespie mips_elf_is_local_label_name
1573c88b1d6cSniklas #define bfd_elf32_find_nearest_line _bfd_mips_elf_find_nearest_line
1574c074d1c9Sdrahn #define bfd_elf32_new_section_hook _bfd_mips_elf_new_section_hook
1575c88b1d6cSniklas #define bfd_elf32_set_section_contents _bfd_mips_elf_set_section_contents
1576c074d1c9Sdrahn #define bfd_elf32_bfd_get_relocated_section_contents \
1577c074d1c9Sdrahn _bfd_elf_mips_get_relocated_section_contents
15782159047fSniklas #define bfd_elf32_bfd_link_hash_table_create \
1579b305b0f1Sespie _bfd_mips_elf_link_hash_table_create
1580b305b0f1Sespie #define bfd_elf32_bfd_final_link _bfd_mips_elf_final_link
1581c88b1d6cSniklas #define bfd_elf32_bfd_merge_private_bfd_data \
1582c88b1d6cSniklas _bfd_mips_elf_merge_private_bfd_data
1583c88b1d6cSniklas #define bfd_elf32_bfd_set_private_flags _bfd_mips_elf_set_private_flags
1584b305b0f1Sespie #define bfd_elf32_bfd_print_private_bfd_data \
1585b305b0f1Sespie _bfd_mips_elf_print_private_bfd_data
1586c074d1c9Sdrahn
1587c074d1c9Sdrahn /* Support for SGI-ish mips targets. */
1588c074d1c9Sdrahn #define TARGET_LITTLE_SYM bfd_elf32_littlemips_vec
1589c074d1c9Sdrahn #define TARGET_LITTLE_NAME "elf32-littlemips"
1590c074d1c9Sdrahn #define TARGET_BIG_SYM bfd_elf32_bigmips_vec
1591c074d1c9Sdrahn #define TARGET_BIG_NAME "elf32-bigmips"
1592c074d1c9Sdrahn
1593*007c2a45Smiod /* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses
1594*007c2a45Smiod a value of 0x1000, and we are compatible. */
1595*007c2a45Smiod #define ELF_MAXPAGESIZE 0x1000
1596*007c2a45Smiod
15972159047fSniklas #include "elf32-target.h"
1598b55d4692Sfgsch
1599c074d1c9Sdrahn /* Support for traditional mips targets. */
1600b55d4692Sfgsch #undef TARGET_LITTLE_SYM
1601b55d4692Sfgsch #undef TARGET_LITTLE_NAME
1602b55d4692Sfgsch #undef TARGET_BIG_SYM
1603b55d4692Sfgsch #undef TARGET_BIG_NAME
1604b55d4692Sfgsch
1605*007c2a45Smiod #undef ELF_MAXPAGESIZE
1606*007c2a45Smiod
1607b55d4692Sfgsch #define TARGET_LITTLE_SYM bfd_elf32_tradlittlemips_vec
1608b55d4692Sfgsch #define TARGET_LITTLE_NAME "elf32-tradlittlemips"
1609b55d4692Sfgsch #define TARGET_BIG_SYM bfd_elf32_tradbigmips_vec
1610b55d4692Sfgsch #define TARGET_BIG_NAME "elf32-tradbigmips"
1611b55d4692Sfgsch
1612*007c2a45Smiod /* The SVR4 MIPS ABI says that this should be 0x10000, and Linux uses
1613*007c2a45Smiod page sizes of up to that limit, so we need to respect it. */
1614*007c2a45Smiod #define ELF_MAXPAGESIZE 0x10000
1615*007c2a45Smiod #define elf32_bed elf32_tradbed
1616*007c2a45Smiod
1617c074d1c9Sdrahn /* Include the target file again for this target. */
1618b55d4692Sfgsch #include "elf32-target.h"
1619