Home | History | Annotate | Line # | Download | only in bfd
elf32-fr30.c revision 1.1.1.1
      1 /* FR30-specific support for 32-bit ELF.
      2    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
      3    2010, 2012
      4    Free Software Foundation, Inc.
      5 
      6    This file is part of BFD, the Binary File Descriptor library.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21    MA 02110-1301, USA.  */
     22 
     23 #include "sysdep.h"
     24 #include "bfd.h"
     25 #include "libbfd.h"
     26 #include "elf-bfd.h"
     27 #include "elf/fr30.h"
     28 
     29 /* Forward declarations.  */
     30 static bfd_reloc_status_type
     31 fr30_elf_i20_reloc (bfd *, arelent *, asymbol *, void * data,
     32 		    asection *, bfd *, char **error_message);
     33 static bfd_reloc_status_type
     34 fr30_elf_i32_reloc (bfd *, arelent *, asymbol *, void *,
     35 		    asection *, bfd *, char **);
     36 
     37 static reloc_howto_type fr30_elf_howto_table [] =
     38 {
     39   /* This reloc does nothing.  */
     40   HOWTO (R_FR30_NONE,		/* type */
     41 	 0,			/* rightshift */
     42 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
     43 	 32,			/* bitsize */
     44 	 FALSE,			/* pc_relative */
     45 	 0,			/* bitpos */
     46 	 complain_overflow_bitfield, /* complain_on_overflow */
     47 	 bfd_elf_generic_reloc,	/* special_function */
     48 	 "R_FR30_NONE",		/* name */
     49 	 FALSE,			/* partial_inplace */
     50 	 0,			/* src_mask */
     51 	 0,			/* dst_mask */
     52 	 FALSE),		/* pcrel_offset */
     53 
     54   /* An 8 bit absolute relocation.  */
     55   HOWTO (R_FR30_8,		/* type */
     56 	 0,			/* rightshift */
     57 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
     58 	 8,			/* bitsize */
     59 	 FALSE,			/* pc_relative */
     60 	 4,			/* bitpos */
     61 	 complain_overflow_bitfield, /* complain_on_overflow */
     62 	 bfd_elf_generic_reloc,	/* special_function */
     63 	 "R_FR30_8",		/* name */
     64 	 FALSE,			/* partial_inplace */
     65 	 0x0000,		/* src_mask */
     66 	 0x0ff0,		/* dst_mask */
     67 	 FALSE),		/* pcrel_offset */
     68 
     69   /* A 20 bit absolute relocation.  */
     70   HOWTO (R_FR30_20,		/* type */
     71 	 0,			/* rightshift */
     72 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
     73 	 20,			/* bitsize */
     74 	 FALSE,			/* pc_relative */
     75 	 0,			/* bitpos */
     76 	 complain_overflow_bitfield, /* complain_on_overflow */
     77 	 fr30_elf_i20_reloc,	/* special_function */
     78 	 "R_FR30_20",		/* name */
     79 	 FALSE,			/* partial_inplace */
     80 	 0x00000000,		/* src_mask */
     81 	 0x00f0ffff,		/* dst_mask */
     82 	 FALSE),		/* pcrel_offset */
     83 
     84   /* A 32 bit absolute relocation.  */
     85   HOWTO (R_FR30_32,		/* type */
     86 	 0,			/* rightshift */
     87 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
     88 	 32,			/* bitsize */
     89 	 FALSE,			/* pc_relative */
     90 	 0,			/* bitpos */
     91 	 complain_overflow_bitfield, /* complain_on_overflow */
     92 	 bfd_elf_generic_reloc,	/* special_function */
     93 	 "R_FR30_32",		/* name */
     94 	 FALSE,			/* partial_inplace */
     95 	 0x00000000,		/* src_mask */
     96 	 0xffffffff,		/* dst_mask */
     97 	 FALSE),		/* pcrel_offset */
     98 
     99   /* A 32 bit into 48 bits absolute relocation.  */
    100   HOWTO (R_FR30_48,		/* type */
    101 	 0,			/* rightshift */
    102 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    103 	 32,			/* bitsize */
    104 	 FALSE,			/* pc_relative */
    105 	 0,			/* bitpos */
    106 	 complain_overflow_bitfield, /* complain_on_overflow */
    107 	 fr30_elf_i32_reloc,	/* special_function */
    108 	 "R_FR30_48",		/* name */
    109 	 FALSE,			/* partial_inplace */
    110 	 0x00000000,		/* src_mask */
    111 	 0xffffffff,		/* dst_mask */
    112 	 FALSE),		/* pcrel_offset */
    113 
    114   /* A 6 bit absolute relocation.  */
    115   HOWTO (R_FR30_6_IN_4,		/* type */
    116 	 2,			/* rightshift */
    117 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    118 	 6,			/* bitsize */
    119 	 FALSE,			/* pc_relative */
    120 	 4,			/* bitpos */
    121 	 complain_overflow_unsigned, /* complain_on_overflow */
    122 	 bfd_elf_generic_reloc,	/* special_function */
    123 	 "R_FR30_6_IN_4",	/* name */
    124 	 FALSE,			/* partial_inplace */
    125 	 0x0000,		/* src_mask */
    126 	 0x00f0,		/* dst_mask */
    127 	 FALSE),		/* pcrel_offset */
    128 
    129   /* An 8 bit absolute relocation.  */
    130   HOWTO (R_FR30_8_IN_8,		/* type */
    131 	 0,			/* rightshift */
    132 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    133 	 8,			/* bitsize */
    134 	 FALSE,			/* pc_relative */
    135 	 4,			/* bitpos */
    136 	 complain_overflow_signed, /* complain_on_overflow */
    137 	 bfd_elf_generic_reloc,/* special_function */
    138 	 "R_FR30_8_IN_8",	/* name */
    139 	 FALSE,			/* partial_inplace */
    140 	 0x0000,		/* src_mask */
    141 	 0x0ff0,		/* dst_mask */
    142 	 FALSE),		/* pcrel_offset */
    143 
    144   /* A 9 bit absolute relocation.  */
    145   HOWTO (R_FR30_9_IN_8,		/* type */
    146 	 1,			/* rightshift */
    147 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    148 	 9,			/* bitsize */
    149 	 FALSE,			/* pc_relative */
    150 	 4,			/* bitpos */
    151 	 complain_overflow_signed, /* complain_on_overflow */
    152 	 bfd_elf_generic_reloc,/* special_function */
    153 	 "R_FR30_9_IN_8",	/* name */
    154 	 FALSE,			/* partial_inplace */
    155 	 0x0000,		/* src_mask */
    156 	 0x0ff0,		/* dst_mask */
    157 	 FALSE),		/* pcrel_offset */
    158 
    159   /* A 10 bit absolute relocation.  */
    160   HOWTO (R_FR30_10_IN_8,	/* type */
    161 	 2,			/* rightshift */
    162 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    163 	 10,			/* bitsize */
    164 	 FALSE,			/* pc_relative */
    165 	 4,			/* bitpos */
    166 	 complain_overflow_signed, /* complain_on_overflow */
    167 	 bfd_elf_generic_reloc,/* special_function */
    168 	 "R_FR30_10_IN_8",	/* name */
    169 	 FALSE,			/* partial_inplace */
    170 	 0x0000,		/* src_mask */
    171 	 0x0ff0,		/* dst_mask */
    172 	 FALSE),		/* pcrel_offset */
    173 
    174   /* A PC relative 9 bit relocation, right shifted by 1.  */
    175   HOWTO (R_FR30_9_PCREL,	/* type */
    176 	 1,			/* rightshift */
    177 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    178 	 9,			/* bitsize */
    179 	 TRUE,			/* pc_relative */
    180 	 0,			/* bitpos */
    181 	 complain_overflow_signed, /* complain_on_overflow */
    182 	 bfd_elf_generic_reloc, /* special_function */
    183 	 "R_FR30_9_PCREL",	/* name */
    184 	 FALSE,			/* partial_inplace */
    185 	 0x0000,		/* src_mask */
    186 	 0x00ff,		/* dst_mask */
    187 	 FALSE),		/* pcrel_offset */
    188 
    189   /* A PC relative 12 bit relocation, right shifted by 1.  */
    190   HOWTO (R_FR30_12_PCREL,	/* type */
    191 	 1,			/* rightshift */
    192 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    193 	 12,			/* bitsize */
    194 	 TRUE,			/* pc_relative */
    195 	 0,			/* bitpos */
    196 	 complain_overflow_signed, /* complain_on_overflow */
    197 	 bfd_elf_generic_reloc, /* special_function */
    198 	 "R_FR30_12_PCREL",	/* name */
    199 	 FALSE,			/* partial_inplace */
    200 	 0x0000,		/* src_mask */
    201 	 0x07ff,		/* dst_mask */
    202 	 FALSE),		/* pcrel_offset */
    203   /* GNU extension to record C++ vtable hierarchy */
    204   HOWTO (R_FR30_GNU_VTINHERIT, /* type */
    205          0,                     /* rightshift */
    206          2,                     /* size (0 = byte, 1 = short, 2 = long) */
    207          0,                     /* bitsize */
    208          FALSE,                 /* pc_relative */
    209          0,                     /* bitpos */
    210          complain_overflow_dont, /* complain_on_overflow */
    211          NULL,                  /* special_function */
    212          "R_FR30_GNU_VTINHERIT", /* name */
    213          FALSE,                 /* partial_inplace */
    214          0,                     /* src_mask */
    215          0,                     /* dst_mask */
    216          FALSE),                /* pcrel_offset */
    217 
    218   /* GNU extension to record C++ vtable member usage */
    219   HOWTO (R_FR30_GNU_VTENTRY,     /* type */
    220          0,                     /* rightshift */
    221          2,                     /* size (0 = byte, 1 = short, 2 = long) */
    222          0,                     /* bitsize */
    223          FALSE,                 /* pc_relative */
    224          0,                     /* bitpos */
    225          complain_overflow_dont, /* complain_on_overflow */
    226          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
    227          "R_FR30_GNU_VTENTRY",   /* name */
    228          FALSE,                 /* partial_inplace */
    229          0,                     /* src_mask */
    230          0,                     /* dst_mask */
    231          FALSE),                /* pcrel_offset */
    232 };
    233 
    234 /* Utility to actually perform an R_FR30_20 reloc.  */
    236 
    237 static bfd_reloc_status_type
    238 fr30_elf_i20_reloc (bfd *abfd,
    239 		    arelent *reloc_entry,
    240 		    asymbol *symbol,
    241 		    void * data,
    242 		    asection *input_section,
    243 		    bfd *output_bfd,
    244 		    char **error_message ATTRIBUTE_UNUSED)
    245 {
    246   bfd_vma relocation;
    247   unsigned long x;
    248 
    249   /* This part is from bfd_elf_generic_reloc.  */
    250   if (output_bfd != (bfd *) NULL
    251       && (symbol->flags & BSF_SECTION_SYM) == 0
    252       && (! reloc_entry->howto->partial_inplace
    253 	  || reloc_entry->addend == 0))
    254     {
    255       reloc_entry->address += input_section->output_offset;
    256       return bfd_reloc_ok;
    257     }
    258 
    259   if (output_bfd != NULL)
    260     /* FIXME: See bfd_perform_relocation.  Is this right?  */
    261     return bfd_reloc_ok;
    262 
    263   relocation =
    264     symbol->value
    265     + symbol->section->output_section->vma
    266     + symbol->section->output_offset
    267     + reloc_entry->addend;
    268 
    269   if (relocation > (((bfd_vma) 1 << 20) - 1))
    270     return bfd_reloc_overflow;
    271 
    272   x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
    273   x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
    274   bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
    275 
    276   return bfd_reloc_ok;
    277 }
    278 
    279 /* Utility to actually perform a R_FR30_48 reloc.  */
    281 
    282 static bfd_reloc_status_type
    283 fr30_elf_i32_reloc (bfd *abfd,
    284 		    arelent *reloc_entry,
    285 		    asymbol *symbol,
    286 		    void * data,
    287 		    asection *input_section,
    288 		    bfd *output_bfd,
    289 		    char **error_message ATTRIBUTE_UNUSED)
    290 {
    291   bfd_vma relocation;
    292 
    293   /* This part is from bfd_elf_generic_reloc.  */
    294   if (output_bfd != (bfd *) NULL
    295       && (symbol->flags & BSF_SECTION_SYM) == 0
    296       && (! reloc_entry->howto->partial_inplace
    297 	  || reloc_entry->addend == 0))
    298     {
    299       reloc_entry->address += input_section->output_offset;
    300       return bfd_reloc_ok;
    301     }
    302 
    303   if (output_bfd != NULL)
    304     /* FIXME: See bfd_perform_relocation.  Is this right?  */
    305     return bfd_reloc_ok;
    306 
    307   relocation =
    308     symbol->value
    309     + symbol->section->output_section->vma
    310     + symbol->section->output_offset
    311     + reloc_entry->addend;
    312 
    313   bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
    314 
    315   return bfd_reloc_ok;
    316 }
    317 
    318 /* Map BFD reloc types to FR30 ELF reloc types.  */
    320 
    321 struct fr30_reloc_map
    322 {
    323   bfd_reloc_code_real_type bfd_reloc_val;
    324   unsigned int fr30_reloc_val;
    325 };
    326 
    327 static const struct fr30_reloc_map fr30_reloc_map [] =
    328 {
    329   { BFD_RELOC_NONE,           R_FR30_NONE },
    330   { BFD_RELOC_8,              R_FR30_8 },
    331   { BFD_RELOC_FR30_20,        R_FR30_20 },
    332   { BFD_RELOC_32,             R_FR30_32 },
    333   { BFD_RELOC_FR30_48,        R_FR30_48 },
    334   { BFD_RELOC_FR30_6_IN_4,    R_FR30_6_IN_4 },
    335   { BFD_RELOC_FR30_8_IN_8,    R_FR30_8_IN_8 },
    336   { BFD_RELOC_FR30_9_IN_8,    R_FR30_9_IN_8 },
    337   { BFD_RELOC_FR30_10_IN_8,   R_FR30_10_IN_8 },
    338   { BFD_RELOC_FR30_9_PCREL,   R_FR30_9_PCREL },
    339   { BFD_RELOC_FR30_12_PCREL,  R_FR30_12_PCREL },
    340   { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
    341   { BFD_RELOC_VTABLE_ENTRY,   R_FR30_GNU_VTENTRY },
    342 };
    343 
    344 static reloc_howto_type *
    345 fr30_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    346 			bfd_reloc_code_real_type code)
    347 {
    348   unsigned int i;
    349 
    350   for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
    351        --i;)
    352     if (fr30_reloc_map [i].bfd_reloc_val == code)
    353       return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
    354 
    355   return NULL;
    356 }
    357 
    358 static reloc_howto_type *
    359 fr30_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
    360 {
    361   unsigned int i;
    362 
    363   for (i = 0;
    364        i < sizeof (fr30_elf_howto_table) / sizeof (fr30_elf_howto_table[0]);
    365        i++)
    366     if (fr30_elf_howto_table[i].name != NULL
    367 	&& strcasecmp (fr30_elf_howto_table[i].name, r_name) == 0)
    368       return &fr30_elf_howto_table[i];
    369 
    370   return NULL;
    371 }
    372 
    373 /* Set the howto pointer for an FR30 ELF reloc.  */
    374 
    375 static void
    376 fr30_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
    377 			 arelent *cache_ptr,
    378 			 Elf_Internal_Rela *dst)
    379 {
    380   unsigned int r_type;
    381 
    382   r_type = ELF32_R_TYPE (dst->r_info);
    383   BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
    384   cache_ptr->howto = & fr30_elf_howto_table [r_type];
    385 }
    386 
    387 /* Perform a single relocation.  By default we use the standard BFD
    389    routines, but a few relocs, we have to do them ourselves.  */
    390 
    391 static bfd_reloc_status_type
    392 fr30_final_link_relocate (reloc_howto_type *howto,
    393 			  bfd *input_bfd,
    394 			  asection *input_section,
    395 			  bfd_byte *contents,
    396 			  Elf_Internal_Rela *rel,
    397 			  bfd_vma relocation)
    398 {
    399   bfd_reloc_status_type r = bfd_reloc_ok;
    400   bfd_vma x;
    401   bfd_signed_vma srel;
    402 
    403   switch (howto->type)
    404     {
    405     case R_FR30_20:
    406       contents   += rel->r_offset;
    407       relocation += rel->r_addend;
    408 
    409       if (relocation > ((1 << 20) - 1))
    410 	return bfd_reloc_overflow;
    411 
    412       x = bfd_get_32 (input_bfd, contents);
    413       x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
    414       bfd_put_32 (input_bfd, x, contents);
    415       break;
    416 
    417     case R_FR30_48:
    418       contents   += rel->r_offset + 2;
    419       relocation += rel->r_addend;
    420       bfd_put_32 (input_bfd, relocation, contents);
    421       break;
    422 
    423     case R_FR30_9_PCREL:
    424       contents   += rel->r_offset + 1;
    425       srel = (bfd_signed_vma) relocation;
    426       srel += rel->r_addend;
    427       srel -= rel->r_offset;
    428       srel -= 2;  /* Branch instructions add 2 to the PC...  */
    429       srel -= (input_section->output_section->vma +
    430 		     input_section->output_offset);
    431 
    432       if (srel & 1)
    433 	return bfd_reloc_outofrange;
    434       if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
    435 	return bfd_reloc_overflow;
    436 
    437       bfd_put_8 (input_bfd, srel >> 1, contents);
    438       break;
    439 
    440     case R_FR30_12_PCREL:
    441       contents   += rel->r_offset;
    442       srel = (bfd_signed_vma) relocation;
    443       srel += rel->r_addend;
    444       srel -= rel->r_offset;
    445       srel -= 2; /* Branch instructions add 2 to the PC...  */
    446       srel -= (input_section->output_section->vma +
    447 		     input_section->output_offset);
    448 
    449       if (srel & 1)
    450 	return bfd_reloc_outofrange;
    451       if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
    452 	  return bfd_reloc_overflow;
    453 
    454       x = bfd_get_16 (input_bfd, contents);
    455       x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
    456       bfd_put_16 (input_bfd, x, contents);
    457       break;
    458 
    459     default:
    460       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    461 				    contents, rel->r_offset,
    462 				    relocation, rel->r_addend);
    463     }
    464 
    465   return r;
    466 }
    467 
    468 /* Relocate an FR30 ELF section.
    470 
    471    The RELOCATE_SECTION function is called by the new ELF backend linker
    472    to handle the relocations for a section.
    473 
    474    The relocs are always passed as Rela structures; if the section
    475    actually uses Rel structures, the r_addend field will always be
    476    zero.
    477 
    478    This function is responsible for adjusting the section contents as
    479    necessary, and (if using Rela relocs and generating a relocatable
    480    output file) adjusting the reloc addend as necessary.
    481 
    482    This function does not have to worry about setting the reloc
    483    address or the reloc symbol index.
    484 
    485    LOCAL_SYMS is a pointer to the swapped in local symbols.
    486 
    487    LOCAL_SECTIONS is an array giving the section in the input file
    488    corresponding to the st_shndx field of each local symbol.
    489 
    490    The global hash table entry for the global symbols can be found
    491    via elf_sym_hashes (input_bfd).
    492 
    493    When generating relocatable output, this function must handle
    494    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    495    going to be the section symbol corresponding to the output
    496    section, which means that the addend must be adjusted
    497    accordingly.  */
    498 
    499 static bfd_boolean
    500 fr30_elf_relocate_section (bfd *output_bfd,
    501 			   struct bfd_link_info *info,
    502 			   bfd *input_bfd,
    503 			   asection *input_section,
    504 			   bfd_byte *contents,
    505 			   Elf_Internal_Rela *relocs,
    506 			   Elf_Internal_Sym *local_syms,
    507 			   asection **local_sections)
    508 {
    509   Elf_Internal_Shdr *symtab_hdr;
    510   struct elf_link_hash_entry **sym_hashes;
    511   Elf_Internal_Rela *rel;
    512   Elf_Internal_Rela *relend;
    513 
    514   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    515   sym_hashes = elf_sym_hashes (input_bfd);
    516   relend     = relocs + input_section->reloc_count;
    517 
    518   for (rel = relocs; rel < relend; rel ++)
    519     {
    520       reloc_howto_type *howto;
    521       unsigned long r_symndx;
    522       Elf_Internal_Sym *sym;
    523       asection *sec;
    524       struct elf_link_hash_entry *h;
    525       bfd_vma relocation;
    526       bfd_reloc_status_type r;
    527       const char *name;
    528       int r_type;
    529 
    530       r_type = ELF32_R_TYPE (rel->r_info);
    531 
    532       if (   r_type == R_FR30_GNU_VTINHERIT
    533 	  || r_type == R_FR30_GNU_VTENTRY)
    534 	continue;
    535 
    536       r_symndx = ELF32_R_SYM (rel->r_info);
    537 
    538       howto  = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
    539       h      = NULL;
    540       sym    = NULL;
    541       sec    = NULL;
    542 
    543       if (r_symndx < symtab_hdr->sh_info)
    544 	{
    545 	  sym = local_syms + r_symndx;
    546 	  sec = local_sections [r_symndx];
    547 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    548 
    549 	  name = bfd_elf_string_from_elf_section
    550 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
    551 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
    552 	}
    553       else
    554 	{
    555 	  bfd_boolean unresolved_reloc, warned, ignored;
    556 
    557 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    558 				   r_symndx, symtab_hdr, sym_hashes,
    559 				   h, sec, relocation,
    560 				   unresolved_reloc, warned, ignored);
    561 
    562 	  name = h->root.root.string;
    563 	}
    564 
    565       if (sec != NULL && discarded_section (sec))
    566 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    567 					 rel, 1, relend, howto, 0, contents);
    568 
    569       if (info->relocatable)
    570 	continue;
    571 
    572       r = fr30_final_link_relocate (howto, input_bfd, input_section,
    573 				     contents, rel, relocation);
    574 
    575       if (r != bfd_reloc_ok)
    576 	{
    577 	  const char * msg = (const char *) NULL;
    578 
    579 	  switch (r)
    580 	    {
    581 	    case bfd_reloc_overflow:
    582 	      r = info->callbacks->reloc_overflow
    583 		(info, (h ? &h->root : NULL), name, howto->name,
    584 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    585 	      break;
    586 
    587 	    case bfd_reloc_undefined:
    588 	      r = info->callbacks->undefined_symbol
    589 		(info, name, input_bfd, input_section, rel->r_offset,
    590 		 TRUE);
    591 	      break;
    592 
    593 	    case bfd_reloc_outofrange:
    594 	      msg = _("internal error: out of range error");
    595 	      break;
    596 
    597 	    case bfd_reloc_notsupported:
    598 	      msg = _("internal error: unsupported relocation error");
    599 	      break;
    600 
    601 	    case bfd_reloc_dangerous:
    602 	      msg = _("internal error: dangerous relocation");
    603 	      break;
    604 
    605 	    default:
    606 	      msg = _("internal error: unknown error");
    607 	      break;
    608 	    }
    609 
    610 	  if (msg)
    611 	    r = info->callbacks->warning
    612 	      (info, msg, name, input_bfd, input_section, rel->r_offset);
    613 
    614 	  if (! r)
    615 	    return FALSE;
    616 	}
    617     }
    618 
    619   return TRUE;
    620 }
    621 
    622 /* Return the section that should be marked against GC for a given
    624    relocation.  */
    625 
    626 static asection *
    627 fr30_elf_gc_mark_hook (asection *sec,
    628 		       struct bfd_link_info *info,
    629 		       Elf_Internal_Rela *rel,
    630 		       struct elf_link_hash_entry *h,
    631 		       Elf_Internal_Sym *sym)
    632 {
    633   if (h != NULL)
    634     switch (ELF32_R_TYPE (rel->r_info))
    635       {
    636       case R_FR30_GNU_VTINHERIT:
    637       case R_FR30_GNU_VTENTRY:
    638 	return NULL;
    639       }
    640 
    641   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
    642 }
    643 
    644 /* Look through the relocs for a section during the first phase.
    645    Since we don't do .gots or .plts, we just need to consider the
    646    virtual table relocs for gc.  */
    647 
    648 static bfd_boolean
    649 fr30_elf_check_relocs (bfd *abfd,
    650 		       struct bfd_link_info *info,
    651 		       asection *sec,
    652 		       const Elf_Internal_Rela *relocs)
    653 {
    654   Elf_Internal_Shdr *symtab_hdr;
    655   struct elf_link_hash_entry **sym_hashes;
    656   const Elf_Internal_Rela *rel;
    657   const Elf_Internal_Rela *rel_end;
    658 
    659   if (info->relocatable)
    660     return TRUE;
    661 
    662   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    663   sym_hashes = elf_sym_hashes (abfd);
    664 
    665   rel_end = relocs + sec->reloc_count;
    666   for (rel = relocs; rel < rel_end; rel++)
    667     {
    668       struct elf_link_hash_entry *h;
    669       unsigned long r_symndx;
    670 
    671       r_symndx = ELF32_R_SYM (rel->r_info);
    672       if (r_symndx < symtab_hdr->sh_info)
    673         h = NULL;
    674       else
    675 	{
    676 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    677 	  while (h->root.type == bfd_link_hash_indirect
    678 		 || h->root.type == bfd_link_hash_warning)
    679 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    680 
    681 	  /* PR15323, ref flags aren't set for references in the same
    682 	     object.  */
    683 	  h->root.non_ir_ref = 1;
    684 	}
    685 
    686       switch (ELF32_R_TYPE (rel->r_info))
    687         {
    688         /* This relocation describes the C++ object vtable hierarchy.
    689            Reconstruct it for later use during GC.  */
    690         case R_FR30_GNU_VTINHERIT:
    691           if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
    692             return FALSE;
    693           break;
    694 
    695         /* This relocation describes which C++ vtable entries are actually
    696            used.  Record for later use during GC.  */
    697         case R_FR30_GNU_VTENTRY:
    698           BFD_ASSERT (h != NULL);
    699           if (h != NULL
    700               && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
    701             return FALSE;
    702           break;
    703         }
    704     }
    705 
    706   return TRUE;
    707 }
    708 
    709 #define ELF_ARCH		bfd_arch_fr30
    711 #define ELF_MACHINE_CODE	EM_FR30
    712 #define ELF_MACHINE_ALT1	EM_CYGNUS_FR30
    713 #define ELF_MAXPAGESIZE		0x1000
    714 
    715 #define TARGET_BIG_SYM          bfd_elf32_fr30_vec
    716 #define TARGET_BIG_NAME		"elf32-fr30"
    717 
    718 #define elf_info_to_howto_rel			NULL
    719 #define elf_info_to_howto			fr30_info_to_howto_rela
    720 #define elf_backend_relocate_section		fr30_elf_relocate_section
    721 #define elf_backend_gc_mark_hook		fr30_elf_gc_mark_hook
    722 #define elf_backend_check_relocs                fr30_elf_check_relocs
    723 
    724 #define elf_backend_can_gc_sections		1
    725 #define elf_backend_rela_normal			1
    726 
    727 #define bfd_elf32_bfd_reloc_type_lookup		fr30_reloc_type_lookup
    728 #define bfd_elf32_bfd_reloc_name_lookup	fr30_reloc_name_lookup
    729 
    730 #include "elf32-target.h"
    731