2000-05-23 H.J. Lu <hjl@gnu.org>
[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
553 #ifdef DEBUG
554       fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
555                howto->name, r_type, r_symndx, (long) offset, (long) addend);
556 #endif
557
558       r = _bfd_final_link_relocate
559         (howto, input_bfd, input_section, contents, offset, relocation, addend);
560
561       if (r != bfd_reloc_ok && r_type == R_MCORE_PCRELJSR_IMM11BY2)
562         {
563           /* Wasn't ok, back it out and give up.  */
564           bfd_put_16 (input_bfd, oldinst, contents + offset);
565           r = bfd_reloc_ok;
566         }
567       
568       if (r != bfd_reloc_ok)
569         {
570           ret = false;
571           
572           switch (r)
573             {
574             default:
575               break;
576
577             case bfd_reloc_overflow:
578               {
579                 const char * name;
580
581                 if (h != NULL)
582                   name = h->root.root.string;
583                 else
584                   {
585                     name = bfd_elf_string_from_elf_section
586                       (input_bfd, symtab_hdr->sh_link, sym->st_name);
587                     
588                     if (name == NULL)
589                       break;
590
591                     if (* name == '\0')
592                       name = bfd_section_name (input_bfd, sec);
593                   }
594
595                 (*info->callbacks->reloc_overflow)
596                   (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section,
597                    offset);
598               }
599               break;
600             }
601         }
602     }
603
604 #ifdef DEBUG
605   fprintf (stderr, "\n");
606 #endif
607
608   return ret;
609 }
610 \f
611 /* Return the section that should be marked against GC for a given
612    relocation.  */
613
614 static asection *
615 mcore_elf_gc_mark_hook (abfd, info, rel, h, sym)
616      bfd *                        abfd;
617      struct bfd_link_info *       info ATTRIBUTE_UNUSED;
618      Elf_Internal_Rela *          rel;
619      struct elf_link_hash_entry * h;
620      Elf_Internal_Sym *           sym;
621 {
622   if (h != NULL)
623     {
624       switch (ELF32_R_TYPE (rel->r_info))
625         {
626         case R_MCORE_GNU_VTINHERIT:
627         case R_MCORE_GNU_VTENTRY:
628           break;
629
630         default:
631           switch (h->root.type)
632             {
633             case bfd_link_hash_defined:
634             case bfd_link_hash_defweak:
635               return h->root.u.def.section;
636               
637             case bfd_link_hash_common:
638               return h->root.u.c.p->section;
639
640             default:
641               break;
642             }
643         }
644     }
645   else
646     {
647       if (!(elf_bad_symtab (abfd)
648             && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
649           && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
650                 && sym->st_shndx != SHN_COMMON))
651         {
652           return bfd_section_from_elf_index (abfd, sym->st_shndx);
653         }
654     }
655
656   return NULL;
657 }
658
659 /* Update the got entry reference counts for the section being removed.  */
660
661 static boolean
662 mcore_elf_gc_sweep_hook (abfd, info, sec, relocs)
663      bfd *                     abfd ATTRIBUTE_UNUSED;
664      struct bfd_link_info *    info ATTRIBUTE_UNUSED;
665      asection *                sec ATTRIBUTE_UNUSED;
666      const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
667 {
668   return true;
669 }
670
671 /* Look through the relocs for a section during the first phase.
672    Since we don't do .gots or .plts, we just need to consider the
673    virtual table relocs for gc.  */
674  
675 static boolean
676 mcore_elf_check_relocs (abfd, info, sec, relocs)
677      bfd * abfd;
678      struct bfd_link_info * info;
679      asection * sec;
680      const Elf_Internal_Rela * relocs;
681 {
682   Elf_Internal_Shdr *           symtab_hdr;
683   struct elf_link_hash_entry ** sym_hashes;
684   struct elf_link_hash_entry ** sym_hashes_end;
685   const Elf_Internal_Rela *     rel;
686   const Elf_Internal_Rela *     rel_end;
687  
688   if (info->relocateable)
689     return true;
690  
691   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
692   sym_hashes = elf_sym_hashes (abfd);
693   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
694   if (!elf_bad_symtab (abfd))
695     sym_hashes_end -= symtab_hdr->sh_info;
696  
697   rel_end = relocs + sec->reloc_count;
698   
699   for (rel = relocs; rel < rel_end; rel++)
700     {
701       struct elf_link_hash_entry * h;
702       unsigned long r_symndx;
703  
704       r_symndx = ELF32_R_SYM (rel->r_info);
705       
706       if (r_symndx < symtab_hdr->sh_info)
707         h = NULL;
708       else
709         h = sym_hashes [r_symndx - symtab_hdr->sh_info];
710  
711       switch (ELF32_R_TYPE (rel->r_info))
712         {
713         /* This relocation describes the C++ object vtable hierarchy.
714            Reconstruct it for later use during GC.  */
715         case R_MCORE_GNU_VTINHERIT:
716           if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
717             return false;
718           break;
719           
720         /* This relocation describes which C++ vtable entries are actually
721            used.  Record for later use during GC.  */
722         case R_MCORE_GNU_VTENTRY:
723           if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
724             return false;
725           break;
726         }
727     }
728  
729   return true;
730 }
731
732 #define TARGET_BIG_SYM          bfd_elf32_mcore_big_vec
733 #define TARGET_BIG_NAME         "elf32-mcore-big"
734 #define TARGET_LITTLE_SYM       bfd_elf32_mcore_little_vec
735 #define TARGET_LITTLE_NAME      "elf32-mcore-little"
736
737 #define ELF_ARCH                bfd_arch_mcore
738 #define ELF_MACHINE_CODE        EM_MCORE
739 #define ELF_MAXPAGESIZE         0x1000          /* 4k, if we ever have 'em */
740 #define elf_info_to_howto       mcore_elf_info_to_howto
741 #define elf_info_to_howto_rel   NULL
742
743
744 #define bfd_elf32_bfd_copy_private_bfd_data     mcore_elf_copy_private_bfd_data
745 #define bfd_elf32_bfd_merge_private_bfd_data    mcore_elf_merge_private_bfd_data
746 #define bfd_elf32_bfd_set_private_flags         mcore_elf_set_private_flags
747 #define bfd_elf32_bfd_reloc_type_lookup         mcore_elf_reloc_type_lookup
748 #define elf_backend_relocate_section            mcore_elf_relocate_section
749 #define elf_backend_gc_mark_hook                mcore_elf_gc_mark_hook
750 #define elf_backend_gc_sweep_hook               mcore_elf_gc_sweep_hook
751 #define elf_backend_check_relocs                mcore_elf_check_relocs
752
753 #define elf_backend_can_gc_sections             1
754
755 #include "elf32-target.h"