1179407Sobrien/* MIPS-specific support for 32-bit ELF 2179407Sobrien Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 3218822Sdim 2003, 2004, 2005, 2007 Free Software Foundation, Inc. 4179407Sobrien 5179407Sobrien Most of the information added by Ian Lance Taylor, Cygnus Support, 6179407Sobrien <ian@cygnus.com>. 7179407Sobrien N32/64 ABI support added by Mark Mitchell, CodeSourcery, LLC. 8179407Sobrien <mark@codesourcery.com> 9179407Sobrien Traditional MIPS targets support added by Koundinya.K, Dansk Data 10179407Sobrien Elektronik & Operations Research Group. <kk@ddeorg.soft.net> 11179407Sobrien 12179407SobrienThis file is part of BFD, the Binary File Descriptor library. 13179407Sobrien 14179407SobrienThis program is free software; you can redistribute it and/or modify 15179407Sobrienit under the terms of the GNU General Public License as published by 16179407Sobrienthe Free Software Foundation; either version 2 of the License, or 17179407Sobrien(at your option) any later version. 18179407Sobrien 19179407SobrienThis program is distributed in the hope that it will be useful, 20179407Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 21179407SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22179407SobrienGNU General Public License for more details. 23179407Sobrien 24179407SobrienYou should have received a copy of the GNU General Public License 25179407Sobrienalong with this program; if not, write to the Free Software 26218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 27179407Sobrien 28179407Sobrien/* This file handles MIPS ELF targets. SGI Irix 5 uses a slightly 29179407Sobrien different MIPS ELF from other targets. This matters when linking. 30179407Sobrien This file supports both, switching at runtime. */ 31179407Sobrien 32218822Sdim#include "sysdep.h" 33179407Sobrien#include "bfd.h" 34179407Sobrien#include "libbfd.h" 35179407Sobrien#include "bfdlink.h" 36179407Sobrien#include "genlink.h" 37179407Sobrien#include "elf-bfd.h" 38179407Sobrien#include "elfxx-mips.h" 39179407Sobrien#include "elf/mips.h" 40218822Sdim#include "elf-vxworks.h" 41179407Sobrien 42179407Sobrien/* Get the ECOFF swapping routines. */ 43179407Sobrien#include "coff/sym.h" 44179407Sobrien#include "coff/symconst.h" 45179407Sobrien#include "coff/internal.h" 46179407Sobrien#include "coff/ecoff.h" 47179407Sobrien#include "coff/mips.h" 48179407Sobrien#define ECOFF_SIGNED_32 49179407Sobrien#include "ecoffswap.h" 50179407Sobrien 51179407Sobrienstatic bfd_reloc_status_type gprel32_with_gp 52179407Sobrien (bfd *, asymbol *, arelent *, asection *, bfd_boolean, void *, bfd_vma); 53179407Sobrienstatic bfd_reloc_status_type mips_elf_gprel32_reloc 54179407Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 55179407Sobrienstatic bfd_reloc_status_type mips32_64bit_reloc 56179407Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 57179407Sobrienstatic reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup 58179407Sobrien (bfd *, bfd_reloc_code_real_type); 59179407Sobrienstatic reloc_howto_type *mips_elf32_rtype_to_howto 60179407Sobrien (unsigned int, bfd_boolean); 61179407Sobrienstatic void mips_info_to_howto_rel 62179407Sobrien (bfd *, arelent *, Elf_Internal_Rela *); 63179407Sobrienstatic void mips_info_to_howto_rela 64179407Sobrien (bfd *, arelent *, Elf_Internal_Rela *); 65179407Sobrienstatic bfd_boolean mips_elf_sym_is_global 66179407Sobrien (bfd *, asymbol *); 67179407Sobrienstatic bfd_boolean mips_elf32_object_p 68179407Sobrien (bfd *); 69179407Sobrienstatic bfd_boolean mips_elf_is_local_label_name 70179407Sobrien (bfd *, const char *); 71179407Sobrienstatic bfd_reloc_status_type mips16_gprel_reloc 72179407Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 73179407Sobrienstatic bfd_reloc_status_type mips_elf_final_gp 74179407Sobrien (bfd *, asymbol *, bfd_boolean, char **, bfd_vma *); 75179407Sobrienstatic bfd_boolean mips_elf_assign_gp 76179407Sobrien (bfd *, bfd_vma *); 77179407Sobrienstatic bfd_boolean elf32_mips_grok_prstatus 78179407Sobrien (bfd *, Elf_Internal_Note *); 79179407Sobrienstatic bfd_boolean elf32_mips_grok_psinfo 80179407Sobrien (bfd *, Elf_Internal_Note *); 81179407Sobrienstatic irix_compat_t elf32_mips_irix_compat 82179407Sobrien (bfd *); 83179407Sobrien 84179407Sobrienextern const bfd_target bfd_elf32_bigmips_vec; 85179407Sobrienextern const bfd_target bfd_elf32_littlemips_vec; 86179407Sobrien 87179407Sobrien/* Nonzero if ABFD is using the N32 ABI. */ 88179407Sobrien#define ABI_N32_P(abfd) \ 89179407Sobrien ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0) 90179407Sobrien 91179407Sobrien/* Whether we are trying to be compatible with IRIX at all. */ 92179407Sobrien#define SGI_COMPAT(abfd) \ 93179407Sobrien (elf32_mips_irix_compat (abfd) != ict_none) 94179407Sobrien 95179407Sobrien/* The number of local .got entries we reserve. */ 96179407Sobrien#define MIPS_RESERVED_GOTNO (2) 97179407Sobrien 98179407Sobrien/* In case we're on a 32-bit machine, construct a 64-bit "-1" value 99179407Sobrien from smaller values. Start with zero, widen, *then* decrement. */ 100179407Sobrien#define MINUS_ONE (((bfd_vma)0) - 1) 101179407Sobrien 102179407Sobrien/* The relocation table used for SHT_REL sections. */ 103179407Sobrien 104179407Sobrienstatic reloc_howto_type elf_mips_howto_table_rel[] = 105179407Sobrien{ 106179407Sobrien /* No relocation. */ 107179407Sobrien HOWTO (R_MIPS_NONE, /* type */ 108179407Sobrien 0, /* rightshift */ 109179407Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 110179407Sobrien 0, /* bitsize */ 111179407Sobrien FALSE, /* pc_relative */ 112179407Sobrien 0, /* bitpos */ 113179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 114179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 115179407Sobrien "R_MIPS_NONE", /* name */ 116179407Sobrien FALSE, /* partial_inplace */ 117179407Sobrien 0, /* src_mask */ 118179407Sobrien 0, /* dst_mask */ 119179407Sobrien FALSE), /* pcrel_offset */ 120179407Sobrien 121179407Sobrien /* 16 bit relocation. */ 122179407Sobrien HOWTO (R_MIPS_16, /* type */ 123179407Sobrien 0, /* rightshift */ 124179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 125179407Sobrien 16, /* bitsize */ 126179407Sobrien FALSE, /* pc_relative */ 127179407Sobrien 0, /* bitpos */ 128179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 129179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 130179407Sobrien "R_MIPS_16", /* name */ 131179407Sobrien TRUE, /* partial_inplace */ 132179407Sobrien 0x0000ffff, /* src_mask */ 133179407Sobrien 0x0000ffff, /* dst_mask */ 134179407Sobrien FALSE), /* pcrel_offset */ 135179407Sobrien 136179407Sobrien /* 32 bit relocation. */ 137179407Sobrien HOWTO (R_MIPS_32, /* type */ 138179407Sobrien 0, /* rightshift */ 139179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 140179407Sobrien 32, /* bitsize */ 141179407Sobrien FALSE, /* pc_relative */ 142179407Sobrien 0, /* bitpos */ 143179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 144179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 145179407Sobrien "R_MIPS_32", /* name */ 146179407Sobrien TRUE, /* partial_inplace */ 147179407Sobrien 0xffffffff, /* src_mask */ 148179407Sobrien 0xffffffff, /* dst_mask */ 149179407Sobrien FALSE), /* pcrel_offset */ 150179407Sobrien 151179407Sobrien /* 32 bit symbol relative relocation. */ 152179407Sobrien HOWTO (R_MIPS_REL32, /* type */ 153179407Sobrien 0, /* rightshift */ 154179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 155179407Sobrien 32, /* bitsize */ 156179407Sobrien FALSE, /* pc_relative */ 157179407Sobrien 0, /* bitpos */ 158179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 159179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 160179407Sobrien "R_MIPS_REL32", /* name */ 161179407Sobrien TRUE, /* partial_inplace */ 162179407Sobrien 0xffffffff, /* src_mask */ 163179407Sobrien 0xffffffff, /* dst_mask */ 164179407Sobrien FALSE), /* pcrel_offset */ 165179407Sobrien 166179407Sobrien /* 26 bit jump address. */ 167179407Sobrien HOWTO (R_MIPS_26, /* type */ 168179407Sobrien 2, /* rightshift */ 169179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 170179407Sobrien 26, /* bitsize */ 171179407Sobrien FALSE, /* pc_relative */ 172179407Sobrien 0, /* bitpos */ 173179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 174179407Sobrien /* This needs complex overflow 175179407Sobrien detection, because the upper four 176179407Sobrien bits must match the PC + 4. */ 177179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 178179407Sobrien "R_MIPS_26", /* name */ 179179407Sobrien TRUE, /* partial_inplace */ 180179407Sobrien 0x03ffffff, /* src_mask */ 181179407Sobrien 0x03ffffff, /* dst_mask */ 182179407Sobrien FALSE), /* pcrel_offset */ 183179407Sobrien 184179407Sobrien /* High 16 bits of symbol value. */ 185179407Sobrien HOWTO (R_MIPS_HI16, /* type */ 186179407Sobrien 16, /* rightshift */ 187179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 188179407Sobrien 16, /* bitsize */ 189179407Sobrien FALSE, /* pc_relative */ 190179407Sobrien 0, /* bitpos */ 191179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 192179407Sobrien _bfd_mips_elf_hi16_reloc, /* special_function */ 193179407Sobrien "R_MIPS_HI16", /* name */ 194179407Sobrien TRUE, /* partial_inplace */ 195179407Sobrien 0x0000ffff, /* src_mask */ 196179407Sobrien 0x0000ffff, /* dst_mask */ 197179407Sobrien FALSE), /* pcrel_offset */ 198179407Sobrien 199179407Sobrien /* Low 16 bits of symbol value. */ 200179407Sobrien HOWTO (R_MIPS_LO16, /* type */ 201179407Sobrien 0, /* rightshift */ 202179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 203179407Sobrien 16, /* bitsize */ 204179407Sobrien FALSE, /* pc_relative */ 205179407Sobrien 0, /* bitpos */ 206179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 207179407Sobrien _bfd_mips_elf_lo16_reloc, /* special_function */ 208179407Sobrien "R_MIPS_LO16", /* name */ 209179407Sobrien TRUE, /* partial_inplace */ 210179407Sobrien 0x0000ffff, /* src_mask */ 211179407Sobrien 0x0000ffff, /* dst_mask */ 212179407Sobrien FALSE), /* pcrel_offset */ 213179407Sobrien 214179407Sobrien /* GP relative reference. */ 215179407Sobrien HOWTO (R_MIPS_GPREL16, /* type */ 216179407Sobrien 0, /* rightshift */ 217179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 218179407Sobrien 16, /* bitsize */ 219179407Sobrien FALSE, /* pc_relative */ 220179407Sobrien 0, /* bitpos */ 221179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 222179407Sobrien _bfd_mips_elf32_gprel16_reloc, /* special_function */ 223179407Sobrien "R_MIPS_GPREL16", /* name */ 224179407Sobrien TRUE, /* partial_inplace */ 225179407Sobrien 0x0000ffff, /* src_mask */ 226179407Sobrien 0x0000ffff, /* dst_mask */ 227179407Sobrien FALSE), /* pcrel_offset */ 228179407Sobrien 229179407Sobrien /* Reference to literal section. */ 230179407Sobrien HOWTO (R_MIPS_LITERAL, /* type */ 231179407Sobrien 0, /* rightshift */ 232179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 233179407Sobrien 16, /* bitsize */ 234179407Sobrien FALSE, /* pc_relative */ 235179407Sobrien 0, /* bitpos */ 236179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 237179407Sobrien _bfd_mips_elf32_gprel16_reloc, /* special_function */ 238179407Sobrien "R_MIPS_LITERAL", /* name */ 239179407Sobrien TRUE, /* partial_inplace */ 240179407Sobrien 0x0000ffff, /* src_mask */ 241179407Sobrien 0x0000ffff, /* dst_mask */ 242179407Sobrien FALSE), /* pcrel_offset */ 243179407Sobrien 244179407Sobrien /* Reference to global offset table. */ 245179407Sobrien HOWTO (R_MIPS_GOT16, /* type */ 246179407Sobrien 0, /* rightshift */ 247179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 248179407Sobrien 16, /* bitsize */ 249179407Sobrien FALSE, /* pc_relative */ 250179407Sobrien 0, /* bitpos */ 251179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 252179407Sobrien _bfd_mips_elf_got16_reloc, /* special_function */ 253179407Sobrien "R_MIPS_GOT16", /* name */ 254179407Sobrien TRUE, /* partial_inplace */ 255179407Sobrien 0x0000ffff, /* src_mask */ 256179407Sobrien 0x0000ffff, /* dst_mask */ 257179407Sobrien FALSE), /* pcrel_offset */ 258179407Sobrien 259218822Sdim /* 16 bit PC relative reference. Note that the ABI document has a typo 260218822Sdim and claims R_MIPS_PC16 to be not rightshifted, rendering it useless. 261218822Sdim We do the right thing here. */ 262179407Sobrien HOWTO (R_MIPS_PC16, /* type */ 263218822Sdim 2, /* rightshift */ 264179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 265179407Sobrien 16, /* bitsize */ 266179407Sobrien TRUE, /* pc_relative */ 267179407Sobrien 0, /* bitpos */ 268179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 269179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 270179407Sobrien "R_MIPS_PC16", /* name */ 271179407Sobrien TRUE, /* partial_inplace */ 272179407Sobrien 0x0000ffff, /* src_mask */ 273179407Sobrien 0x0000ffff, /* dst_mask */ 274179407Sobrien TRUE), /* pcrel_offset */ 275179407Sobrien 276179407Sobrien /* 16 bit call through global offset table. */ 277179407Sobrien HOWTO (R_MIPS_CALL16, /* type */ 278179407Sobrien 0, /* rightshift */ 279179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 280179407Sobrien 16, /* bitsize */ 281179407Sobrien FALSE, /* pc_relative */ 282179407Sobrien 0, /* bitpos */ 283179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 284179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 285179407Sobrien "R_MIPS_CALL16", /* name */ 286179407Sobrien TRUE, /* partial_inplace */ 287179407Sobrien 0x0000ffff, /* src_mask */ 288179407Sobrien 0x0000ffff, /* dst_mask */ 289179407Sobrien FALSE), /* pcrel_offset */ 290179407Sobrien 291179407Sobrien /* 32 bit GP relative reference. */ 292179407Sobrien HOWTO (R_MIPS_GPREL32, /* type */ 293179407Sobrien 0, /* rightshift */ 294179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 295179407Sobrien 32, /* bitsize */ 296179407Sobrien FALSE, /* pc_relative */ 297179407Sobrien 0, /* bitpos */ 298179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 299179407Sobrien mips_elf_gprel32_reloc, /* special_function */ 300179407Sobrien "R_MIPS_GPREL32", /* name */ 301179407Sobrien TRUE, /* partial_inplace */ 302179407Sobrien 0xffffffff, /* src_mask */ 303179407Sobrien 0xffffffff, /* dst_mask */ 304179407Sobrien FALSE), /* pcrel_offset */ 305179407Sobrien 306179407Sobrien /* The remaining relocs are defined on Irix 5, although they are 307179407Sobrien not defined by the ABI. */ 308179407Sobrien EMPTY_HOWTO (13), 309179407Sobrien EMPTY_HOWTO (14), 310179407Sobrien EMPTY_HOWTO (15), 311179407Sobrien 312179407Sobrien /* A 5 bit shift field. */ 313179407Sobrien HOWTO (R_MIPS_SHIFT5, /* type */ 314179407Sobrien 0, /* rightshift */ 315179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 316179407Sobrien 5, /* bitsize */ 317179407Sobrien FALSE, /* pc_relative */ 318179407Sobrien 6, /* bitpos */ 319179407Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 320179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 321179407Sobrien "R_MIPS_SHIFT5", /* name */ 322179407Sobrien TRUE, /* partial_inplace */ 323179407Sobrien 0x000007c0, /* src_mask */ 324179407Sobrien 0x000007c0, /* dst_mask */ 325179407Sobrien FALSE), /* pcrel_offset */ 326179407Sobrien 327179407Sobrien /* A 6 bit shift field. */ 328179407Sobrien /* FIXME: This is not handled correctly; a special function is 329179407Sobrien needed to put the most significant bit in the right place. */ 330179407Sobrien HOWTO (R_MIPS_SHIFT6, /* type */ 331179407Sobrien 0, /* rightshift */ 332179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 333179407Sobrien 6, /* bitsize */ 334179407Sobrien FALSE, /* pc_relative */ 335179407Sobrien 6, /* bitpos */ 336179407Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 337179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 338179407Sobrien "R_MIPS_SHIFT6", /* name */ 339179407Sobrien TRUE, /* partial_inplace */ 340179407Sobrien 0x000007c4, /* src_mask */ 341179407Sobrien 0x000007c4, /* dst_mask */ 342179407Sobrien FALSE), /* pcrel_offset */ 343179407Sobrien 344179407Sobrien /* A 64 bit relocation. */ 345179407Sobrien HOWTO (R_MIPS_64, /* type */ 346179407Sobrien 0, /* rightshift */ 347179407Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 348179407Sobrien 64, /* bitsize */ 349179407Sobrien FALSE, /* pc_relative */ 350179407Sobrien 0, /* bitpos */ 351179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 352179407Sobrien mips32_64bit_reloc, /* special_function */ 353179407Sobrien "R_MIPS_64", /* name */ 354179407Sobrien TRUE, /* partial_inplace */ 355179407Sobrien MINUS_ONE, /* src_mask */ 356179407Sobrien MINUS_ONE, /* dst_mask */ 357179407Sobrien FALSE), /* pcrel_offset */ 358179407Sobrien 359179407Sobrien /* Displacement in the global offset table. */ 360179407Sobrien HOWTO (R_MIPS_GOT_DISP, /* type */ 361179407Sobrien 0, /* rightshift */ 362179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 363179407Sobrien 16, /* bitsize */ 364179407Sobrien FALSE, /* pc_relative */ 365179407Sobrien 0, /* bitpos */ 366179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 367179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 368179407Sobrien "R_MIPS_GOT_DISP", /* name */ 369179407Sobrien TRUE, /* partial_inplace */ 370179407Sobrien 0x0000ffff, /* src_mask */ 371179407Sobrien 0x0000ffff, /* dst_mask */ 372179407Sobrien FALSE), /* pcrel_offset */ 373179407Sobrien 374179407Sobrien /* Displacement to page pointer in the global offset table. */ 375179407Sobrien HOWTO (R_MIPS_GOT_PAGE, /* type */ 376179407Sobrien 0, /* rightshift */ 377179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 378179407Sobrien 16, /* bitsize */ 379179407Sobrien FALSE, /* pc_relative */ 380179407Sobrien 0, /* bitpos */ 381179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 382179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 383179407Sobrien "R_MIPS_GOT_PAGE", /* name */ 384179407Sobrien TRUE, /* partial_inplace */ 385179407Sobrien 0x0000ffff, /* src_mask */ 386179407Sobrien 0x0000ffff, /* dst_mask */ 387179407Sobrien FALSE), /* pcrel_offset */ 388179407Sobrien 389179407Sobrien /* Offset from page pointer in the global offset table. */ 390179407Sobrien HOWTO (R_MIPS_GOT_OFST, /* type */ 391179407Sobrien 0, /* rightshift */ 392179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 393179407Sobrien 16, /* bitsize */ 394179407Sobrien FALSE, /* pc_relative */ 395179407Sobrien 0, /* bitpos */ 396179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 397179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 398179407Sobrien "R_MIPS_GOT_OFST", /* name */ 399179407Sobrien TRUE, /* partial_inplace */ 400179407Sobrien 0x0000ffff, /* src_mask */ 401179407Sobrien 0x0000ffff, /* dst_mask */ 402179407Sobrien FALSE), /* pcrel_offset */ 403179407Sobrien 404179407Sobrien /* High 16 bits of displacement in global offset table. */ 405179407Sobrien HOWTO (R_MIPS_GOT_HI16, /* type */ 406179407Sobrien 0, /* rightshift */ 407179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 408179407Sobrien 16, /* bitsize */ 409179407Sobrien FALSE, /* pc_relative */ 410179407Sobrien 0, /* bitpos */ 411179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 412179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 413179407Sobrien "R_MIPS_GOT_HI16", /* name */ 414179407Sobrien TRUE, /* partial_inplace */ 415179407Sobrien 0x0000ffff, /* src_mask */ 416179407Sobrien 0x0000ffff, /* dst_mask */ 417179407Sobrien FALSE), /* pcrel_offset */ 418179407Sobrien 419179407Sobrien /* Low 16 bits of displacement in global offset table. */ 420179407Sobrien HOWTO (R_MIPS_GOT_LO16, /* type */ 421179407Sobrien 0, /* rightshift */ 422179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 423179407Sobrien 16, /* bitsize */ 424179407Sobrien FALSE, /* pc_relative */ 425179407Sobrien 0, /* bitpos */ 426179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 427179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 428179407Sobrien "R_MIPS_GOT_LO16", /* name */ 429179407Sobrien TRUE, /* partial_inplace */ 430179407Sobrien 0x0000ffff, /* src_mask */ 431179407Sobrien 0x0000ffff, /* dst_mask */ 432179407Sobrien FALSE), /* pcrel_offset */ 433179407Sobrien 434179407Sobrien /* 64 bit subtraction. Used in the N32 ABI. */ 435179407Sobrien HOWTO (R_MIPS_SUB, /* type */ 436179407Sobrien 0, /* rightshift */ 437179407Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 438179407Sobrien 64, /* bitsize */ 439179407Sobrien FALSE, /* pc_relative */ 440179407Sobrien 0, /* bitpos */ 441179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 442179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 443179407Sobrien "R_MIPS_SUB", /* name */ 444179407Sobrien TRUE, /* partial_inplace */ 445179407Sobrien MINUS_ONE, /* src_mask */ 446179407Sobrien MINUS_ONE, /* dst_mask */ 447179407Sobrien FALSE), /* pcrel_offset */ 448179407Sobrien 449179407Sobrien /* Used to cause the linker to insert and delete instructions? */ 450179407Sobrien EMPTY_HOWTO (R_MIPS_INSERT_A), 451179407Sobrien EMPTY_HOWTO (R_MIPS_INSERT_B), 452179407Sobrien EMPTY_HOWTO (R_MIPS_DELETE), 453179407Sobrien 454179407Sobrien /* Get the higher value of a 64 bit addend. */ 455179407Sobrien HOWTO (R_MIPS_HIGHER, /* type */ 456179407Sobrien 0, /* rightshift */ 457179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 458179407Sobrien 16, /* bitsize */ 459179407Sobrien FALSE, /* pc_relative */ 460179407Sobrien 0, /* bitpos */ 461179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 462179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 463179407Sobrien "R_MIPS_HIGHER", /* name */ 464179407Sobrien TRUE, /* partial_inplace */ 465179407Sobrien 0x0000ffff, /* src_mask */ 466179407Sobrien 0x0000ffff, /* dst_mask */ 467179407Sobrien FALSE), /* pcrel_offset */ 468179407Sobrien 469179407Sobrien /* Get the highest value of a 64 bit addend. */ 470179407Sobrien HOWTO (R_MIPS_HIGHEST, /* type */ 471179407Sobrien 0, /* rightshift */ 472179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 473179407Sobrien 16, /* bitsize */ 474179407Sobrien FALSE, /* pc_relative */ 475179407Sobrien 0, /* bitpos */ 476179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 477179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 478179407Sobrien "R_MIPS_HIGHEST", /* name */ 479179407Sobrien TRUE, /* partial_inplace */ 480179407Sobrien 0x0000ffff, /* src_mask */ 481179407Sobrien 0x0000ffff, /* dst_mask */ 482179407Sobrien FALSE), /* pcrel_offset */ 483179407Sobrien 484179407Sobrien /* High 16 bits of displacement in global offset table. */ 485179407Sobrien HOWTO (R_MIPS_CALL_HI16, /* type */ 486179407Sobrien 0, /* rightshift */ 487179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 488179407Sobrien 16, /* bitsize */ 489179407Sobrien FALSE, /* pc_relative */ 490179407Sobrien 0, /* bitpos */ 491179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 492179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 493179407Sobrien "R_MIPS_CALL_HI16", /* name */ 494179407Sobrien TRUE, /* partial_inplace */ 495179407Sobrien 0x0000ffff, /* src_mask */ 496179407Sobrien 0x0000ffff, /* dst_mask */ 497179407Sobrien FALSE), /* pcrel_offset */ 498179407Sobrien 499179407Sobrien /* Low 16 bits of displacement in global offset table. */ 500179407Sobrien HOWTO (R_MIPS_CALL_LO16, /* type */ 501179407Sobrien 0, /* rightshift */ 502179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 503179407Sobrien 16, /* bitsize */ 504179407Sobrien FALSE, /* pc_relative */ 505179407Sobrien 0, /* bitpos */ 506179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 507179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 508179407Sobrien "R_MIPS_CALL_LO16", /* name */ 509179407Sobrien TRUE, /* partial_inplace */ 510179407Sobrien 0x0000ffff, /* src_mask */ 511179407Sobrien 0x0000ffff, /* dst_mask */ 512179407Sobrien FALSE), /* pcrel_offset */ 513179407Sobrien 514179407Sobrien /* Section displacement. */ 515179407Sobrien HOWTO (R_MIPS_SCN_DISP, /* type */ 516179407Sobrien 0, /* rightshift */ 517179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 518179407Sobrien 32, /* bitsize */ 519179407Sobrien FALSE, /* pc_relative */ 520179407Sobrien 0, /* bitpos */ 521179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 522179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 523179407Sobrien "R_MIPS_SCN_DISP", /* name */ 524179407Sobrien TRUE, /* partial_inplace */ 525179407Sobrien 0xffffffff, /* src_mask */ 526179407Sobrien 0xffffffff, /* dst_mask */ 527179407Sobrien FALSE), /* pcrel_offset */ 528179407Sobrien 529179407Sobrien EMPTY_HOWTO (R_MIPS_REL16), 530179407Sobrien EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE), 531179407Sobrien EMPTY_HOWTO (R_MIPS_PJUMP), 532179407Sobrien EMPTY_HOWTO (R_MIPS_RELGOT), 533179407Sobrien 534179407Sobrien /* Protected jump conversion. This is an optimization hint. No 535179407Sobrien relocation is required for correctness. */ 536179407Sobrien HOWTO (R_MIPS_JALR, /* type */ 537179407Sobrien 0, /* rightshift */ 538179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 539179407Sobrien 32, /* bitsize */ 540179407Sobrien FALSE, /* pc_relative */ 541179407Sobrien 0, /* bitpos */ 542179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 543179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 544179407Sobrien "R_MIPS_JALR", /* name */ 545179407Sobrien FALSE, /* partial_inplace */ 546179407Sobrien 0x00000000, /* src_mask */ 547179407Sobrien 0x00000000, /* dst_mask */ 548179407Sobrien FALSE), /* pcrel_offset */ 549218822Sdim 550218822Sdim /* TLS GD/LD dynamic relocations. */ 551218822Sdim HOWTO (R_MIPS_TLS_DTPMOD32, /* type */ 552218822Sdim 0, /* rightshift */ 553218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 554218822Sdim 32, /* bitsize */ 555218822Sdim FALSE, /* pc_relative */ 556218822Sdim 0, /* bitpos */ 557218822Sdim complain_overflow_dont, /* complain_on_overflow */ 558218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 559218822Sdim "R_MIPS_TLS_DTPMOD32", /* name */ 560218822Sdim TRUE, /* partial_inplace */ 561218822Sdim 0xffffffff, /* src_mask */ 562218822Sdim 0xffffffff, /* dst_mask */ 563218822Sdim FALSE), /* pcrel_offset */ 564218822Sdim 565218822Sdim HOWTO (R_MIPS_TLS_DTPREL32, /* type */ 566218822Sdim 0, /* rightshift */ 567218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 568218822Sdim 32, /* bitsize */ 569218822Sdim FALSE, /* pc_relative */ 570218822Sdim 0, /* bitpos */ 571218822Sdim complain_overflow_dont, /* complain_on_overflow */ 572218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 573218822Sdim "R_MIPS_TLS_DTPREL32", /* name */ 574218822Sdim TRUE, /* partial_inplace */ 575218822Sdim 0xffffffff, /* src_mask */ 576218822Sdim 0xffffffff, /* dst_mask */ 577218822Sdim FALSE), /* pcrel_offset */ 578218822Sdim 579218822Sdim EMPTY_HOWTO (R_MIPS_TLS_DTPMOD64), 580218822Sdim EMPTY_HOWTO (R_MIPS_TLS_DTPREL64), 581218822Sdim 582218822Sdim /* TLS general dynamic variable reference. */ 583218822Sdim HOWTO (R_MIPS_TLS_GD, /* type */ 584218822Sdim 0, /* rightshift */ 585218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 586218822Sdim 16, /* bitsize */ 587218822Sdim FALSE, /* pc_relative */ 588218822Sdim 0, /* bitpos */ 589218822Sdim complain_overflow_signed, /* complain_on_overflow */ 590218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 591218822Sdim "R_MIPS_TLS_GD", /* name */ 592218822Sdim TRUE, /* partial_inplace */ 593218822Sdim 0x0000ffff, /* src_mask */ 594218822Sdim 0x0000ffff, /* dst_mask */ 595218822Sdim FALSE), /* pcrel_offset */ 596218822Sdim 597218822Sdim /* TLS local dynamic variable reference. */ 598218822Sdim HOWTO (R_MIPS_TLS_LDM, /* type */ 599218822Sdim 0, /* rightshift */ 600218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 601218822Sdim 16, /* bitsize */ 602218822Sdim FALSE, /* pc_relative */ 603218822Sdim 0, /* bitpos */ 604218822Sdim complain_overflow_signed, /* complain_on_overflow */ 605218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 606218822Sdim "R_MIPS_TLS_LDM", /* name */ 607218822Sdim TRUE, /* partial_inplace */ 608218822Sdim 0x0000ffff, /* src_mask */ 609218822Sdim 0x0000ffff, /* dst_mask */ 610218822Sdim FALSE), /* pcrel_offset */ 611218822Sdim 612218822Sdim /* TLS local dynamic offset. */ 613218822Sdim HOWTO (R_MIPS_TLS_DTPREL_HI16, /* type */ 614218822Sdim 0, /* rightshift */ 615218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 616218822Sdim 16, /* bitsize */ 617218822Sdim FALSE, /* pc_relative */ 618218822Sdim 0, /* bitpos */ 619218822Sdim complain_overflow_signed, /* complain_on_overflow */ 620218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 621218822Sdim "R_MIPS_TLS_DTPREL_HI16", /* name */ 622218822Sdim TRUE, /* partial_inplace */ 623218822Sdim 0x0000ffff, /* src_mask */ 624218822Sdim 0x0000ffff, /* dst_mask */ 625218822Sdim FALSE), /* pcrel_offset */ 626218822Sdim 627218822Sdim /* TLS local dynamic offset. */ 628218822Sdim HOWTO (R_MIPS_TLS_DTPREL_LO16, /* type */ 629218822Sdim 0, /* rightshift */ 630218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 631218822Sdim 16, /* bitsize */ 632218822Sdim FALSE, /* pc_relative */ 633218822Sdim 0, /* bitpos */ 634218822Sdim complain_overflow_signed, /* complain_on_overflow */ 635218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 636218822Sdim "R_MIPS_TLS_DTPREL_LO16", /* name */ 637218822Sdim TRUE, /* partial_inplace */ 638218822Sdim 0x0000ffff, /* src_mask */ 639218822Sdim 0x0000ffff, /* dst_mask */ 640218822Sdim FALSE), /* pcrel_offset */ 641218822Sdim 642218822Sdim /* TLS thread pointer offset. */ 643218822Sdim HOWTO (R_MIPS_TLS_GOTTPREL, /* type */ 644218822Sdim 0, /* rightshift */ 645218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 646218822Sdim 16, /* bitsize */ 647218822Sdim FALSE, /* pc_relative */ 648218822Sdim 0, /* bitpos */ 649218822Sdim complain_overflow_signed, /* complain_on_overflow */ 650218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 651218822Sdim "R_MIPS_TLS_GOTTPREL", /* name */ 652218822Sdim TRUE, /* partial_inplace */ 653218822Sdim 0x0000ffff, /* src_mask */ 654218822Sdim 0x0000ffff, /* dst_mask */ 655218822Sdim FALSE), /* pcrel_offset */ 656218822Sdim 657218822Sdim /* TLS IE dynamic relocations. */ 658218822Sdim HOWTO (R_MIPS_TLS_TPREL32, /* type */ 659218822Sdim 0, /* rightshift */ 660218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 661218822Sdim 32, /* bitsize */ 662218822Sdim FALSE, /* pc_relative */ 663218822Sdim 0, /* bitpos */ 664218822Sdim complain_overflow_dont, /* complain_on_overflow */ 665218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 666218822Sdim "R_MIPS_TLS_TPREL32", /* name */ 667218822Sdim TRUE, /* partial_inplace */ 668218822Sdim 0xffffffff, /* src_mask */ 669218822Sdim 0xffffffff, /* dst_mask */ 670218822Sdim FALSE), /* pcrel_offset */ 671218822Sdim 672218822Sdim EMPTY_HOWTO (R_MIPS_TLS_TPREL64), 673218822Sdim 674218822Sdim /* TLS thread pointer offset. */ 675218822Sdim HOWTO (R_MIPS_TLS_TPREL_HI16, /* type */ 676218822Sdim 0, /* rightshift */ 677218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 678218822Sdim 16, /* bitsize */ 679218822Sdim FALSE, /* pc_relative */ 680218822Sdim 0, /* bitpos */ 681218822Sdim complain_overflow_signed, /* complain_on_overflow */ 682218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 683218822Sdim "R_MIPS_TLS_TPREL_HI16", /* name */ 684218822Sdim TRUE, /* partial_inplace */ 685218822Sdim 0x0000ffff, /* src_mask */ 686218822Sdim 0x0000ffff, /* dst_mask */ 687218822Sdim FALSE), /* pcrel_offset */ 688218822Sdim 689218822Sdim /* TLS thread pointer offset. */ 690218822Sdim HOWTO (R_MIPS_TLS_TPREL_LO16, /* type */ 691218822Sdim 0, /* rightshift */ 692218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 693218822Sdim 16, /* bitsize */ 694218822Sdim FALSE, /* pc_relative */ 695218822Sdim 0, /* bitpos */ 696218822Sdim complain_overflow_signed, /* complain_on_overflow */ 697218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 698218822Sdim "R_MIPS_TLS_TPREL_LO16", /* name */ 699218822Sdim TRUE, /* partial_inplace */ 700218822Sdim 0x0000ffff, /* src_mask */ 701218822Sdim 0x0000ffff, /* dst_mask */ 702218822Sdim FALSE), /* pcrel_offset */ 703218822Sdim 704218822Sdim /* 32 bit relocation with no addend. */ 705218822Sdim HOWTO (R_MIPS_GLOB_DAT, /* type */ 706218822Sdim 0, /* rightshift */ 707218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 708218822Sdim 32, /* bitsize */ 709218822Sdim FALSE, /* pc_relative */ 710218822Sdim 0, /* bitpos */ 711218822Sdim complain_overflow_dont, /* complain_on_overflow */ 712218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 713218822Sdim "R_MIPS_GLOB_DAT", /* name */ 714218822Sdim FALSE, /* partial_inplace */ 715218822Sdim 0x0, /* src_mask */ 716218822Sdim 0xffffffff, /* dst_mask */ 717218822Sdim FALSE), /* pcrel_offset */ 718179407Sobrien}; 719179407Sobrien 720179407Sobrien/* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This 721179407Sobrien is a hack to make the linker think that we need 64 bit values. */ 722179407Sobrienstatic reloc_howto_type elf_mips_ctor64_howto = 723179407Sobrien HOWTO (R_MIPS_64, /* type */ 724179407Sobrien 0, /* rightshift */ 725179407Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 726179407Sobrien 32, /* bitsize */ 727179407Sobrien FALSE, /* pc_relative */ 728179407Sobrien 0, /* bitpos */ 729179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 730179407Sobrien mips32_64bit_reloc, /* special_function */ 731179407Sobrien "R_MIPS_64", /* name */ 732179407Sobrien TRUE, /* partial_inplace */ 733179407Sobrien 0xffffffff, /* src_mask */ 734179407Sobrien 0xffffffff, /* dst_mask */ 735179407Sobrien FALSE); /* pcrel_offset */ 736179407Sobrien 737218822Sdimstatic reloc_howto_type elf_mips16_howto_table_rel[] = 738218822Sdim{ 739218822Sdim /* The reloc used for the mips16 jump instruction. */ 740179407Sobrien HOWTO (R_MIPS16_26, /* type */ 741179407Sobrien 2, /* rightshift */ 742179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 743179407Sobrien 26, /* bitsize */ 744179407Sobrien FALSE, /* pc_relative */ 745179407Sobrien 0, /* bitpos */ 746179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 747179407Sobrien /* This needs complex overflow 748179407Sobrien detection, because the upper four 749179407Sobrien bits must match the PC. */ 750218822Sdim _bfd_mips_elf_generic_reloc, /* special_function */ 751179407Sobrien "R_MIPS16_26", /* name */ 752179407Sobrien TRUE, /* partial_inplace */ 753179407Sobrien 0x3ffffff, /* src_mask */ 754179407Sobrien 0x3ffffff, /* dst_mask */ 755218822Sdim FALSE), /* pcrel_offset */ 756179407Sobrien 757218822Sdim /* The reloc used for the mips16 gprel instruction. */ 758179407Sobrien HOWTO (R_MIPS16_GPREL, /* type */ 759179407Sobrien 0, /* rightshift */ 760179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 761179407Sobrien 16, /* bitsize */ 762179407Sobrien FALSE, /* pc_relative */ 763179407Sobrien 0, /* bitpos */ 764179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 765179407Sobrien mips16_gprel_reloc, /* special_function */ 766179407Sobrien "R_MIPS16_GPREL", /* name */ 767179407Sobrien TRUE, /* partial_inplace */ 768218822Sdim 0x0000ffff, /* src_mask */ 769218822Sdim 0x0000ffff, /* dst_mask */ 770218822Sdim FALSE), /* pcrel_offset */ 771179407Sobrien 772218822Sdim /* A placeholder for MIPS16 reference to global offset table. */ 773218822Sdim EMPTY_HOWTO (R_MIPS16_GOT16), 774218822Sdim 775218822Sdim /* A placeholder for MIPS16 16 bit call through global offset table. */ 776218822Sdim EMPTY_HOWTO (R_MIPS16_CALL16), 777218822Sdim 778218822Sdim /* MIPS16 high 16 bits of symbol value. */ 779218822Sdim HOWTO (R_MIPS16_HI16, /* type */ 780179407Sobrien 16, /* rightshift */ 781179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 782179407Sobrien 16, /* bitsize */ 783218822Sdim FALSE, /* pc_relative */ 784179407Sobrien 0, /* bitpos */ 785179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 786179407Sobrien _bfd_mips_elf_hi16_reloc, /* special_function */ 787218822Sdim "R_MIPS16_HI16", /* name */ 788179407Sobrien TRUE, /* partial_inplace */ 789218822Sdim 0x0000ffff, /* src_mask */ 790218822Sdim 0x0000ffff, /* dst_mask */ 791218822Sdim FALSE), /* pcrel_offset */ 792179407Sobrien 793218822Sdim /* MIPS16 low 16 bits of symbol value. */ 794218822Sdim HOWTO (R_MIPS16_LO16, /* type */ 795179407Sobrien 0, /* rightshift */ 796179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 797179407Sobrien 16, /* bitsize */ 798218822Sdim FALSE, /* pc_relative */ 799179407Sobrien 0, /* bitpos */ 800179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 801179407Sobrien _bfd_mips_elf_lo16_reloc, /* special_function */ 802218822Sdim "R_MIPS16_LO16", /* name */ 803179407Sobrien TRUE, /* partial_inplace */ 804218822Sdim 0x0000ffff, /* src_mask */ 805218822Sdim 0x0000ffff, /* dst_mask */ 806218822Sdim FALSE), /* pcrel_offset */ 807218822Sdim}; 808179407Sobrien 809179407Sobrien/* 16 bit offset for pc-relative branches. */ 810179407Sobrienstatic reloc_howto_type elf_mips_gnu_rel16_s2 = 811179407Sobrien HOWTO (R_MIPS_GNU_REL16_S2, /* type */ 812179407Sobrien 2, /* rightshift */ 813179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 814179407Sobrien 16, /* bitsize */ 815179407Sobrien TRUE, /* pc_relative */ 816179407Sobrien 0, /* bitpos */ 817179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 818179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 819179407Sobrien "R_MIPS_GNU_REL16_S2", /* name */ 820179407Sobrien TRUE, /* partial_inplace */ 821179407Sobrien 0xffff, /* src_mask */ 822179407Sobrien 0xffff, /* dst_mask */ 823179407Sobrien TRUE); /* pcrel_offset */ 824179407Sobrien 825218822Sdim/* 32 bit pc-relative. This was a GNU extension used by embedded-PIC. 826218822Sdim It was co-opted by mips-linux for exception-handling data. It is no 827218822Sdim longer used, but should continue to be supported by the linker for 828218822Sdim backward compatibility. (GCC stopped using it in May, 2004.) */ 829179407Sobrienstatic reloc_howto_type elf_mips_gnu_pcrel32 = 830179407Sobrien HOWTO (R_MIPS_PC32, /* type */ 831179407Sobrien 0, /* rightshift */ 832179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 833179407Sobrien 32, /* bitsize */ 834179407Sobrien TRUE, /* pc_relative */ 835179407Sobrien 0, /* bitpos */ 836179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 837179407Sobrien _bfd_mips_elf_generic_reloc, /* special_function */ 838179407Sobrien "R_MIPS_PC32", /* name */ 839179407Sobrien TRUE, /* partial_inplace */ 840179407Sobrien 0xffffffff, /* src_mask */ 841179407Sobrien 0xffffffff, /* dst_mask */ 842179407Sobrien TRUE); /* pcrel_offset */ 843179407Sobrien 844179407Sobrien/* GNU extension to record C++ vtable hierarchy */ 845179407Sobrienstatic reloc_howto_type elf_mips_gnu_vtinherit_howto = 846179407Sobrien HOWTO (R_MIPS_GNU_VTINHERIT, /* type */ 847179407Sobrien 0, /* rightshift */ 848179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 849179407Sobrien 0, /* bitsize */ 850179407Sobrien FALSE, /* pc_relative */ 851179407Sobrien 0, /* bitpos */ 852179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 853179407Sobrien NULL, /* special_function */ 854179407Sobrien "R_MIPS_GNU_VTINHERIT", /* name */ 855179407Sobrien FALSE, /* partial_inplace */ 856179407Sobrien 0, /* src_mask */ 857179407Sobrien 0, /* dst_mask */ 858179407Sobrien FALSE); /* pcrel_offset */ 859179407Sobrien 860179407Sobrien/* GNU extension to record C++ vtable member usage */ 861179407Sobrienstatic reloc_howto_type elf_mips_gnu_vtentry_howto = 862179407Sobrien HOWTO (R_MIPS_GNU_VTENTRY, /* type */ 863179407Sobrien 0, /* rightshift */ 864179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 865179407Sobrien 0, /* bitsize */ 866179407Sobrien FALSE, /* pc_relative */ 867179407Sobrien 0, /* bitpos */ 868179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 869179407Sobrien _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 870179407Sobrien "R_MIPS_GNU_VTENTRY", /* name */ 871179407Sobrien FALSE, /* partial_inplace */ 872179407Sobrien 0, /* src_mask */ 873179407Sobrien 0, /* dst_mask */ 874179407Sobrien FALSE); /* pcrel_offset */ 875179407Sobrien 876179407Sobrien/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a 877179407Sobrien dangerous relocation. */ 878179407Sobrien 879179407Sobrienstatic bfd_boolean 880179407Sobrienmips_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp) 881179407Sobrien{ 882179407Sobrien unsigned int count; 883179407Sobrien asymbol **sym; 884179407Sobrien unsigned int i; 885179407Sobrien 886179407Sobrien /* If we've already figured out what GP will be, just return it. */ 887179407Sobrien *pgp = _bfd_get_gp_value (output_bfd); 888179407Sobrien if (*pgp) 889179407Sobrien return TRUE; 890179407Sobrien 891179407Sobrien count = bfd_get_symcount (output_bfd); 892179407Sobrien sym = bfd_get_outsymbols (output_bfd); 893179407Sobrien 894179407Sobrien /* The linker script will have created a symbol named `_gp' with the 895179407Sobrien appropriate value. */ 896179407Sobrien if (sym == NULL) 897179407Sobrien i = count; 898179407Sobrien else 899179407Sobrien { 900179407Sobrien for (i = 0; i < count; i++, sym++) 901179407Sobrien { 902179407Sobrien register const char *name; 903179407Sobrien 904179407Sobrien name = bfd_asymbol_name (*sym); 905179407Sobrien if (*name == '_' && strcmp (name, "_gp") == 0) 906179407Sobrien { 907179407Sobrien *pgp = bfd_asymbol_value (*sym); 908179407Sobrien _bfd_set_gp_value (output_bfd, *pgp); 909179407Sobrien break; 910179407Sobrien } 911179407Sobrien } 912179407Sobrien } 913179407Sobrien 914179407Sobrien if (i >= count) 915179407Sobrien { 916179407Sobrien /* Only get the error once. */ 917179407Sobrien *pgp = 4; 918179407Sobrien _bfd_set_gp_value (output_bfd, *pgp); 919179407Sobrien return FALSE; 920179407Sobrien } 921179407Sobrien 922179407Sobrien return TRUE; 923179407Sobrien} 924179407Sobrien 925179407Sobrien/* We have to figure out the gp value, so that we can adjust the 926179407Sobrien symbol value correctly. We look up the symbol _gp in the output 927179407Sobrien BFD. If we can't find it, we're stuck. We cache it in the ELF 928179407Sobrien target data. We don't need to adjust the symbol value for an 929179407Sobrien external symbol if we are producing relocatable output. */ 930179407Sobrien 931179407Sobrienstatic bfd_reloc_status_type 932179407Sobrienmips_elf_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable, 933179407Sobrien char **error_message, bfd_vma *pgp) 934179407Sobrien{ 935179407Sobrien if (bfd_is_und_section (symbol->section) 936179407Sobrien && ! relocatable) 937179407Sobrien { 938179407Sobrien *pgp = 0; 939179407Sobrien return bfd_reloc_undefined; 940179407Sobrien } 941179407Sobrien 942179407Sobrien *pgp = _bfd_get_gp_value (output_bfd); 943179407Sobrien if (*pgp == 0 944179407Sobrien && (! relocatable 945179407Sobrien || (symbol->flags & BSF_SECTION_SYM) != 0)) 946179407Sobrien { 947179407Sobrien if (relocatable) 948179407Sobrien { 949179407Sobrien /* Make up a value. */ 950179407Sobrien *pgp = symbol->section->output_section->vma + 0x4000; 951179407Sobrien _bfd_set_gp_value (output_bfd, *pgp); 952179407Sobrien } 953179407Sobrien else if (!mips_elf_assign_gp (output_bfd, pgp)) 954179407Sobrien { 955179407Sobrien *error_message = 956179407Sobrien (char *) _("GP relative relocation when _gp not defined"); 957179407Sobrien return bfd_reloc_dangerous; 958179407Sobrien } 959179407Sobrien } 960179407Sobrien 961179407Sobrien return bfd_reloc_ok; 962179407Sobrien} 963179407Sobrien 964179407Sobrien/* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must 965179407Sobrien become the offset from the gp register. This function also handles 966179407Sobrien R_MIPS_LITERAL relocations, although those can be handled more 967179407Sobrien cleverly because the entries in the .lit8 and .lit4 sections can be 968179407Sobrien merged. */ 969179407Sobrien 970179407Sobrienbfd_reloc_status_type 971179407Sobrien_bfd_mips_elf32_gprel16_reloc (bfd *abfd, arelent *reloc_entry, 972179407Sobrien asymbol *symbol, void *data, 973179407Sobrien asection *input_section, bfd *output_bfd, 974179407Sobrien char **error_message) 975179407Sobrien{ 976179407Sobrien bfd_boolean relocatable; 977179407Sobrien bfd_reloc_status_type ret; 978179407Sobrien bfd_vma gp; 979179407Sobrien 980218822Sdim /* R_MIPS_LITERAL relocations are defined for local symbols only. */ 981218822Sdim if (reloc_entry->howto->type == R_MIPS_LITERAL 982218822Sdim && output_bfd != NULL 983218822Sdim && (symbol->flags & BSF_SECTION_SYM) == 0 984218822Sdim && (symbol->flags & BSF_LOCAL) != 0) 985218822Sdim { 986218822Sdim *error_message = (char *) 987218822Sdim _("literal relocation occurs for an external symbol"); 988218822Sdim return bfd_reloc_outofrange; 989218822Sdim } 990218822Sdim 991179407Sobrien if (output_bfd != NULL) 992179407Sobrien relocatable = TRUE; 993179407Sobrien else 994179407Sobrien { 995179407Sobrien relocatable = FALSE; 996179407Sobrien output_bfd = symbol->section->output_section->owner; 997179407Sobrien } 998179407Sobrien 999179407Sobrien ret = mips_elf_final_gp (output_bfd, symbol, relocatable, error_message, 1000179407Sobrien &gp); 1001179407Sobrien if (ret != bfd_reloc_ok) 1002179407Sobrien return ret; 1003179407Sobrien 1004179407Sobrien return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, 1005179407Sobrien input_section, relocatable, 1006179407Sobrien data, gp); 1007179407Sobrien} 1008179407Sobrien 1009179407Sobrien/* Do a R_MIPS_GPREL32 relocation. This is a 32 bit value which must 1010179407Sobrien become the offset from the gp register. */ 1011179407Sobrien 1012179407Sobrienstatic bfd_reloc_status_type 1013179407Sobrienmips_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 1014179407Sobrien void *data, asection *input_section, bfd *output_bfd, 1015179407Sobrien char **error_message) 1016179407Sobrien{ 1017179407Sobrien bfd_boolean relocatable; 1018179407Sobrien bfd_reloc_status_type ret; 1019179407Sobrien bfd_vma gp; 1020179407Sobrien 1021218822Sdim /* R_MIPS_GPREL32 relocations are defined for local symbols only. */ 1022218822Sdim if (output_bfd != NULL 1023218822Sdim && (symbol->flags & BSF_SECTION_SYM) == 0 1024218822Sdim && (symbol->flags & BSF_LOCAL) != 0) 1025218822Sdim { 1026218822Sdim *error_message = (char *) 1027218822Sdim _("32bits gp relative relocation occurs for an external symbol"); 1028218822Sdim return bfd_reloc_outofrange; 1029218822Sdim } 1030218822Sdim 1031179407Sobrien if (output_bfd != NULL) 1032179407Sobrien relocatable = TRUE; 1033179407Sobrien else 1034179407Sobrien { 1035179407Sobrien relocatable = FALSE; 1036179407Sobrien output_bfd = symbol->section->output_section->owner; 1037179407Sobrien } 1038179407Sobrien 1039179407Sobrien ret = mips_elf_final_gp (output_bfd, symbol, relocatable, 1040179407Sobrien error_message, &gp); 1041179407Sobrien if (ret != bfd_reloc_ok) 1042179407Sobrien return ret; 1043179407Sobrien 1044179407Sobrien return gprel32_with_gp (abfd, symbol, reloc_entry, input_section, 1045179407Sobrien relocatable, data, gp); 1046179407Sobrien} 1047179407Sobrien 1048179407Sobrienstatic bfd_reloc_status_type 1049179407Sobriengprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, 1050179407Sobrien asection *input_section, bfd_boolean relocatable, 1051179407Sobrien void *data, bfd_vma gp) 1052179407Sobrien{ 1053179407Sobrien bfd_vma relocation; 1054179407Sobrien bfd_vma val; 1055179407Sobrien 1056179407Sobrien if (bfd_is_com_section (symbol->section)) 1057179407Sobrien relocation = 0; 1058179407Sobrien else 1059179407Sobrien relocation = symbol->value; 1060179407Sobrien 1061179407Sobrien relocation += symbol->section->output_section->vma; 1062179407Sobrien relocation += symbol->section->output_offset; 1063179407Sobrien 1064218822Sdim if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 1065179407Sobrien return bfd_reloc_outofrange; 1066179407Sobrien 1067179407Sobrien /* Set val to the offset into the section or symbol. */ 1068179407Sobrien val = reloc_entry->addend; 1069179407Sobrien 1070179407Sobrien if (reloc_entry->howto->partial_inplace) 1071179407Sobrien val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 1072179407Sobrien 1073179407Sobrien /* Adjust val for the final section location and GP value. If we 1074179407Sobrien are producing relocatable output, we don't want to do this for 1075179407Sobrien an external symbol. */ 1076179407Sobrien if (! relocatable 1077179407Sobrien || (symbol->flags & BSF_SECTION_SYM) != 0) 1078179407Sobrien val += relocation - gp; 1079179407Sobrien 1080179407Sobrien if (reloc_entry->howto->partial_inplace) 1081179407Sobrien bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address); 1082179407Sobrien else 1083179407Sobrien reloc_entry->addend = val; 1084179407Sobrien 1085179407Sobrien if (relocatable) 1086179407Sobrien reloc_entry->address += input_section->output_offset; 1087179407Sobrien 1088179407Sobrien return bfd_reloc_ok; 1089179407Sobrien} 1090179407Sobrien 1091179407Sobrien/* Handle a 64 bit reloc in a 32 bit MIPS ELF file. These are 1092179407Sobrien generated when addresses are 64 bits. The upper 32 bits are a simple 1093179407Sobrien sign extension. */ 1094179407Sobrien 1095179407Sobrienstatic bfd_reloc_status_type 1096179407Sobrienmips32_64bit_reloc (bfd *abfd, arelent *reloc_entry, 1097179407Sobrien asymbol *symbol ATTRIBUTE_UNUSED, 1098179407Sobrien void *data, asection *input_section, 1099179407Sobrien bfd *output_bfd, char **error_message) 1100179407Sobrien{ 1101179407Sobrien bfd_reloc_status_type r; 1102179407Sobrien arelent reloc32; 1103179407Sobrien unsigned long val; 1104179407Sobrien bfd_size_type addr; 1105179407Sobrien 1106179407Sobrien /* Do a normal 32 bit relocation on the lower 32 bits. */ 1107179407Sobrien reloc32 = *reloc_entry; 1108179407Sobrien if (bfd_big_endian (abfd)) 1109179407Sobrien reloc32.address += 4; 1110179407Sobrien reloc32.howto = &elf_mips_howto_table_rel[R_MIPS_32]; 1111179407Sobrien r = bfd_perform_relocation (abfd, &reloc32, data, input_section, 1112179407Sobrien output_bfd, error_message); 1113179407Sobrien 1114179407Sobrien /* Sign extend into the upper 32 bits. */ 1115179407Sobrien val = bfd_get_32 (abfd, (bfd_byte *) data + reloc32.address); 1116179407Sobrien if ((val & 0x80000000) != 0) 1117179407Sobrien val = 0xffffffff; 1118179407Sobrien else 1119179407Sobrien val = 0; 1120179407Sobrien addr = reloc_entry->address; 1121179407Sobrien if (bfd_little_endian (abfd)) 1122179407Sobrien addr += 4; 1123179407Sobrien bfd_put_32 (abfd, val, (bfd_byte *) data + addr); 1124179407Sobrien 1125179407Sobrien return r; 1126179407Sobrien} 1127179407Sobrien 1128179407Sobrien/* Handle a mips16 GP relative reloc. */ 1129179407Sobrien 1130179407Sobrienstatic bfd_reloc_status_type 1131179407Sobrienmips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 1132179407Sobrien void *data, asection *input_section, bfd *output_bfd, 1133179407Sobrien char **error_message) 1134179407Sobrien{ 1135179407Sobrien bfd_boolean relocatable; 1136179407Sobrien bfd_reloc_status_type ret; 1137218822Sdim bfd_byte *location; 1138179407Sobrien bfd_vma gp; 1139179407Sobrien 1140179407Sobrien /* If we're relocating, and this is an external symbol, we don't want 1141179407Sobrien to change anything. */ 1142179407Sobrien if (output_bfd != NULL 1143179407Sobrien && (symbol->flags & BSF_SECTION_SYM) == 0 1144179407Sobrien && (symbol->flags & BSF_LOCAL) != 0) 1145179407Sobrien { 1146179407Sobrien reloc_entry->address += input_section->output_offset; 1147179407Sobrien return bfd_reloc_ok; 1148179407Sobrien } 1149179407Sobrien 1150179407Sobrien if (output_bfd != NULL) 1151179407Sobrien relocatable = TRUE; 1152179407Sobrien else 1153179407Sobrien { 1154179407Sobrien relocatable = FALSE; 1155179407Sobrien output_bfd = symbol->section->output_section->owner; 1156179407Sobrien } 1157179407Sobrien 1158179407Sobrien ret = mips_elf_final_gp (output_bfd, symbol, relocatable, error_message, 1159179407Sobrien &gp); 1160179407Sobrien if (ret != bfd_reloc_ok) 1161179407Sobrien return ret; 1162179407Sobrien 1163218822Sdim location = (bfd_byte *) data + reloc_entry->address; 1164218822Sdim _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE, 1165218822Sdim location); 1166218822Sdim ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, 1167218822Sdim input_section, relocatable, 1168218822Sdim data, gp); 1169218822Sdim _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, !relocatable, 1170218822Sdim location); 1171179407Sobrien 1172218822Sdim return ret; 1173179407Sobrien} 1174179407Sobrien 1175179407Sobrien/* A mapping from BFD reloc types to MIPS ELF reloc types. */ 1176179407Sobrien 1177179407Sobrienstruct elf_reloc_map { 1178179407Sobrien bfd_reloc_code_real_type bfd_val; 1179179407Sobrien enum elf_mips_reloc_type elf_val; 1180179407Sobrien}; 1181179407Sobrien 1182179407Sobrienstatic const struct elf_reloc_map mips_reloc_map[] = 1183179407Sobrien{ 1184179407Sobrien { BFD_RELOC_NONE, R_MIPS_NONE }, 1185179407Sobrien { BFD_RELOC_16, R_MIPS_16 }, 1186179407Sobrien { BFD_RELOC_32, R_MIPS_32 }, 1187179407Sobrien /* There is no BFD reloc for R_MIPS_REL32. */ 1188179407Sobrien { BFD_RELOC_64, R_MIPS_64 }, 1189179407Sobrien { BFD_RELOC_MIPS_JMP, R_MIPS_26 }, 1190179407Sobrien { BFD_RELOC_HI16_S, R_MIPS_HI16 }, 1191179407Sobrien { BFD_RELOC_LO16, R_MIPS_LO16 }, 1192179407Sobrien { BFD_RELOC_GPREL16, R_MIPS_GPREL16 }, 1193179407Sobrien { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL }, 1194179407Sobrien { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 }, 1195218822Sdim { BFD_RELOC_16_PCREL_S2, R_MIPS_PC16 }, 1196179407Sobrien { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 }, 1197179407Sobrien { BFD_RELOC_GPREL32, R_MIPS_GPREL32 }, 1198179407Sobrien { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 }, 1199179407Sobrien { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 }, 1200179407Sobrien { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 }, 1201179407Sobrien { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }, 1202179407Sobrien { BFD_RELOC_MIPS_SUB, R_MIPS_SUB }, 1203179407Sobrien { BFD_RELOC_MIPS_GOT_PAGE, R_MIPS_GOT_PAGE }, 1204179407Sobrien { BFD_RELOC_MIPS_GOT_OFST, R_MIPS_GOT_OFST }, 1205218822Sdim { BFD_RELOC_MIPS_GOT_DISP, R_MIPS_GOT_DISP }, 1206218822Sdim { BFD_RELOC_MIPS_TLS_DTPMOD32, R_MIPS_TLS_DTPMOD32 }, 1207218822Sdim { BFD_RELOC_MIPS_TLS_DTPREL32, R_MIPS_TLS_DTPREL32 }, 1208218822Sdim { BFD_RELOC_MIPS_TLS_DTPMOD64, R_MIPS_TLS_DTPMOD64 }, 1209218822Sdim { BFD_RELOC_MIPS_TLS_DTPREL64, R_MIPS_TLS_DTPREL64 }, 1210218822Sdim { BFD_RELOC_MIPS_TLS_GD, R_MIPS_TLS_GD }, 1211218822Sdim { BFD_RELOC_MIPS_TLS_LDM, R_MIPS_TLS_LDM }, 1212218822Sdim { BFD_RELOC_MIPS_TLS_DTPREL_HI16, R_MIPS_TLS_DTPREL_HI16 }, 1213218822Sdim { BFD_RELOC_MIPS_TLS_DTPREL_LO16, R_MIPS_TLS_DTPREL_LO16 }, 1214218822Sdim { BFD_RELOC_MIPS_TLS_GOTTPREL, R_MIPS_TLS_GOTTPREL }, 1215218822Sdim { BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 }, 1216218822Sdim { BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 }, 1217218822Sdim { BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 }, 1218218822Sdim { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 } 1219179407Sobrien}; 1220179407Sobrien 1221218822Sdimstatic const struct elf_reloc_map mips16_reloc_map[] = 1222218822Sdim{ 1223218822Sdim { BFD_RELOC_MIPS16_JMP, R_MIPS16_26 - R_MIPS16_min }, 1224218822Sdim { BFD_RELOC_MIPS16_GPREL, R_MIPS16_GPREL - R_MIPS16_min }, 1225218822Sdim { BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min }, 1226218822Sdim { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min }, 1227218822Sdim}; 1228218822Sdim 1229179407Sobrien/* Given a BFD reloc type, return a howto structure. */ 1230179407Sobrien 1231179407Sobrienstatic reloc_howto_type * 1232179407Sobrienbfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) 1233179407Sobrien{ 1234179407Sobrien unsigned int i; 1235179407Sobrien reloc_howto_type *howto_table = elf_mips_howto_table_rel; 1236218822Sdim reloc_howto_type *howto16_table = elf_mips16_howto_table_rel; 1237179407Sobrien 1238179407Sobrien for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); 1239179407Sobrien i++) 1240179407Sobrien { 1241179407Sobrien if (mips_reloc_map[i].bfd_val == code) 1242179407Sobrien return &howto_table[(int) mips_reloc_map[i].elf_val]; 1243179407Sobrien } 1244179407Sobrien 1245218822Sdim for (i = 0; i < sizeof (mips16_reloc_map) / sizeof (struct elf_reloc_map); 1246218822Sdim i++) 1247218822Sdim { 1248218822Sdim if (mips16_reloc_map[i].bfd_val == code) 1249218822Sdim return &howto16_table[(int) mips16_reloc_map[i].elf_val]; 1250218822Sdim } 1251218822Sdim 1252179407Sobrien switch (code) 1253179407Sobrien { 1254179407Sobrien default: 1255179407Sobrien bfd_set_error (bfd_error_bad_value); 1256179407Sobrien return NULL; 1257179407Sobrien 1258179407Sobrien case BFD_RELOC_CTOR: 1259179407Sobrien /* We need to handle BFD_RELOC_CTOR specially. 1260179407Sobrien Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the 1261179407Sobrien size of addresses of the ABI. */ 1262179407Sobrien if ((elf_elfheader (abfd)->e_flags & (E_MIPS_ABI_O64 1263179407Sobrien | E_MIPS_ABI_EABI64)) != 0) 1264179407Sobrien return &elf_mips_ctor64_howto; 1265179407Sobrien else 1266179407Sobrien return &howto_table[(int) R_MIPS_32]; 1267179407Sobrien 1268179407Sobrien case BFD_RELOC_VTABLE_INHERIT: 1269179407Sobrien return &elf_mips_gnu_vtinherit_howto; 1270179407Sobrien case BFD_RELOC_VTABLE_ENTRY: 1271179407Sobrien return &elf_mips_gnu_vtentry_howto; 1272179407Sobrien case BFD_RELOC_32_PCREL: 1273179407Sobrien return &elf_mips_gnu_pcrel32; 1274179407Sobrien } 1275179407Sobrien} 1276179407Sobrien 1277218822Sdimstatic reloc_howto_type * 1278218822Sdimbfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 1279218822Sdim const char *r_name) 1280218822Sdim{ 1281218822Sdim unsigned int i; 1282218822Sdim 1283218822Sdim for (i = 0; 1284218822Sdim i < (sizeof (elf_mips_howto_table_rel) 1285218822Sdim / sizeof (elf_mips_howto_table_rel[0])); 1286218822Sdim i++) 1287218822Sdim if (elf_mips_howto_table_rel[i].name != NULL 1288218822Sdim && strcasecmp (elf_mips_howto_table_rel[i].name, r_name) == 0) 1289218822Sdim return &elf_mips_howto_table_rel[i]; 1290218822Sdim 1291218822Sdim for (i = 0; 1292218822Sdim i < (sizeof (elf_mips16_howto_table_rel) 1293218822Sdim / sizeof (elf_mips16_howto_table_rel[0])); 1294218822Sdim i++) 1295218822Sdim if (elf_mips16_howto_table_rel[i].name != NULL 1296218822Sdim && strcasecmp (elf_mips16_howto_table_rel[i].name, r_name) == 0) 1297218822Sdim return &elf_mips16_howto_table_rel[i]; 1298218822Sdim 1299218822Sdim if (strcasecmp (elf_mips_gnu_pcrel32.name, r_name) == 0) 1300218822Sdim return &elf_mips_gnu_pcrel32; 1301218822Sdim if (strcasecmp (elf_mips_gnu_rel16_s2.name, r_name) == 0) 1302218822Sdim return &elf_mips_gnu_rel16_s2; 1303218822Sdim if (strcasecmp (elf_mips_gnu_vtinherit_howto.name, r_name) == 0) 1304218822Sdim return &elf_mips_gnu_vtinherit_howto; 1305218822Sdim if (strcasecmp (elf_mips_gnu_vtentry_howto.name, r_name) == 0) 1306218822Sdim return &elf_mips_gnu_vtentry_howto; 1307218822Sdim 1308218822Sdim return NULL; 1309218822Sdim} 1310218822Sdim 1311179407Sobrien/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */ 1312179407Sobrien 1313179407Sobrienstatic reloc_howto_type * 1314179407Sobrienmips_elf32_rtype_to_howto (unsigned int r_type, 1315179407Sobrien bfd_boolean rela_p ATTRIBUTE_UNUSED) 1316179407Sobrien{ 1317179407Sobrien switch (r_type) 1318179407Sobrien { 1319179407Sobrien case R_MIPS_GNU_VTINHERIT: 1320179407Sobrien return &elf_mips_gnu_vtinherit_howto; 1321179407Sobrien case R_MIPS_GNU_VTENTRY: 1322179407Sobrien return &elf_mips_gnu_vtentry_howto; 1323179407Sobrien case R_MIPS_GNU_REL16_S2: 1324179407Sobrien return &elf_mips_gnu_rel16_s2; 1325179407Sobrien case R_MIPS_PC32: 1326179407Sobrien return &elf_mips_gnu_pcrel32; 1327179407Sobrien default: 1328218822Sdim if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max) 1329218822Sdim return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min]; 1330179407Sobrien BFD_ASSERT (r_type < (unsigned int) R_MIPS_max); 1331179407Sobrien return &elf_mips_howto_table_rel[r_type]; 1332179407Sobrien } 1333179407Sobrien} 1334179407Sobrien 1335179407Sobrien/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */ 1336179407Sobrien 1337179407Sobrienstatic void 1338179407Sobrienmips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) 1339179407Sobrien{ 1340218822Sdim const struct elf_backend_data *bed; 1341179407Sobrien unsigned int r_type; 1342179407Sobrien 1343179407Sobrien r_type = ELF32_R_TYPE (dst->r_info); 1344218822Sdim bed = get_elf_backend_data (abfd); 1345218822Sdim cache_ptr->howto = bed->elf_backend_mips_rtype_to_howto (r_type, FALSE); 1346179407Sobrien 1347179407Sobrien /* The addend for a GPREL16 or LITERAL relocation comes from the GP 1348179407Sobrien value for the object file. We get the addend now, rather than 1349179407Sobrien when we do the relocation, because the symbol manipulations done 1350179407Sobrien by the linker may cause us to lose track of the input BFD. */ 1351179407Sobrien if (((*cache_ptr->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0 1352179407Sobrien && (r_type == (unsigned int) R_MIPS_GPREL16 1353179407Sobrien || r_type == (unsigned int) R_MIPS_LITERAL)) 1354179407Sobrien cache_ptr->addend = elf_gp (abfd); 1355179407Sobrien} 1356179407Sobrien 1357179407Sobrien/* Given a MIPS Elf_Internal_Rela, fill in an arelent structure. */ 1358179407Sobrien 1359179407Sobrienstatic void 1360179407Sobrienmips_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) 1361179407Sobrien{ 1362179407Sobrien mips_info_to_howto_rel (abfd, cache_ptr, dst); 1363179407Sobrien 1364179407Sobrien /* If we ever need to do any extra processing with dst->r_addend 1365179407Sobrien (the field omitted in an Elf_Internal_Rel) we can do it here. */ 1366179407Sobrien} 1367179407Sobrien 1368179407Sobrien/* Determine whether a symbol is global for the purposes of splitting 1369179407Sobrien the symbol table into global symbols and local symbols. At least 1370179407Sobrien on Irix 5, this split must be between section symbols and all other 1371179407Sobrien symbols. On most ELF targets the split is between static symbols 1372179407Sobrien and externally visible symbols. */ 1373179407Sobrien 1374179407Sobrienstatic bfd_boolean 1375179407Sobrienmips_elf_sym_is_global (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym) 1376179407Sobrien{ 1377179407Sobrien if (SGI_COMPAT (abfd)) 1378179407Sobrien return (sym->flags & BSF_SECTION_SYM) == 0; 1379179407Sobrien else 1380179407Sobrien return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 1381179407Sobrien || bfd_is_und_section (bfd_get_section (sym)) 1382179407Sobrien || bfd_is_com_section (bfd_get_section (sym))); 1383179407Sobrien} 1384179407Sobrien 1385179407Sobrien/* Set the right machine number for a MIPS ELF file. */ 1386179407Sobrien 1387179407Sobrienstatic bfd_boolean 1388179407Sobrienmips_elf32_object_p (bfd *abfd) 1389179407Sobrien{ 1390179407Sobrien unsigned long mach; 1391179407Sobrien 1392179407Sobrien /* Irix 5 and 6 are broken. Object file symbol tables are not always 1393179407Sobrien sorted correctly such that local symbols precede global symbols, 1394179407Sobrien and the sh_info field in the symbol table is not always right. */ 1395179407Sobrien if (SGI_COMPAT (abfd)) 1396179407Sobrien elf_bad_symtab (abfd) = TRUE; 1397179407Sobrien 1398179407Sobrien if (ABI_N32_P (abfd)) 1399179407Sobrien return FALSE; 1400179407Sobrien 1401179407Sobrien mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags); 1402179407Sobrien bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach); 1403179407Sobrien 1404179407Sobrien return TRUE; 1405179407Sobrien} 1406179407Sobrien 1407179407Sobrien/* MIPS ELF local labels start with '$', not 'L'. */ 1408179407Sobrien 1409179407Sobrienstatic bfd_boolean 1410179407Sobrienmips_elf_is_local_label_name (bfd *abfd, const char *name) 1411179407Sobrien{ 1412179407Sobrien if (name[0] == '$') 1413179407Sobrien return TRUE; 1414179407Sobrien 1415179407Sobrien /* On Irix 6, the labels go back to starting with '.', so we accept 1416179407Sobrien the generic ELF local label syntax as well. */ 1417179407Sobrien return _bfd_elf_is_local_label_name (abfd, name); 1418179407Sobrien} 1419179407Sobrien 1420179407Sobrien/* Support for core dump NOTE sections. */ 1421179407Sobrienstatic bfd_boolean 1422179407Sobrienelf32_mips_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) 1423179407Sobrien{ 1424179407Sobrien int offset; 1425218822Sdim unsigned int size; 1426179407Sobrien 1427179407Sobrien switch (note->descsz) 1428179407Sobrien { 1429179407Sobrien default: 1430179407Sobrien return FALSE; 1431179407Sobrien 1432179407Sobrien case 256: /* Linux/MIPS */ 1433179407Sobrien /* pr_cursig */ 1434179407Sobrien elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); 1435179407Sobrien 1436179407Sobrien /* pr_pid */ 1437179407Sobrien elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); 1438179407Sobrien 1439179407Sobrien /* pr_reg */ 1440179407Sobrien offset = 72; 1441218822Sdim size = 180; 1442179407Sobrien 1443179407Sobrien break; 1444179407Sobrien } 1445179407Sobrien 1446179407Sobrien /* Make a ".reg/999" section. */ 1447179407Sobrien return _bfd_elfcore_make_pseudosection (abfd, ".reg", 1448218822Sdim size, note->descpos + offset); 1449179407Sobrien} 1450179407Sobrien 1451179407Sobrienstatic bfd_boolean 1452179407Sobrienelf32_mips_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) 1453179407Sobrien{ 1454179407Sobrien switch (note->descsz) 1455179407Sobrien { 1456179407Sobrien default: 1457179407Sobrien return FALSE; 1458179407Sobrien 1459179407Sobrien case 128: /* Linux/MIPS elf_prpsinfo */ 1460179407Sobrien elf_tdata (abfd)->core_program 1461179407Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); 1462179407Sobrien elf_tdata (abfd)->core_command 1463179407Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); 1464179407Sobrien } 1465179407Sobrien 1466179407Sobrien /* Note that for some reason, a spurious space is tacked 1467179407Sobrien onto the end of the args in some (at least one anyway) 1468179407Sobrien implementations, so strip it off if it exists. */ 1469179407Sobrien 1470179407Sobrien { 1471179407Sobrien char *command = elf_tdata (abfd)->core_command; 1472179407Sobrien int n = strlen (command); 1473179407Sobrien 1474179407Sobrien if (0 < n && command[n - 1] == ' ') 1475179407Sobrien command[n - 1] = '\0'; 1476179407Sobrien } 1477179407Sobrien 1478179407Sobrien return TRUE; 1479179407Sobrien} 1480179407Sobrien 1481179407Sobrien/* Depending on the target vector we generate some version of Irix 1482179407Sobrien executables or "normal" MIPS ELF ABI executables. */ 1483179407Sobrienstatic irix_compat_t 1484179407Sobrienelf32_mips_irix_compat (bfd *abfd) 1485179407Sobrien{ 1486179407Sobrien if ((abfd->xvec == &bfd_elf32_bigmips_vec) 1487179407Sobrien || (abfd->xvec == &bfd_elf32_littlemips_vec)) 1488179407Sobrien return ict_irix5; 1489179407Sobrien else 1490179407Sobrien return ict_none; 1491179407Sobrien} 1492179407Sobrien 1493179407Sobrien/* ECOFF swapping routines. These are used when dealing with the 1494179407Sobrien .mdebug section, which is in the ECOFF debugging format. */ 1495179407Sobrienstatic const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { 1496179407Sobrien /* Symbol table magic number. */ 1497179407Sobrien magicSym, 1498179407Sobrien /* Alignment of debugging information. E.g., 4. */ 1499179407Sobrien 4, 1500179407Sobrien /* Sizes of external symbolic information. */ 1501179407Sobrien sizeof (struct hdr_ext), 1502179407Sobrien sizeof (struct dnr_ext), 1503179407Sobrien sizeof (struct pdr_ext), 1504179407Sobrien sizeof (struct sym_ext), 1505179407Sobrien sizeof (struct opt_ext), 1506179407Sobrien sizeof (struct fdr_ext), 1507179407Sobrien sizeof (struct rfd_ext), 1508179407Sobrien sizeof (struct ext_ext), 1509179407Sobrien /* Functions to swap in external symbolic data. */ 1510179407Sobrien ecoff_swap_hdr_in, 1511179407Sobrien ecoff_swap_dnr_in, 1512179407Sobrien ecoff_swap_pdr_in, 1513179407Sobrien ecoff_swap_sym_in, 1514179407Sobrien ecoff_swap_opt_in, 1515179407Sobrien ecoff_swap_fdr_in, 1516179407Sobrien ecoff_swap_rfd_in, 1517179407Sobrien ecoff_swap_ext_in, 1518179407Sobrien _bfd_ecoff_swap_tir_in, 1519179407Sobrien _bfd_ecoff_swap_rndx_in, 1520179407Sobrien /* Functions to swap out external symbolic data. */ 1521179407Sobrien ecoff_swap_hdr_out, 1522179407Sobrien ecoff_swap_dnr_out, 1523179407Sobrien ecoff_swap_pdr_out, 1524179407Sobrien ecoff_swap_sym_out, 1525179407Sobrien ecoff_swap_opt_out, 1526179407Sobrien ecoff_swap_fdr_out, 1527179407Sobrien ecoff_swap_rfd_out, 1528179407Sobrien ecoff_swap_ext_out, 1529179407Sobrien _bfd_ecoff_swap_tir_out, 1530179407Sobrien _bfd_ecoff_swap_rndx_out, 1531179407Sobrien /* Function to read in symbolic data. */ 1532179407Sobrien _bfd_mips_elf_read_ecoff_info 1533179407Sobrien}; 1534179407Sobrien 1535179407Sobrien#define ELF_ARCH bfd_arch_mips 1536179407Sobrien#define ELF_MACHINE_CODE EM_MIPS 1537179407Sobrien 1538179407Sobrien#define elf_backend_collect TRUE 1539179407Sobrien#define elf_backend_type_change_ok TRUE 1540179407Sobrien#define elf_backend_can_gc_sections TRUE 1541179407Sobrien#define elf_info_to_howto mips_info_to_howto_rela 1542179407Sobrien#define elf_info_to_howto_rel mips_info_to_howto_rel 1543179407Sobrien#define elf_backend_sym_is_global mips_elf_sym_is_global 1544179407Sobrien#define elf_backend_object_p mips_elf32_object_p 1545179407Sobrien#define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing 1546179407Sobrien#define elf_backend_section_processing _bfd_mips_elf_section_processing 1547179407Sobrien#define elf_backend_section_from_shdr _bfd_mips_elf_section_from_shdr 1548179407Sobrien#define elf_backend_fake_sections _bfd_mips_elf_fake_sections 1549179407Sobrien#define elf_backend_section_from_bfd_section \ 1550179407Sobrien _bfd_mips_elf_section_from_bfd_section 1551179407Sobrien#define elf_backend_add_symbol_hook _bfd_mips_elf_add_symbol_hook 1552179407Sobrien#define elf_backend_link_output_symbol_hook \ 1553179407Sobrien _bfd_mips_elf_link_output_symbol_hook 1554179407Sobrien#define elf_backend_create_dynamic_sections \ 1555179407Sobrien _bfd_mips_elf_create_dynamic_sections 1556179407Sobrien#define elf_backend_check_relocs _bfd_mips_elf_check_relocs 1557218822Sdim#define elf_backend_merge_symbol_attribute \ 1558218822Sdim _bfd_mips_elf_merge_symbol_attribute 1559179407Sobrien#define elf_backend_adjust_dynamic_symbol \ 1560179407Sobrien _bfd_mips_elf_adjust_dynamic_symbol 1561179407Sobrien#define elf_backend_always_size_sections \ 1562179407Sobrien _bfd_mips_elf_always_size_sections 1563179407Sobrien#define elf_backend_size_dynamic_sections \ 1564179407Sobrien _bfd_mips_elf_size_dynamic_sections 1565218822Sdim#define elf_backend_init_index_section _bfd_elf_init_1_index_section 1566179407Sobrien#define elf_backend_relocate_section _bfd_mips_elf_relocate_section 1567179407Sobrien#define elf_backend_finish_dynamic_symbol \ 1568179407Sobrien _bfd_mips_elf_finish_dynamic_symbol 1569179407Sobrien#define elf_backend_finish_dynamic_sections \ 1570179407Sobrien _bfd_mips_elf_finish_dynamic_sections 1571179407Sobrien#define elf_backend_final_write_processing \ 1572179407Sobrien _bfd_mips_elf_final_write_processing 1573179407Sobrien#define elf_backend_additional_program_headers \ 1574179407Sobrien _bfd_mips_elf_additional_program_headers 1575179407Sobrien#define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map 1576179407Sobrien#define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook 1577179407Sobrien#define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook 1578179407Sobrien#define elf_backend_copy_indirect_symbol \ 1579179407Sobrien _bfd_mips_elf_copy_indirect_symbol 1580179407Sobrien#define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol 1581179407Sobrien#define elf_backend_grok_prstatus elf32_mips_grok_prstatus 1582179407Sobrien#define elf_backend_grok_psinfo elf32_mips_grok_psinfo 1583179407Sobrien#define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap 1584179407Sobrien 1585179407Sobrien#define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO) 1586179407Sobrien#define elf_backend_may_use_rel_p 1 1587179407Sobrien#define elf_backend_may_use_rela_p 0 1588179407Sobrien#define elf_backend_default_use_rela_p 0 1589179407Sobrien#define elf_backend_sign_extend_vma TRUE 1590179407Sobrien 1591179407Sobrien#define elf_backend_discard_info _bfd_mips_elf_discard_info 1592179407Sobrien#define elf_backend_ignore_discarded_relocs \ 1593179407Sobrien _bfd_mips_elf_ignore_discarded_relocs 1594179407Sobrien#define elf_backend_mips_irix_compat elf32_mips_irix_compat 1595179407Sobrien#define elf_backend_mips_rtype_to_howto mips_elf32_rtype_to_howto 1596179407Sobrien#define bfd_elf32_bfd_is_local_label_name \ 1597179407Sobrien mips_elf_is_local_label_name 1598179407Sobrien#define bfd_elf32_find_nearest_line _bfd_mips_elf_find_nearest_line 1599218822Sdim#define bfd_elf32_find_inliner_info _bfd_mips_elf_find_inliner_info 1600179407Sobrien#define bfd_elf32_new_section_hook _bfd_mips_elf_new_section_hook 1601179407Sobrien#define bfd_elf32_set_section_contents _bfd_mips_elf_set_section_contents 1602179407Sobrien#define bfd_elf32_bfd_get_relocated_section_contents \ 1603179407Sobrien _bfd_elf_mips_get_relocated_section_contents 1604179407Sobrien#define bfd_elf32_bfd_link_hash_table_create \ 1605179407Sobrien _bfd_mips_elf_link_hash_table_create 1606179407Sobrien#define bfd_elf32_bfd_final_link _bfd_mips_elf_final_link 1607179407Sobrien#define bfd_elf32_bfd_merge_private_bfd_data \ 1608179407Sobrien _bfd_mips_elf_merge_private_bfd_data 1609179407Sobrien#define bfd_elf32_bfd_set_private_flags _bfd_mips_elf_set_private_flags 1610179407Sobrien#define bfd_elf32_bfd_print_private_bfd_data \ 1611179407Sobrien _bfd_mips_elf_print_private_bfd_data 1612179407Sobrien 1613179407Sobrien/* Support for SGI-ish mips targets. */ 1614179407Sobrien#define TARGET_LITTLE_SYM bfd_elf32_littlemips_vec 1615179407Sobrien#define TARGET_LITTLE_NAME "elf32-littlemips" 1616179407Sobrien#define TARGET_BIG_SYM bfd_elf32_bigmips_vec 1617179407Sobrien#define TARGET_BIG_NAME "elf32-bigmips" 1618179407Sobrien 1619179407Sobrien/* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses 1620179407Sobrien a value of 0x1000, and we are compatible. */ 1621179407Sobrien#define ELF_MAXPAGESIZE 0x1000 1622218822Sdim#define ELF_COMMONPAGESIZE 0x1000 1623179407Sobrien 1624179407Sobrien#include "elf32-target.h" 1625179407Sobrien 1626179407Sobrien/* Support for traditional mips targets. */ 1627179407Sobrien#undef TARGET_LITTLE_SYM 1628179407Sobrien#undef TARGET_LITTLE_NAME 1629179407Sobrien#undef TARGET_BIG_SYM 1630179407Sobrien#undef TARGET_BIG_NAME 1631179407Sobrien 1632179407Sobrien#undef ELF_MAXPAGESIZE 1633218822Sdim#undef ELF_COMMONPAGESIZE 1634179407Sobrien 1635179407Sobrien#define TARGET_LITTLE_SYM bfd_elf32_tradlittlemips_vec 1636179407Sobrien#define TARGET_LITTLE_NAME "elf32-tradlittlemips" 1637179407Sobrien#define TARGET_BIG_SYM bfd_elf32_tradbigmips_vec 1638179407Sobrien#define TARGET_BIG_NAME "elf32-tradbigmips" 1639179407Sobrien 1640218822Sdim/* The MIPS ABI says at Page 5-1: 1641218822Sdim Virtual addresses and file offsets for MIPS segments are congruent 1642218822Sdim modulo 64 KByte (0x10000) or larger powers of 2. Because 64 KBytes 1643218822Sdim is the maximum page size, the files are suitable for paging 1644218822Sdim regardless of physical page size. */ 1645179407Sobrien#define ELF_MAXPAGESIZE 0x10000 1646218822Sdim#define ELF_COMMONPAGESIZE 0x1000 1647179407Sobrien#define elf32_bed elf32_tradbed 1648179407Sobrien 1649179407Sobrien/* Include the target file again for this target. */ 1650179407Sobrien#include "elf32-target.h" 1651218822Sdim 1652218822Sdim 1653218822Sdim/* Specific to VxWorks. */ 1654218822Sdimstatic reloc_howto_type mips_vxworks_copy_howto_rela = 1655218822Sdim HOWTO (R_MIPS_COPY, /* type */ 1656218822Sdim 0, /* rightshift */ 1657218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1658218822Sdim 32, /* bitsize */ 1659218822Sdim FALSE, /* pc_relative */ 1660218822Sdim 0, /* bitpos */ 1661218822Sdim complain_overflow_bitfield, /* complain_on_overflow */ 1662218822Sdim bfd_elf_generic_reloc, /* special_function */ 1663218822Sdim "R_MIPS_COPY", /* name */ 1664218822Sdim FALSE, /* partial_inplace */ 1665218822Sdim 0x0, /* src_mask */ 1666218822Sdim 0x0, /* dst_mask */ 1667218822Sdim FALSE); /* pcrel_offset */ 1668218822Sdim 1669218822Sdim/* Specific to VxWorks. */ 1670218822Sdimstatic reloc_howto_type mips_vxworks_jump_slot_howto_rela = 1671218822Sdim HOWTO (R_MIPS_JUMP_SLOT, /* type */ 1672218822Sdim 0, /* rightshift */ 1673218822Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1674218822Sdim 32, /* bitsize */ 1675218822Sdim FALSE, /* pc_relative */ 1676218822Sdim 0, /* bitpos */ 1677218822Sdim complain_overflow_bitfield, /* complain_on_overflow */ 1678218822Sdim bfd_elf_generic_reloc, /* special_function */ 1679218822Sdim "R_MIPS_JUMP_SLOT", /* name */ 1680218822Sdim FALSE, /* partial_inplace */ 1681218822Sdim 0x0, /* src_mask */ 1682218822Sdim 0x0, /* dst_mask */ 1683218822Sdim FALSE); /* pcrel_offset */ 1684218822Sdim 1685218822Sdim/* Implement elf_backend_bfd_reloc_type_lookup for VxWorks. */ 1686218822Sdim 1687218822Sdimstatic reloc_howto_type * 1688218822Sdimmips_vxworks_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) 1689218822Sdim{ 1690218822Sdim switch (code) 1691218822Sdim { 1692218822Sdim case BFD_RELOC_MIPS_COPY: 1693218822Sdim return &mips_vxworks_copy_howto_rela; 1694218822Sdim case BFD_RELOC_MIPS_JUMP_SLOT: 1695218822Sdim return &mips_vxworks_jump_slot_howto_rela; 1696218822Sdim default: 1697218822Sdim return bfd_elf32_bfd_reloc_type_lookup (abfd, code); 1698218822Sdim } 1699218822Sdim} 1700218822Sdim 1701218822Sdimstatic reloc_howto_type * 1702218822Sdimmips_vxworks_bfd_reloc_name_lookup (bfd *abfd, const char *r_name) 1703218822Sdim{ 1704218822Sdim if (strcasecmp (mips_vxworks_copy_howto_rela.name, r_name) == 0) 1705218822Sdim return &mips_vxworks_copy_howto_rela; 1706218822Sdim if (strcasecmp (mips_vxworks_jump_slot_howto_rela.name, r_name) == 0) 1707218822Sdim return &mips_vxworks_jump_slot_howto_rela; 1708218822Sdim 1709218822Sdim return bfd_elf32_bfd_reloc_name_lookup (abfd, r_name); 1710218822Sdim} 1711218822Sdim 1712218822Sdim/* Implement elf_backend_mips_rtype_to_lookup for VxWorks. */ 1713218822Sdim 1714218822Sdimstatic reloc_howto_type * 1715218822Sdimmips_vxworks_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p) 1716218822Sdim{ 1717218822Sdim switch (r_type) 1718218822Sdim { 1719218822Sdim case R_MIPS_COPY: 1720218822Sdim return &mips_vxworks_copy_howto_rela; 1721218822Sdim case R_MIPS_JUMP_SLOT: 1722218822Sdim return &mips_vxworks_jump_slot_howto_rela; 1723218822Sdim default: 1724218822Sdim return mips_elf32_rtype_to_howto (r_type, rela_p); 1725218822Sdim } 1726218822Sdim} 1727218822Sdim 1728218822Sdim/* Implement elf_backend_final_write_processing for VxWorks. */ 1729218822Sdim 1730218822Sdimstatic void 1731218822Sdimmips_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker) 1732218822Sdim{ 1733218822Sdim _bfd_mips_elf_final_write_processing (abfd, linker); 1734218822Sdim elf_vxworks_final_write_processing (abfd, linker); 1735218822Sdim} 1736218822Sdim 1737218822Sdim#undef TARGET_LITTLE_SYM 1738218822Sdim#undef TARGET_LITTLE_NAME 1739218822Sdim#undef TARGET_BIG_SYM 1740218822Sdim#undef TARGET_BIG_NAME 1741218822Sdim 1742218822Sdim#undef ELF_MAXPAGESIZE 1743218822Sdim#undef ELF_COMMONPAGESIZE 1744218822Sdim 1745218822Sdim#define TARGET_LITTLE_SYM bfd_elf32_littlemips_vxworks_vec 1746218822Sdim#define TARGET_LITTLE_NAME "elf32-littlemips-vxworks" 1747218822Sdim#define TARGET_BIG_SYM bfd_elf32_bigmips_vxworks_vec 1748218822Sdim#define TARGET_BIG_NAME "elf32-bigmips-vxworks" 1749218822Sdim 1750218822Sdim#undef elf32_bed 1751218822Sdim#define elf32_bed elf32_mips_vxworks_bed 1752218822Sdim 1753218822Sdim#define ELF_MAXPAGESIZE 0x1000 1754218822Sdim#define ELF_COMMONPAGESIZE 0x1000 1755218822Sdim 1756218822Sdim#undef elf_backend_want_got_plt 1757218822Sdim#define elf_backend_want_got_plt 1 1758218822Sdim#undef elf_backend_want_plt_sym 1759218822Sdim#define elf_backend_want_plt_sym 1 1760218822Sdim#undef elf_backend_got_symbol_offset 1761218822Sdim#define elf_backend_got_symbol_offset 0 1762218822Sdim#undef elf_backend_want_dynbss 1763218822Sdim#define elf_backend_want_dynbss 1 1764218822Sdim#undef elf_backend_may_use_rel_p 1765218822Sdim#define elf_backend_may_use_rel_p 0 1766218822Sdim#undef elf_backend_may_use_rela_p 1767218822Sdim#define elf_backend_may_use_rela_p 1 1768218822Sdim#undef elf_backend_default_use_rela_p 1769218822Sdim#define elf_backend_default_use_rela_p 1 1770218822Sdim#undef elf_backend_got_header_size 1771218822Sdim#define elf_backend_got_header_size (4 * 3) 1772218822Sdim#undef elf_backend_plt_readonly 1773218822Sdim#define elf_backend_plt_readonly 1 1774218822Sdim 1775218822Sdim#undef bfd_elf32_bfd_reloc_type_lookup 1776218822Sdim#define bfd_elf32_bfd_reloc_type_lookup \ 1777218822Sdim mips_vxworks_bfd_reloc_type_lookup 1778218822Sdim#undef bfd_elf32_bfd_reloc_name_lookup 1779218822Sdim#define bfd_elf32_bfd_reloc_name_lookup \ 1780218822Sdim mips_vxworks_bfd_reloc_name_lookup 1781218822Sdim#undef elf_backend_mips_rtype_to_howto 1782218822Sdim#define elf_backend_mips_rtype_to_howto \ 1783218822Sdim mips_vxworks_rtype_to_howto 1784218822Sdim#undef elf_backend_adjust_dynamic_symbol 1785218822Sdim#define elf_backend_adjust_dynamic_symbol \ 1786218822Sdim _bfd_mips_vxworks_adjust_dynamic_symbol 1787218822Sdim#undef elf_backend_finish_dynamic_symbol 1788218822Sdim#define elf_backend_finish_dynamic_symbol \ 1789218822Sdim _bfd_mips_vxworks_finish_dynamic_symbol 1790218822Sdim#undef bfd_elf32_bfd_link_hash_table_create 1791218822Sdim#define bfd_elf32_bfd_link_hash_table_create \ 1792218822Sdim _bfd_mips_vxworks_link_hash_table_create 1793218822Sdim#undef elf_backend_add_symbol_hook 1794218822Sdim#define elf_backend_add_symbol_hook \ 1795218822Sdim elf_vxworks_add_symbol_hook 1796218822Sdim#undef elf_backend_link_output_symbol_hook 1797218822Sdim#define elf_backend_link_output_symbol_hook \ 1798218822Sdim elf_vxworks_link_output_symbol_hook 1799218822Sdim#undef elf_backend_emit_relocs 1800218822Sdim#define elf_backend_emit_relocs \ 1801218822Sdim elf_vxworks_emit_relocs 1802218822Sdim#undef elf_backend_final_write_processing 1803218822Sdim#define elf_backend_final_write_processing \ 1804218822Sdim mips_vxworks_final_write_processing 1805218822Sdim 1806218822Sdim#undef elf_backend_additional_program_headers 1807218822Sdim#undef elf_backend_modify_segment_map 1808218822Sdim#undef elf_backend_symbol_processing 1809218822Sdim/* NOTE: elf_backend_rela_normal is not defined for MIPS. */ 1810218822Sdim 1811218822Sdim#include "elf32-target.h" 1812