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