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