2000-12-06 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
237 \f
238 static reloc_howto_type *
239 mcore_elf_reloc_type_lookup (abfd, code)
240      bfd * abfd ATTRIBUTE_UNUSED;
241      bfd_reloc_code_real_type code;
242 {
243   enum elf_mcore_reloc_type mcore_reloc = R_MCORE_NONE;
244
245   switch (code)
246     {
247     case BFD_RELOC_NONE:                     mcore_reloc = R_MCORE_NONE; break;
248     case BFD_RELOC_32:                       mcore_reloc = R_MCORE_ADDR32; break;
249     case BFD_RELOC_MCORE_PCREL_IMM8BY4:      mcore_reloc = R_MCORE_PCRELIMM8BY4; break;
250     case BFD_RELOC_MCORE_PCREL_IMM11BY2:     mcore_reloc = R_MCORE_PCRELIMM11BY2; break;
251     case BFD_RELOC_MCORE_PCREL_IMM4BY2:      mcore_reloc = R_MCORE_PCRELIMM4BY2; break;
252     case BFD_RELOC_32_PCREL:                 mcore_reloc = R_MCORE_PCREL32; break;
253     case BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2: mcore_reloc = R_MCORE_PCRELJSR_IMM11BY2; break;
254     case BFD_RELOC_VTABLE_INHERIT:           mcore_reloc = R_MCORE_GNU_VTINHERIT; break;
255     case BFD_RELOC_VTABLE_ENTRY:             mcore_reloc = R_MCORE_GNU_VTENTRY; break;
256     case BFD_RELOC_RVA:                      mcore_reloc = R_MCORE_RELATIVE; break;
257     default:
258       return (reloc_howto_type *)NULL;
259     }
260
261   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])   /* Initialize howto table if needed */
262     mcore_elf_howto_init ();
263
264   return mcore_elf_howto_table [(int) mcore_reloc];
265 };
266
267 /* Set the howto pointer for a RCE ELF reloc.  */
268 static void
269 mcore_elf_info_to_howto (abfd, cache_ptr, dst)
270      bfd * abfd ATTRIBUTE_UNUSED;
271      arelent * cache_ptr;
272      Elf32_Internal_Rela * dst;
273 {
274   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])   /* Initialize howto table if needed */
275     mcore_elf_howto_init ();
276
277   BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MCORE_max);
278
279   cache_ptr->howto = mcore_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
280 }
281
282 /* Function to set whether a module needs the -mrelocatable bit set.  */
283 static boolean
284 mcore_elf_set_private_flags (abfd, flags)
285      bfd * abfd;
286      flagword flags;
287 {
288   BFD_ASSERT (! elf_flags_init (abfd)
289               || elf_elfheader (abfd)->e_flags == flags);
290
291   elf_elfheader (abfd)->e_flags = flags;
292   elf_flags_init (abfd) = true;
293   return true;
294 }
295
296 /* Copy backend specific data from one object module to another.  */
297 static boolean
298 mcore_elf_copy_private_bfd_data (ibfd, obfd)
299      bfd * ibfd;
300      bfd * obfd;
301 {
302   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
303       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
304     return true;
305
306   BFD_ASSERT (! elf_flags_init (obfd)
307               || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
308
309   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
310   elf_flags_init (obfd) = true;
311   return true;
312 }
313
314 /* Merge backend specific data from an object file to the output
315    object file when linking.  */
316 static boolean
317 mcore_elf_merge_private_bfd_data (ibfd, obfd)
318      bfd * ibfd;
319      bfd * obfd;
320 {
321   flagword old_flags;
322   flagword new_flags;
323
324   /* Check if we have the same endianess */
325   if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
326     return false;
327
328   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
329       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
330     return true;
331
332   new_flags = elf_elfheader (ibfd)->e_flags;
333   old_flags = elf_elfheader (obfd)->e_flags;
334
335   if (! elf_flags_init (obfd))  /* First call, no flags set */
336     {
337       elf_flags_init (obfd) = true;
338       elf_elfheader (obfd)->e_flags = new_flags;
339     }
340   else if (new_flags == old_flags)      /* Compatible flags are ok */
341     ;
342   else
343     {
344       /* FIXME */
345     }
346
347   return true;
348 }
349
350 \f
351 /* Don't pretend we can deal with unsupported relocs.  */
352
353 /*ARGSUSED*/
354 static bfd_reloc_status_type
355 mcore_elf_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
356                            output_bfd, error_message)
357      bfd * abfd;
358      arelent * reloc_entry;
359      asymbol * symbol ATTRIBUTE_UNUSED;
360      PTR data ATTRIBUTE_UNUSED;
361      asection * input_section ATTRIBUTE_UNUSED;
362      bfd * output_bfd ATTRIBUTE_UNUSED;
363      char ** error_message ATTRIBUTE_UNUSED;
364 {
365   BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
366
367   _bfd_error_handler (_("%s: Relocation %s (%d) is not currently supported.\n"),
368                       bfd_get_filename (abfd),
369                       reloc_entry->howto->name,
370                       reloc_entry->howto->type);
371
372   return bfd_reloc_notsupported;
373 }
374
375 \f
376 /* The RELOCATE_SECTION function is called by the ELF backend linker
377    to handle the relocations for a section.
378
379    The relocs are always passed as Rela structures; if the section
380    actually uses Rel structures, the r_addend field will always be
381    zero.
382
383    This function is responsible for adjust the section contents as
384    necessary, and (if using Rela relocs and generating a
385    relocateable output file) adjusting the reloc addend as
386    necessary.
387
388    This function does not have to worry about setting the reloc
389    address or the reloc symbol index.
390
391    LOCAL_SYMS is a pointer to the swapped in local symbols.
392
393    LOCAL_SECTIONS is an array giving the section in the input file
394    corresponding to the st_shndx field of each local symbol.
395
396    The global hash table entry for the global symbols can be found
397    via elf_sym_hashes (input_bfd).
398
399    When generating relocateable output, this function must handle
400    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
401    going to be the section symbol corresponding to the output
402    section, which means that the addend must be adjusted
403    accordingly.  */
404
405 static boolean
406 mcore_elf_relocate_section (output_bfd, info, input_bfd, input_section,
407                           contents, relocs, local_syms, local_sections)
408      bfd * output_bfd ATTRIBUTE_UNUSED;
409      struct bfd_link_info * info;
410      bfd * input_bfd;
411      asection * input_section;
412      bfd_byte * contents;
413      Elf_Internal_Rela * relocs;
414      Elf_Internal_Sym * local_syms;
415      asection ** local_sections;
416 {
417   Elf_Internal_Shdr *           symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
418   struct elf_link_hash_entry ** sym_hashes = elf_sym_hashes (input_bfd);
419   Elf_Internal_Rela *           rel = relocs;
420   Elf_Internal_Rela *           relend = relocs + input_section->reloc_count;
421   boolean ret = true;
422
423 #ifdef DEBUG
424   fprintf (stderr,
425            "mcore_elf_relocate_section called for %s section %s, %ld relocations%s\n",
426            bfd_get_filename (input_bfd),
427            bfd_section_name(input_bfd, input_section),
428            (long) input_section->reloc_count,
429            (info->relocateable) ? " (relocatable)" : "");
430 #endif
431
432   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])   /* Initialize howto table if needed */
433     mcore_elf_howto_init ();
434
435   for (; rel < relend; rel++)
436     {
437       enum elf_mcore_reloc_type    r_type = (enum elf_mcore_reloc_type) ELF32_R_TYPE (rel->r_info);
438       bfd_vma                      offset = rel->r_offset;
439       bfd_vma                      addend = rel->r_addend;
440       bfd_reloc_status_type        r = bfd_reloc_other;
441       asection *                   sec = (asection *) 0;
442       reloc_howto_type *           howto;
443       bfd_vma                      relocation;
444       Elf_Internal_Sym *           sym = (Elf_Internal_Sym *) 0;
445       unsigned long                r_symndx;
446       struct elf_link_hash_entry * h = (struct elf_link_hash_entry *) 0;
447       unsigned short               oldinst = 0;
448
449       /* Unknown relocation handling */
450       if ((unsigned) r_type >= (unsigned) R_MCORE_max
451           || ! mcore_elf_howto_table [(int)r_type])
452         {
453           _bfd_error_handler (_("%s: Unknown relocation type %d\n"),
454                               bfd_get_filename (input_bfd),
455                               (int) r_type);
456
457           bfd_set_error (bfd_error_bad_value);
458           ret = false;
459           continue;
460         }
461
462       howto = mcore_elf_howto_table [(int) r_type];
463       r_symndx = ELF32_R_SYM (rel->r_info);
464
465       if (info->relocateable)
466         {
467           /* This is a relocateable link.  We don't have to change
468              anything, unless the reloc is against a section symbol,
469              in which case we have to adjust according to where the
470              section symbol winds up in the output section.  */
471           if (r_symndx < symtab_hdr->sh_info)
472             {
473               sym = local_syms + r_symndx;
474
475               if ((unsigned)ELF_ST_TYPE (sym->st_info) == STT_SECTION)
476                 {
477                   sec = local_sections[r_symndx];
478                   addend = rel->r_addend += sec->output_offset + sym->st_value;
479                 }
480             }
481
482 #ifdef DEBUG
483           fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
484                    howto->name, (int) r_type, r_symndx, (long) offset, (long) addend);
485 #endif
486           continue;
487         }
488
489       /* This is a final link.  */
490
491       /* Complain about known relocation that are not yet supported.  */
492       if (howto->special_function == mcore_elf_unsupported_reloc)
493         {
494           _bfd_error_handler (_("%s: Relocation %s (%d) is not currently supported.\n"),
495                               bfd_get_filename (input_bfd),
496                               howto->name,
497                               (int)r_type);
498
499           bfd_set_error (bfd_error_bad_value);
500           ret = false;
501           continue;
502         }
503
504       if (r_symndx < symtab_hdr->sh_info)
505         {
506           sym = local_syms + r_symndx;
507           sec = local_sections [r_symndx];
508           relocation = (sec->output_section->vma
509                         + sec->output_offset
510                         + sym->st_value);
511         }
512       else
513         {
514           h = sym_hashes [r_symndx - symtab_hdr->sh_info];
515           if (   h->root.type == bfd_link_hash_defined
516               || h->root.type == bfd_link_hash_defweak)
517             {
518               sec = h->root.u.def.section;
519               relocation = (h->root.u.def.value
520                             + sec->output_section->vma
521                             + sec->output_offset);
522             }
523           else if (h->root.type == bfd_link_hash_undefweak)
524             relocation = 0;
525           else if (info->shared
526                    && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
527             relocation = 0;
528           else
529             {
530               if (! ((*info->callbacks->undefined_symbol)
531                         (info, h->root.root.string, input_bfd,
532                          input_section, rel->r_offset, true)))
533                 return false;
534
535               ret = false;
536               continue;
537             }
538         }
539
540       switch (r_type)
541         {
542         default:
543           break;
544
545         case R_MCORE_PCRELJSR_IMM11BY2:
546           oldinst = bfd_get_16 (input_bfd, contents + offset);
547 #define MCORE_INST_BSR  0xF800
548           bfd_put_16 (input_bfd, MCORE_INST_BSR, contents + offset);
549           break;
550         }
551
552 #ifdef DEBUG
553       fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
554                howto->name, r_type, r_symndx, (long) offset, (long) addend);
555 #endif
556
557       r = _bfd_final_link_relocate
558         (howto, input_bfd, input_section, contents, offset, relocation, addend);
559
560       if (r != bfd_reloc_ok && r_type == R_MCORE_PCRELJSR_IMM11BY2)
561         {
562           /* Wasn't ok, back it out and give up.  */
563           bfd_put_16 (input_bfd, oldinst, contents + offset);
564           r = bfd_reloc_ok;
565         }
566
567       if (r != bfd_reloc_ok)
568         {
569           ret = false;
570
571           switch (r)
572             {
573             default:
574               break;
575
576             case bfd_reloc_overflow:
577               {
578                 const char * name;
579
580                 if (h != NULL)
581                   name = h->root.root.string;
582                 else
583                   {
584                     name = bfd_elf_string_from_elf_section
585                       (input_bfd, symtab_hdr->sh_link, sym->st_name);
586
587                     if (name == NULL)
588                       break;
589
590                     if (* name == '\0')
591                       name = bfd_section_name (input_bfd, sec);
592                   }
593
594                 (*info->callbacks->reloc_overflow)
595                   (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section,
596                    offset);
597               }
598               break;
599             }
600         }
601     }
602
603 #ifdef DEBUG
604   fprintf (stderr, "\n");
605 #endif
606
607   return ret;
608 }
609 \f
610 /* Return the section that should be marked against GC for a given
611    relocation.  */
612
613 static asection *
614 mcore_elf_gc_mark_hook (abfd, info, rel, h, sym)
615      bfd *                        abfd;
616      struct bfd_link_info *       info ATTRIBUTE_UNUSED;
617      Elf_Internal_Rela *          rel;
618      struct elf_link_hash_entry * h;
619      Elf_Internal_Sym *           sym;
620 {
621   if (h != NULL)
622     {
623       switch (ELF32_R_TYPE (rel->r_info))
624         {
625         case R_MCORE_GNU_VTINHERIT:
626         case R_MCORE_GNU_VTENTRY:
627           break;
628
629         default:
630           switch (h->root.type)
631             {
632             case bfd_link_hash_defined:
633             case bfd_link_hash_defweak:
634               return h->root.u.def.section;
635
636             case bfd_link_hash_common:
637               return h->root.u.c.p->section;
638
639             default:
640               break;
641             }
642         }
643     }
644   else
645     {
646       if (!(elf_bad_symtab (abfd)
647             && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
648           && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
649                 && sym->st_shndx != SHN_COMMON))
650         {
651           return bfd_section_from_elf_index (abfd, sym->st_shndx);
652         }
653     }
654
655   return NULL;
656 }
657
658 /* Update the got entry reference counts for the section being removed.  */
659
660 static boolean
661 mcore_elf_gc_sweep_hook (abfd, info, sec, relocs)
662      bfd *                     abfd ATTRIBUTE_UNUSED;
663      struct bfd_link_info *    info ATTRIBUTE_UNUSED;
664      asection *                sec ATTRIBUTE_UNUSED;
665      const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
666 {
667   return true;
668 }
669
670 /* Look through the relocs for a section during the first phase.
671    Since we don't do .gots or .plts, we just need to consider the
672    virtual table relocs for gc.  */
673
674 static boolean
675 mcore_elf_check_relocs (abfd, info, sec, relocs)
676      bfd * abfd;
677      struct bfd_link_info * info;
678      asection * sec;
679      const Elf_Internal_Rela * relocs;
680 {
681   Elf_Internal_Shdr *           symtab_hdr;
682   struct elf_link_hash_entry ** sym_hashes;
683   struct elf_link_hash_entry ** sym_hashes_end;
684   const Elf_Internal_Rela *     rel;
685   const Elf_Internal_Rela *     rel_end;
686
687   if (info->relocateable)
688     return true;
689
690   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
691   sym_hashes = elf_sym_hashes (abfd);
692   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
693   if (!elf_bad_symtab (abfd))
694     sym_hashes_end -= symtab_hdr->sh_info;
695
696   rel_end = relocs + sec->reloc_count;
697
698   for (rel = relocs; rel < rel_end; rel++)
699     {
700       struct elf_link_hash_entry * h;
701       unsigned long r_symndx;
702
703       r_symndx = ELF32_R_SYM (rel->r_info);
704
705       if (r_symndx < symtab_hdr->sh_info)
706         h = NULL;
707       else
708         h = sym_hashes [r_symndx - symtab_hdr->sh_info];
709
710       switch (ELF32_R_TYPE (rel->r_info))
711         {
712         /* This relocation describes the C++ object vtable hierarchy.
713            Reconstruct it for later use during GC.  */
714         case R_MCORE_GNU_VTINHERIT:
715           if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
716             return false;
717           break;
718
719         /* This relocation describes which C++ vtable entries are actually
720            used.  Record for later use during GC.  */
721         case R_MCORE_GNU_VTENTRY:
722           if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
723             return false;
724           break;
725         }
726     }
727
728   return true;
729 }
730
731 #define TARGET_BIG_SYM          bfd_elf32_mcore_big_vec
732 #define TARGET_BIG_NAME         "elf32-mcore-big"
733 #define TARGET_LITTLE_SYM       bfd_elf32_mcore_little_vec
734 #define TARGET_LITTLE_NAME      "elf32-mcore-little"
735
736 #define ELF_ARCH                bfd_arch_mcore
737 #define ELF_MACHINE_CODE        EM_MCORE
738 #define ELF_MAXPAGESIZE         0x1000          /* 4k, if we ever have 'em */
739 #define elf_info_to_howto       mcore_elf_info_to_howto
740 #define elf_info_to_howto_rel   NULL
741
742 #define bfd_elf32_bfd_copy_private_bfd_data     mcore_elf_copy_private_bfd_data
743 #define bfd_elf32_bfd_merge_private_bfd_data    mcore_elf_merge_private_bfd_data
744 #define bfd_elf32_bfd_set_private_flags         mcore_elf_set_private_flags
745 #define bfd_elf32_bfd_reloc_type_lookup         mcore_elf_reloc_type_lookup
746 #define elf_backend_relocate_section            mcore_elf_relocate_section
747 #define elf_backend_gc_mark_hook                mcore_elf_gc_mark_hook
748 #define elf_backend_gc_sweep_hook               mcore_elf_gc_sweep_hook
749 #define elf_backend_check_relocs                mcore_elf_check_relocs
750
751 #define elf_backend_can_gc_sections             1
752
753 #include "elf32-target.h"