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