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