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