OSDN Git Service

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