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