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.  */
29static bfd_reloc_status_type fr30_elf_i20_reloc
30  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
31static bfd_reloc_status_type fr30_elf_i32_reloc
32  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
33static reloc_howto_type * fr30_reloc_type_lookup
34  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
35static void fr30_info_to_howto_rela
36  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
37static 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 **));
40static bfd_reloc_status_type fr30_final_link_relocate
41  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
42	   Elf_Internal_Rela *, bfd_vma));
43static bfd_boolean fr30_elf_check_relocs
44  PARAMS ((bfd *, struct bfd_link_info *, asection *,
45	   const Elf_Internal_Rela *));
46
47static 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	 TRUE,			/* 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	 TRUE,			/* 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	 TRUE,			/* 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	 TRUE,			/* 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	 TRUE,			/* 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	 TRUE,			/* 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	 TRUE,			/* 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	 TRUE,			/* 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
244/* Utility to actually perform an R_FR30_20 reloc.  */
245
246static bfd_reloc_status_type
247fr30_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
290/* Utility to actually perform a R_FR30_48 reloc.  */
291
292static bfd_reloc_status_type
293fr30_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
330/* Map BFD reloc types to FR30 ELF reloc types.  */
331
332struct fr30_reloc_map
333{
334  bfd_reloc_code_real_type bfd_reloc_val;
335  unsigned int fr30_reloc_val;
336};
337
338static 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
355static reloc_howto_type *
356fr30_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
370static reloc_howto_type *
371fr30_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
387static void
388fr30_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
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
403static bfd_reloc_status_type
404fr30_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
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
512static bfd_boolean
513fr30_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
644/* Return the section that should be marked against GC for a given
645   relocation.  */
646
647static asection *
648fr30_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
669static bfd_boolean
670fr30_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, **sym_hashes_end;
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  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
687  if (!elf_bad_symtab (abfd))
688    sym_hashes_end -= symtab_hdr->sh_info;
689
690  rel_end = relocs + sec->reloc_count;
691  for (rel = relocs; rel < rel_end; rel++)
692    {
693      struct elf_link_hash_entry *h;
694      unsigned long r_symndx;
695
696      r_symndx = ELF32_R_SYM (rel->r_info);
697      if (r_symndx < symtab_hdr->sh_info)
698        h = NULL;
699      else
700	{
701	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
702	  while (h->root.type == bfd_link_hash_indirect
703		 || h->root.type == bfd_link_hash_warning)
704	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
705	}
706
707      switch (ELF32_R_TYPE (rel->r_info))
708        {
709        /* This relocation describes the C++ object vtable hierarchy.
710           Reconstruct it for later use during GC.  */
711        case R_FR30_GNU_VTINHERIT:
712          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
713            return FALSE;
714          break;
715
716        /* This relocation describes which C++ vtable entries are actually
717           used.  Record for later use during GC.  */
718        case R_FR30_GNU_VTENTRY:
719          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
720            return FALSE;
721          break;
722        }
723    }
724
725  return TRUE;
726}
727
728#define ELF_ARCH		bfd_arch_fr30
729#define ELF_MACHINE_CODE	EM_FR30
730#define ELF_MACHINE_ALT1	EM_CYGNUS_FR30
731#define ELF_MAXPAGESIZE		0x1000
732
733#define TARGET_BIG_SYM          bfd_elf32_fr30_vec
734#define TARGET_BIG_NAME		"elf32-fr30"
735
736#define elf_info_to_howto_rel			NULL
737#define elf_info_to_howto			fr30_info_to_howto_rela
738#define elf_backend_relocate_section		fr30_elf_relocate_section
739#define elf_backend_gc_mark_hook		fr30_elf_gc_mark_hook
740#define elf_backend_check_relocs                fr30_elf_check_relocs
741
742#define elf_backend_can_gc_sections		1
743#define elf_backend_rela_normal			1
744
745#define bfd_elf32_bfd_reloc_type_lookup		fr30_reloc_type_lookup
746#define bfd_elf32_bfd_reloc_name_lookup	fr30_reloc_name_lookup
747
748#include "elf32-target.h"
749