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