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