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