2001-01-23 Kazu Hirata <kazu@hxi.com>
[external/binutils.git] / bfd / elf32-mcore.c
1 /* Motorola MCore specific support for 32-bit ELF
2    Copyright 1994, 1995, 1999 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 /* This file is based on a preliminary RCE ELF ABI.  The
21    information may not match the final RCE ELF ABI.   */
22
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include "bfdlink.h"
26 #include "libbfd.h"
27 #include "elf-bfd.h"
28 #include "elf/mcore.h"
29 #include <assert.h>
30
31 #define USE_RELA        /* Only USE_REL is actually significant, but this is
32                            here are a reminder...  */
33
34 static void mcore_elf_howto_init
35   PARAMS ((void));
36 static reloc_howto_type * mcore_elf_reloc_type_lookup
37   PARAMS ((bfd *, bfd_reloc_code_real_type));
38 static void mcore_elf_info_to_howto
39   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
40 static boolean mcore_elf_set_private_flags
41   PARAMS ((bfd *, flagword));
42 static boolean mcore_elf_copy_private_bfd_data
43   PARAMS ((bfd *, bfd *));
44 static boolean mcore_elf_merge_private_bfd_data
45   PARAMS ((bfd *, bfd *));
46 static bfd_reloc_status_type mcore_elf_unsupported_reloc
47   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
48 static boolean mcore_elf_relocate_section
49   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
50            Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
51
52 static reloc_howto_type * mcore_elf_howto_table [(int) R_MCORE_max];
53
54 static reloc_howto_type mcore_elf_howto_raw[] =
55 {
56   /* This reloc does nothing.  */
57   HOWTO (R_MCORE_NONE,          /* type */
58          0,                     /* rightshift */
59          2,                     /* size (0 = byte, 1 = short, 2 = long) */
60          32,                    /* bitsize */
61          false,                 /* pc_relative */
62          0,                     /* bitpos */
63          complain_overflow_bitfield,  /* complain_on_overflow */
64          NULL,                  /* special_function */
65          "R_MCORE_NONE",        /* name */
66          false,                 /* partial_inplace */
67          0,                     /* src_mask */
68          0,                     /* dst_mask */
69          false),                /* pcrel_offset */
70
71   /* A standard 32 bit relocation.  */
72   HOWTO (R_MCORE_ADDR32,        /* type */
73          0,                     /* rightshift */
74          2,                     /* size (0 = byte, 1 = short, 2 = long) */
75          32,                    /* bitsize */
76          false,                 /* pc_relative */
77          0,                     /* bitpos */
78          complain_overflow_bitfield, /* complain_on_overflow */
79          bfd_elf_generic_reloc, /* special_function */
80          "ADDR32",              /* name *//* For compatability with coff/pe port.  */
81          false,                 /* partial_inplace */
82          0x0,                   /* src_mask */
83          0xffffffff,            /* dst_mask */
84          false),                /* pcrel_offset */
85
86   /* 8 bits + 2 zero bits; jmpi/jsri/lrw instructions.
87      Should not appear in object files.  */
88   HOWTO (R_MCORE_PCRELIMM8BY4,  /* type */
89          2,                     /* rightshift */
90          1,                     /* size (0 = byte, 1 = short, 2 = long) */
91          8,                     /* bitsize */
92          true,                  /* pc_relative */
93          0,                     /* bitpos */
94          complain_overflow_bitfield, /* complain_on_overflow */
95          mcore_elf_unsupported_reloc,   /* special_function */
96          "R_MCORE_PCRELIMM8BY4",/* name */
97          false,                 /* partial_inplace */
98          0,                     /* src_mask */
99          0,                     /* dst_mask */
100          true),                 /* pcrel_offset */
101
102   /* bsr/bt/bf/br instructions; 11 bits + 1 zero bit
103      Span 2k instructions == 4k bytes.
104      Only useful pieces at the relocated address are the opcode (5 bits) */
105   HOWTO (R_MCORE_PCRELIMM11BY2,/* type */
106          1,                     /* rightshift */
107          1,                     /* size (0 = byte, 1 = short, 2 = long) */
108          11,                    /* bitsize */
109          true,                  /* pc_relative */
110          0,                     /* bitpos */
111          complain_overflow_signed, /* complain_on_overflow */
112          bfd_elf_generic_reloc, /* special_function */
113          "R_MCORE_PCRELIMM11BY2",/* name */
114          false,                 /* partial_inplace */
115          0x0,                   /* src_mask */
116          0x7ff,                 /* dst_mask */
117          true),                 /* pcrel_offset */
118
119   /* 4 bits + 1 zero bit; 'loopt' instruction only; unsupported.  */
120   HOWTO (R_MCORE_PCRELIMM4BY2,  /* type */
121          1,                     /* rightshift */
122          1,                     /* size (0 = byte, 1 = short, 2 = long) */
123          4,                     /* bitsize */
124          true,                  /* pc_relative */
125          0,                     /* bitpos */
126          complain_overflow_bitfield, /* complain_on_overflow */
127          mcore_elf_unsupported_reloc,/* special_function */
128          "R_MCORE_PCRELIMM4BY2",/* name */
129          false,                 /* partial_inplace */
130          0,                     /* src_mask */
131          0,                     /* dst_mask */
132          true),                 /* pcrel_offset */
133
134   /* 32-bit pc-relative. Eventually this will help support PIC code.  */
135   HOWTO (R_MCORE_PCREL32,       /* type */
136          0,                     /* rightshift */
137          2,                     /* size (0 = byte, 1 = short, 2 = long) */
138          32,                    /* bitsize */
139          true,                  /* pc_relative */
140          0,                     /* bitpos */
141          complain_overflow_bitfield, /* complain_on_overflow */
142          bfd_elf_generic_reloc, /* special_function */
143          "R_MCORE_PCREL32",     /* name */
144          false,                 /* partial_inplace */
145          0x0,                   /* src_mask */
146          0xffffffff,            /* dst_mask */
147          true),                 /* pcrel_offset */
148
149   /* Like PCRELIMM11BY2, this relocation indicates that there is a
150      'jsri' at the specified address. There is a separate relocation
151      entry for the literal pool entry that it references, but we
152      might be able to change the jsri to a bsr if the target turns out
153      to be close enough [even though we won't reclaim the literal pool
154      entry, we'll get some runtime efficiency back]. Note that this
155      is a relocation that we are allowed to safely ignore.  */
156   HOWTO (R_MCORE_PCRELJSR_IMM11BY2,/* type */
157          1,                     /* rightshift */
158          1,                     /* size (0 = byte, 1 = short, 2 = long) */
159          11,                    /* bitsize */
160          true,                  /* pc_relative */
161          0,                     /* bitpos */
162          complain_overflow_signed, /* complain_on_overflow */
163          bfd_elf_generic_reloc, /* special_function */
164          "R_MCORE_PCRELJSR_IMM11BY2", /* name */
165          false,                 /* partial_inplace */
166          0x0,                   /* src_mask */
167          0x7ff,                 /* dst_mask */
168          true),                 /* pcrel_offset */
169
170   /* GNU extension to record C++ vtable hierarchy */
171   HOWTO (R_MCORE_GNU_VTINHERIT, /* type */
172          0,                     /* rightshift */
173          2,                     /* size (0 = byte, 1 = short, 2 = long) */
174          0,                     /* bitsize */
175          false,                 /* pc_relative */
176          0,                     /* bitpos */
177          complain_overflow_dont, /* complain_on_overflow */
178          NULL,                  /* special_function */
179          "R_MCORE_GNU_VTINHERIT", /* name */
180          false,                 /* partial_inplace */
181          0,                     /* src_mask */
182          0,                     /* dst_mask */
183          false),                /* pcrel_offset */
184
185   /* GNU extension to record C++ vtable member usage */
186   HOWTO (R_MCORE_GNU_VTENTRY,   /* type */
187          0,                     /* rightshift */
188          2,                     /* size (0 = byte, 1 = short, 2 = long) */
189          0,                     /* bitsize */
190          false,                 /* pc_relative */
191          0,                     /* bitpos */
192          complain_overflow_dont,/* complain_on_overflow */
193          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
194          "R_MCORE_GNU_VTENTRY", /* name */
195          false,                 /* partial_inplace */
196          0,                     /* src_mask */
197          0,                     /* dst_mask */
198          false),                /* pcrel_offset */
199
200   HOWTO (R_MCORE_RELATIVE,      /* type */
201          0,                     /* rightshift */
202          2,                     /* size (0 = byte, 1 = short, 2 = long) */
203          32,                    /* bitsize */
204          false,                 /* pc_relative */
205          0,                     /* bitpos */
206          complain_overflow_signed, /* complain_on_overflow */
207          NULL,                  /* special_function */
208          "R_MCORE_RELATIVE",    /* name */
209          true,                  /* partial_inplace */
210          0xffffffff,            /* src_mask */
211          0xffffffff,            /* dst_mask */
212          false)                 /* pcrel_offset */
213 };
214
215 #ifndef NUM_ELEM
216 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
217 #endif
218 \f
219 /* Initialize the mcore_elf_howto_table, so that linear accesses can be done.  */
220 static void
221 mcore_elf_howto_init ()
222 {
223   unsigned int i;
224
225   for (i = NUM_ELEM (mcore_elf_howto_raw); i--;)
226     {
227       unsigned int type;
228
229       type = mcore_elf_howto_raw[i].type;
230
231       BFD_ASSERT (type < NUM_ELEM (mcore_elf_howto_table));
232
233       mcore_elf_howto_table [type] = & mcore_elf_howto_raw [i];
234     }
235 }
236 \f
237 static reloc_howto_type *
238 mcore_elf_reloc_type_lookup (abfd, code)
239      bfd * abfd ATTRIBUTE_UNUSED;
240      bfd_reloc_code_real_type code;
241 {
242   enum elf_mcore_reloc_type mcore_reloc = R_MCORE_NONE;
243
244   switch (code)
245     {
246     case BFD_RELOC_NONE:                     mcore_reloc = R_MCORE_NONE; break;
247     case BFD_RELOC_32:                       mcore_reloc = R_MCORE_ADDR32; break;
248     case BFD_RELOC_MCORE_PCREL_IMM8BY4:      mcore_reloc = R_MCORE_PCRELIMM8BY4; break;
249     case BFD_RELOC_MCORE_PCREL_IMM11BY2:     mcore_reloc = R_MCORE_PCRELIMM11BY2; break;
250     case BFD_RELOC_MCORE_PCREL_IMM4BY2:      mcore_reloc = R_MCORE_PCRELIMM4BY2; break;
251     case BFD_RELOC_32_PCREL:                 mcore_reloc = R_MCORE_PCREL32; break;
252     case BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2: mcore_reloc = R_MCORE_PCRELJSR_IMM11BY2; break;
253     case BFD_RELOC_VTABLE_INHERIT:           mcore_reloc = R_MCORE_GNU_VTINHERIT; break;
254     case BFD_RELOC_VTABLE_ENTRY:             mcore_reloc = R_MCORE_GNU_VTENTRY; break;
255     case BFD_RELOC_RVA:                      mcore_reloc = R_MCORE_RELATIVE; break;
256     default:
257       return (reloc_howto_type *)NULL;
258     }
259
260   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])   /* Initialize howto table if needed */
261     mcore_elf_howto_init ();
262
263   return mcore_elf_howto_table [(int) mcore_reloc];
264 };
265
266 /* Set the howto pointer for a RCE ELF reloc.  */
267 static void
268 mcore_elf_info_to_howto (abfd, cache_ptr, dst)
269      bfd * abfd ATTRIBUTE_UNUSED;
270      arelent * cache_ptr;
271      Elf32_Internal_Rela * dst;
272 {
273   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])   /* Initialize howto table if needed */
274     mcore_elf_howto_init ();
275
276   BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MCORE_max);
277
278   cache_ptr->howto = mcore_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
279 }
280
281 /* Function to set whether a module needs the -mrelocatable bit set.  */
282 static boolean
283 mcore_elf_set_private_flags (abfd, flags)
284      bfd * abfd;
285      flagword flags;
286 {
287   BFD_ASSERT (! elf_flags_init (abfd)
288               || elf_elfheader (abfd)->e_flags == flags);
289
290   elf_elfheader (abfd)->e_flags = flags;
291   elf_flags_init (abfd) = true;
292   return true;
293 }
294
295 /* Copy backend specific data from one object module to another.  */
296 static boolean
297 mcore_elf_copy_private_bfd_data (ibfd, obfd)
298      bfd * ibfd;
299      bfd * obfd;
300 {
301   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
302       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
303     return true;
304
305   BFD_ASSERT (! elf_flags_init (obfd)
306               || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
307
308   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
309   elf_flags_init (obfd) = true;
310   return true;
311 }
312
313 /* Merge backend specific data from an object file to the output
314    object file when linking.  */
315 static boolean
316 mcore_elf_merge_private_bfd_data (ibfd, obfd)
317      bfd * ibfd;
318      bfd * obfd;
319 {
320   flagword old_flags;
321   flagword new_flags;
322
323   /* Check if we have the same endianess */
324   if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
325     return false;
326
327   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
328       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
329     return true;
330
331   new_flags = elf_elfheader (ibfd)->e_flags;
332   old_flags = elf_elfheader (obfd)->e_flags;
333
334   if (! elf_flags_init (obfd))  /* First call, no flags set */
335     {
336       elf_flags_init (obfd) = true;
337       elf_elfheader (obfd)->e_flags = new_flags;
338     }
339   else if (new_flags == old_flags)      /* Compatible flags are ok */
340     ;
341   else
342     {
343       /* FIXME */
344     }
345
346   return true;
347 }
348 \f
349 /* Don't pretend we can deal with unsupported relocs.  */
350
351 static bfd_reloc_status_type
352 mcore_elf_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
353                            output_bfd, error_message)
354      bfd * abfd;
355      arelent * reloc_entry;
356      asymbol * symbol ATTRIBUTE_UNUSED;
357      PTR data ATTRIBUTE_UNUSED;
358      asection * input_section ATTRIBUTE_UNUSED;
359      bfd * output_bfd ATTRIBUTE_UNUSED;
360      char ** error_message ATTRIBUTE_UNUSED;
361 {
362   BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
363
364   _bfd_error_handler (_("%s: Relocation %s (%d) is not currently supported.\n"),
365                       bfd_get_filename (abfd),
366                       reloc_entry->howto->name,
367                       reloc_entry->howto->type);
368
369   return bfd_reloc_notsupported;
370 }
371 \f
372 /* The RELOCATE_SECTION function is called by the ELF backend linker
373    to handle the relocations for a section.
374
375    The relocs are always passed as Rela structures; if the section
376    actually uses Rel structures, the r_addend field will always be
377    zero.
378
379    This function is responsible for adjust the section contents as
380    necessary, and (if using Rela relocs and generating a
381    relocateable output file) adjusting the reloc addend as
382    necessary.
383
384    This function does not have to worry about setting the reloc
385    address or the reloc symbol index.
386
387    LOCAL_SYMS is a pointer to the swapped in local symbols.
388
389    LOCAL_SECTIONS is an array giving the section in the input file
390    corresponding to the st_shndx field of each local symbol.
391
392    The global hash table entry for the global symbols can be found
393    via elf_sym_hashes (input_bfd).
394
395    When generating relocateable output, this function must handle
396    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
397    going to be the section symbol corresponding to the output
398    section, which means that the addend must be adjusted
399    accordingly.  */
400
401 static boolean
402 mcore_elf_relocate_section (output_bfd, info, input_bfd, input_section,
403                           contents, relocs, local_syms, local_sections)
404      bfd * output_bfd ATTRIBUTE_UNUSED;
405      struct bfd_link_info * info;
406      bfd * input_bfd;
407      asection * input_section;
408      bfd_byte * contents;
409      Elf_Internal_Rela * relocs;
410      Elf_Internal_Sym * local_syms;
411      asection ** local_sections;
412 {
413   Elf_Internal_Shdr *           symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
414   struct elf_link_hash_entry ** sym_hashes = elf_sym_hashes (input_bfd);
415   Elf_Internal_Rela *           rel = relocs;
416   Elf_Internal_Rela *           relend = relocs + input_section->reloc_count;
417   boolean ret = true;
418
419 #ifdef DEBUG
420   fprintf (stderr,
421            "mcore_elf_relocate_section called for %s section %s, %ld relocations%s\n",
422            bfd_get_filename (input_bfd),
423            bfd_section_name(input_bfd, input_section),
424            (long) input_section->reloc_count,
425            (info->relocateable) ? " (relocatable)" : "");
426 #endif
427
428   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])   /* Initialize howto table if needed */
429     mcore_elf_howto_init ();
430
431   for (; rel < relend; rel++)
432     {
433       enum elf_mcore_reloc_type    r_type = (enum elf_mcore_reloc_type) ELF32_R_TYPE (rel->r_info);
434       bfd_vma                      offset = rel->r_offset;
435       bfd_vma                      addend = rel->r_addend;
436       bfd_reloc_status_type        r = bfd_reloc_other;
437       asection *                   sec = (asection *) 0;
438       reloc_howto_type *           howto;
439       bfd_vma                      relocation;
440       Elf_Internal_Sym *           sym = (Elf_Internal_Sym *) 0;
441       unsigned long                r_symndx;
442       struct elf_link_hash_entry * h = (struct elf_link_hash_entry *) 0;
443       unsigned short               oldinst = 0;
444
445       /* Unknown relocation handling */
446       if ((unsigned) r_type >= (unsigned) R_MCORE_max
447           || ! mcore_elf_howto_table [(int)r_type])
448         {
449           _bfd_error_handler (_("%s: Unknown relocation type %d\n"),
450                               bfd_get_filename (input_bfd),
451                               (int) r_type);
452
453           bfd_set_error (bfd_error_bad_value);
454           ret = false;
455           continue;
456         }
457
458       howto = mcore_elf_howto_table [(int) r_type];
459       r_symndx = ELF32_R_SYM (rel->r_info);
460
461       if (info->relocateable)
462         {
463           /* This is a relocateable link.  We don't have to change
464              anything, unless the reloc is against a section symbol,
465              in which case we have to adjust according to where the
466              section symbol winds up in the output section.  */
467           if (r_symndx < symtab_hdr->sh_info)
468             {
469               sym = local_syms + r_symndx;
470
471               if ((unsigned)ELF_ST_TYPE (sym->st_info) == STT_SECTION)
472                 {
473                   sec = local_sections[r_symndx];
474                   addend = rel->r_addend += sec->output_offset + sym->st_value;
475                 }
476             }
477
478 #ifdef DEBUG
479           fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
480                    howto->name, (int) r_type, r_symndx, (long) offset, (long) addend);
481 #endif
482           continue;
483         }
484
485       /* This is a final link.  */
486
487       /* Complain about known relocation that are not yet supported.  */
488       if (howto->special_function == mcore_elf_unsupported_reloc)
489         {
490           _bfd_error_handler (_("%s: Relocation %s (%d) is not currently supported.\n"),
491                               bfd_get_filename (input_bfd),
492                               howto->name,
493                               (int)r_type);
494
495           bfd_set_error (bfd_error_bad_value);
496           ret = false;
497           continue;
498         }
499
500       if (r_symndx < symtab_hdr->sh_info)
501         {
502           sym = local_syms + r_symndx;
503           sec = local_sections [r_symndx];
504           relocation = (sec->output_section->vma
505                         + sec->output_offset
506                         + sym->st_value);
507         }
508       else
509         {
510           h = sym_hashes [r_symndx - symtab_hdr->sh_info];
511           if (   h->root.type == bfd_link_hash_defined
512               || h->root.type == bfd_link_hash_defweak)
513             {
514               sec = h->root.u.def.section;
515               relocation = (h->root.u.def.value
516                             + sec->output_section->vma
517                             + sec->output_offset);
518             }
519           else if (h->root.type == bfd_link_hash_undefweak)
520             relocation = 0;
521           else if (info->shared
522                    && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
523             relocation = 0;
524           else
525             {
526               if (! ((*info->callbacks->undefined_symbol)
527                         (info, h->root.root.string, input_bfd,
528                          input_section, rel->r_offset, true)))
529                 return false;
530
531               ret = false;
532               continue;
533             }
534         }
535
536       switch (r_type)
537         {
538         default:
539           break;
540
541         case R_MCORE_PCRELJSR_IMM11BY2:
542           oldinst = bfd_get_16 (input_bfd, contents + offset);
543 #define MCORE_INST_BSR  0xF800
544           bfd_put_16 (input_bfd, MCORE_INST_BSR, contents + offset);
545           break;
546         }
547
548 #ifdef DEBUG
549       fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
550                howto->name, r_type, r_symndx, (long) offset, (long) addend);
551 #endif
552
553       r = _bfd_final_link_relocate
554         (howto, input_bfd, input_section, contents, offset, relocation, addend);
555
556       if (r != bfd_reloc_ok && r_type == R_MCORE_PCRELJSR_IMM11BY2)
557         {
558           /* Wasn't ok, back it out and give up.  */
559           bfd_put_16 (input_bfd, oldinst, contents + offset);
560           r = bfd_reloc_ok;
561         }
562
563       if (r != bfd_reloc_ok)
564         {
565           ret = false;
566
567           switch (r)
568             {
569             default:
570               break;
571
572             case bfd_reloc_overflow:
573               {
574                 const char * name;
575
576                 if (h != NULL)
577                   name = h->root.root.string;
578                 else
579                   {
580                     name = bfd_elf_string_from_elf_section
581                       (input_bfd, symtab_hdr->sh_link, sym->st_name);
582
583                     if (name == NULL)
584                       break;
585
586                     if (* name == '\0')
587                       name = bfd_section_name (input_bfd, sec);
588                   }
589
590                 (*info->callbacks->reloc_overflow)
591                   (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section,
592                    offset);
593               }
594               break;
595             }
596         }
597     }
598
599 #ifdef DEBUG
600   fprintf (stderr, "\n");
601 #endif
602
603   return ret;
604 }
605 \f
606 /* Return the section that should be marked against GC for a given
607    relocation.  */
608
609 static asection *
610 mcore_elf_gc_mark_hook (abfd, info, rel, h, sym)
611      bfd *                        abfd;
612      struct bfd_link_info *       info ATTRIBUTE_UNUSED;
613      Elf_Internal_Rela *          rel;
614      struct elf_link_hash_entry * h;
615      Elf_Internal_Sym *           sym;
616 {
617   if (h != NULL)
618     {
619       switch (ELF32_R_TYPE (rel->r_info))
620         {
621         case R_MCORE_GNU_VTINHERIT:
622         case R_MCORE_GNU_VTENTRY:
623           break;
624
625         default:
626           switch (h->root.type)
627             {
628             case bfd_link_hash_defined:
629             case bfd_link_hash_defweak:
630               return h->root.u.def.section;
631
632             case bfd_link_hash_common:
633               return h->root.u.c.p->section;
634
635             default:
636               break;
637             }
638         }
639     }
640   else
641     {
642       if (!(elf_bad_symtab (abfd)
643             && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
644           && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
645                 && sym->st_shndx != SHN_COMMON))
646         {
647           return bfd_section_from_elf_index (abfd, sym->st_shndx);
648         }
649     }
650
651   return NULL;
652 }
653
654 /* Update the got entry reference counts for the section being removed.  */
655
656 static boolean
657 mcore_elf_gc_sweep_hook (abfd, info, sec, relocs)
658      bfd *                     abfd ATTRIBUTE_UNUSED;
659      struct bfd_link_info *    info ATTRIBUTE_UNUSED;
660      asection *                sec ATTRIBUTE_UNUSED;
661      const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
662 {
663   return true;
664 }
665
666 /* Look through the relocs for a section during the first phase.
667    Since we don't do .gots or .plts, we just need to consider the
668    virtual table relocs for gc.  */
669
670 static boolean
671 mcore_elf_check_relocs (abfd, info, sec, relocs)
672      bfd * abfd;
673      struct bfd_link_info * info;
674      asection * sec;
675      const Elf_Internal_Rela * relocs;
676 {
677   Elf_Internal_Shdr *           symtab_hdr;
678   struct elf_link_hash_entry ** sym_hashes;
679   struct elf_link_hash_entry ** sym_hashes_end;
680   const Elf_Internal_Rela *     rel;
681   const Elf_Internal_Rela *     rel_end;
682
683   if (info->relocateable)
684     return true;
685
686   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
687   sym_hashes = elf_sym_hashes (abfd);
688   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
689   if (!elf_bad_symtab (abfd))
690     sym_hashes_end -= symtab_hdr->sh_info;
691
692   rel_end = relocs + sec->reloc_count;
693
694   for (rel = relocs; rel < rel_end; rel++)
695     {
696       struct elf_link_hash_entry * h;
697       unsigned long r_symndx;
698
699       r_symndx = ELF32_R_SYM (rel->r_info);
700
701       if (r_symndx < symtab_hdr->sh_info)
702         h = NULL;
703       else
704         h = sym_hashes [r_symndx - symtab_hdr->sh_info];
705
706       switch (ELF32_R_TYPE (rel->r_info))
707         {
708         /* This relocation describes the C++ object vtable hierarchy.
709            Reconstruct it for later use during GC.  */
710         case R_MCORE_GNU_VTINHERIT:
711           if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
712             return false;
713           break;
714
715         /* This relocation describes which C++ vtable entries are actually
716            used.  Record for later use during GC.  */
717         case R_MCORE_GNU_VTENTRY:
718           if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
719             return false;
720           break;
721         }
722     }
723
724   return true;
725 }
726
727 #define TARGET_BIG_SYM          bfd_elf32_mcore_big_vec
728 #define TARGET_BIG_NAME         "elf32-mcore-big"
729 #define TARGET_LITTLE_SYM       bfd_elf32_mcore_little_vec
730 #define TARGET_LITTLE_NAME      "elf32-mcore-little"
731
732 #define ELF_ARCH                bfd_arch_mcore
733 #define ELF_MACHINE_CODE        EM_MCORE
734 #define ELF_MAXPAGESIZE         0x1000          /* 4k, if we ever have 'em */
735 #define elf_info_to_howto       mcore_elf_info_to_howto
736 #define elf_info_to_howto_rel   NULL
737
738 #define bfd_elf32_bfd_copy_private_bfd_data     mcore_elf_copy_private_bfd_data
739 #define bfd_elf32_bfd_merge_private_bfd_data    mcore_elf_merge_private_bfd_data
740 #define bfd_elf32_bfd_set_private_flags         mcore_elf_set_private_flags
741 #define bfd_elf32_bfd_reloc_type_lookup         mcore_elf_reloc_type_lookup
742 #define elf_backend_relocate_section            mcore_elf_relocate_section
743 #define elf_backend_gc_mark_hook                mcore_elf_gc_mark_hook
744 #define elf_backend_gc_sweep_hook               mcore_elf_gc_sweep_hook
745 #define elf_backend_check_relocs                mcore_elf_check_relocs
746
747 #define elf_backend_can_gc_sections             1
748
749 #include "elf32-target.h"