Back to index

cell-binutils  2.17cvs20070401
elf32-mcore.c
Go to the documentation of this file.
00001 /* Motorola MCore specific support for 32-bit ELF
00002    Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
00003    2007 Free Software Foundation, Inc.
00004 
00005    This file is part of BFD, the Binary File Descriptor library.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
00020    USA.  */
00021 
00022 /* This file is based on a preliminary RCE ELF ABI.  The
00023    information may not match the final RCE ELF ABI.   */
00024 
00025 #include "bfd.h"
00026 #include "sysdep.h"
00027 #include "bfdlink.h"
00028 #include "libbfd.h"
00029 #include "elf-bfd.h"
00030 #include "elf/mcore.h"
00031 #include <assert.h>
00032 
00033 /* RELA relocs are used here...  */
00034 
00035 /* Function to set whether a module needs the -mrelocatable bit set.  */
00036 
00037 static bfd_boolean
00038 mcore_elf_set_private_flags (bfd * abfd, flagword flags)
00039 {
00040   BFD_ASSERT (! elf_flags_init (abfd)
00041              || elf_elfheader (abfd)->e_flags == flags);
00042 
00043   elf_elfheader (abfd)->e_flags = flags;
00044   elf_flags_init (abfd) = TRUE;
00045   return TRUE;
00046 }
00047 
00048 /* Merge backend specific data from an object file to the output
00049    object file when linking.  */
00050 
00051 static bfd_boolean
00052 mcore_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
00053 {
00054   flagword old_flags;
00055   flagword new_flags;
00056 
00057   /* Check if we have the same endianess.  */
00058   if (! _bfd_generic_verify_endian_match (ibfd, obfd))
00059     return FALSE;
00060 
00061   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
00062       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
00063     return TRUE;
00064 
00065   new_flags = elf_elfheader (ibfd)->e_flags;
00066   old_flags = elf_elfheader (obfd)->e_flags;
00067 
00068   if (! elf_flags_init (obfd))
00069     {
00070        /* First call, no flags set.  */
00071       elf_flags_init (obfd) = TRUE;
00072       elf_elfheader (obfd)->e_flags = new_flags;
00073     }
00074   else if (new_flags == old_flags)
00075     /* Compatible flags are OK.  */
00076     ;
00077   else
00078     {
00079       /* FIXME */
00080     }
00081 
00082   return TRUE;
00083 }
00084 
00085 /* Don't pretend we can deal with unsupported relocs.  */
00086 
00087 static bfd_reloc_status_type
00088 mcore_elf_unsupported_reloc (bfd * abfd,
00089                           arelent * reloc_entry,
00090                           asymbol * symbol ATTRIBUTE_UNUSED,
00091                           PTR data ATTRIBUTE_UNUSED,
00092                           asection * input_section ATTRIBUTE_UNUSED,
00093                           bfd * output_bfd ATTRIBUTE_UNUSED,
00094                           char ** error_message ATTRIBUTE_UNUSED)
00095 {
00096   BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
00097 
00098   _bfd_error_handler (_("%B: Relocation %s (%d) is not currently supported.\n"),
00099                     abfd,
00100                     reloc_entry->howto->name,
00101                     reloc_entry->howto->type);
00102 
00103   return bfd_reloc_notsupported;
00104 }
00105 
00106 static reloc_howto_type * mcore_elf_howto_table [(int) R_MCORE_max];
00107 
00108 static reloc_howto_type mcore_elf_howto_raw[] =
00109 {
00110   /* This reloc does nothing.  */
00111   HOWTO (R_MCORE_NONE,             /* type */
00112         0,                  /* rightshift */
00113         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00114         32,                 /* bitsize */
00115         FALSE,                     /* pc_relative */
00116         0,                  /* bitpos */
00117         complain_overflow_bitfield,  /* complain_on_overflow */
00118         NULL,                  /* special_function */
00119         "R_MCORE_NONE",     /* name */
00120         FALSE,                     /* partial_inplace */
00121         0,                  /* src_mask */
00122         0,                  /* dst_mask */
00123         FALSE),             /* pcrel_offset */
00124 
00125   /* A standard 32 bit relocation.  */
00126   HOWTO (R_MCORE_ADDR32,    /* type */
00127         0,                  /* rightshift */
00128         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00129         32,                 /* bitsize */
00130         FALSE,                     /* pc_relative */
00131         0,                  /* bitpos */
00132         complain_overflow_bitfield, /* complain_on_overflow */
00133         bfd_elf_generic_reloc,     /* special_function */
00134         "ADDR32",           /* name *//* For compatibility with coff/pe port.  */
00135         FALSE,                     /* partial_inplace */
00136         0x0,                /* src_mask */
00137         0xffffffff,         /* dst_mask */
00138         FALSE),             /* pcrel_offset */
00139 
00140   /* 8 bits + 2 zero bits; jmpi/jsri/lrw instructions.
00141      Should not appear in object files.  */
00142   HOWTO (R_MCORE_PCRELIMM8BY4,     /* type */
00143         2,                  /* rightshift */
00144         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00145         8,                  /* bitsize */
00146         TRUE,               /* pc_relative */
00147         0,                  /* bitpos */
00148         complain_overflow_bitfield, /* complain_on_overflow */
00149         mcore_elf_unsupported_reloc,      /* special_function */
00150         "R_MCORE_PCRELIMM8BY4",/* name */
00151         FALSE,                     /* partial_inplace */
00152         0,                  /* src_mask */
00153         0,                  /* dst_mask */
00154         TRUE),                     /* pcrel_offset */
00155 
00156   /* bsr/bt/bf/br instructions; 11 bits + 1 zero bit
00157      Span 2k instructions == 4k bytes.
00158      Only useful pieces at the relocated address are the opcode (5 bits) */
00159   HOWTO (R_MCORE_PCRELIMM11BY2,/* type */
00160         1,                  /* rightshift */
00161         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00162         11,                 /* bitsize */
00163         TRUE,               /* pc_relative */
00164         0,                  /* bitpos */
00165         complain_overflow_signed, /* complain_on_overflow */
00166         bfd_elf_generic_reloc,     /* special_function */
00167         "R_MCORE_PCRELIMM11BY2",/* name */
00168         FALSE,                     /* partial_inplace */
00169         0x0,                /* src_mask */
00170         0x7ff,                     /* dst_mask */
00171         TRUE),                     /* pcrel_offset */
00172 
00173   /* 4 bits + 1 zero bit; 'loopt' instruction only; unsupported.  */
00174   HOWTO (R_MCORE_PCRELIMM4BY2,     /* type */
00175         1,                  /* rightshift */
00176         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00177         4,                  /* bitsize */
00178         TRUE,               /* pc_relative */
00179         0,                  /* bitpos */
00180         complain_overflow_bitfield, /* complain_on_overflow */
00181         mcore_elf_unsupported_reloc,/* special_function */
00182         "R_MCORE_PCRELIMM4BY2",/* name */
00183         FALSE,                     /* partial_inplace */
00184         0,                  /* src_mask */
00185         0,                  /* dst_mask */
00186         TRUE),                     /* pcrel_offset */
00187 
00188   /* 32-bit pc-relative. Eventually this will help support PIC code.  */
00189   HOWTO (R_MCORE_PCREL32,   /* type */
00190         0,                  /* rightshift */
00191         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00192         32,                 /* bitsize */
00193         TRUE,               /* pc_relative */
00194         0,                  /* bitpos */
00195         complain_overflow_bitfield, /* complain_on_overflow */
00196         bfd_elf_generic_reloc,     /* special_function */
00197         "R_MCORE_PCREL32",  /* name */
00198         FALSE,                     /* partial_inplace */
00199         0x0,                /* src_mask */
00200         0xffffffff,         /* dst_mask */
00201         TRUE),                     /* pcrel_offset */
00202 
00203   /* Like PCRELIMM11BY2, this relocation indicates that there is a
00204      'jsri' at the specified address. There is a separate relocation
00205      entry for the literal pool entry that it references, but we
00206      might be able to change the jsri to a bsr if the target turns out
00207      to be close enough [even though we won't reclaim the literal pool
00208      entry, we'll get some runtime efficiency back]. Note that this
00209      is a relocation that we are allowed to safely ignore.  */
00210   HOWTO (R_MCORE_PCRELJSR_IMM11BY2,/* type */
00211         1,                  /* rightshift */
00212         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00213         11,                 /* bitsize */
00214         TRUE,               /* pc_relative */
00215         0,                  /* bitpos */
00216         complain_overflow_signed, /* complain_on_overflow */
00217         bfd_elf_generic_reloc,     /* special_function */
00218         "R_MCORE_PCRELJSR_IMM11BY2", /* name */
00219         FALSE,                     /* partial_inplace */
00220         0x0,                /* src_mask */
00221         0x7ff,                     /* dst_mask */
00222         TRUE),                     /* pcrel_offset */
00223 
00224   /* GNU extension to record C++ vtable hierarchy.  */
00225   HOWTO (R_MCORE_GNU_VTINHERIT, /* type */
00226          0,                     /* rightshift */
00227          2,                     /* size (0 = byte, 1 = short, 2 = long) */
00228          0,                     /* bitsize */
00229          FALSE,                 /* pc_relative */
00230          0,                     /* bitpos */
00231          complain_overflow_dont, /* complain_on_overflow */
00232          NULL,                  /* special_function */
00233          "R_MCORE_GNU_VTINHERIT", /* name */
00234          FALSE,                 /* partial_inplace */
00235          0,                     /* src_mask */
00236          0,                     /* dst_mask */
00237          FALSE),                /* pcrel_offset */
00238 
00239   /* GNU extension to record C++ vtable member usage.  */
00240   HOWTO (R_MCORE_GNU_VTENTRY,   /* type */
00241          0,                     /* rightshift */
00242          2,                     /* size (0 = byte, 1 = short, 2 = long) */
00243          0,                     /* bitsize */
00244          FALSE,                 /* pc_relative */
00245          0,                     /* bitpos */
00246          complain_overflow_dont,/* complain_on_overflow */
00247          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
00248          "R_MCORE_GNU_VTENTRY", /* name */
00249          FALSE,                 /* partial_inplace */
00250          0,                     /* src_mask */
00251          0,                     /* dst_mask */
00252          FALSE),                /* pcrel_offset */
00253 
00254   HOWTO (R_MCORE_RELATIVE,      /* type */
00255         0,                  /* rightshift */
00256         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00257         32,                 /* bitsize */
00258         FALSE,                     /* pc_relative */
00259         0,                  /* bitpos */
00260         complain_overflow_signed, /* complain_on_overflow */
00261         NULL,                  /* special_function */
00262         "R_MCORE_RELATIVE",    /* name */
00263         TRUE,               /* partial_inplace */
00264         0xffffffff,         /* src_mask */
00265         0xffffffff,         /* dst_mask */
00266         FALSE)                     /* pcrel_offset */
00267 };
00268 
00269 #ifndef NUM_ELEM
00270 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
00271 #endif
00272 
00273 /* Initialize the mcore_elf_howto_table, so that linear accesses can be done.  */
00274 static void
00275 mcore_elf_howto_init (void)
00276 {
00277   unsigned int i;
00278 
00279   for (i = NUM_ELEM (mcore_elf_howto_raw); i--;)
00280     {
00281       unsigned int type;
00282 
00283       type = mcore_elf_howto_raw[i].type;
00284 
00285       BFD_ASSERT (type < NUM_ELEM (mcore_elf_howto_table));
00286 
00287       mcore_elf_howto_table [type] = & mcore_elf_howto_raw [i];
00288     }
00289 }
00290 
00291 static reloc_howto_type *
00292 mcore_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
00293                           bfd_reloc_code_real_type code)
00294 {
00295   enum elf_mcore_reloc_type mcore_reloc = R_MCORE_NONE;
00296 
00297   switch (code)
00298     {
00299     case BFD_RELOC_NONE:                mcore_reloc = R_MCORE_NONE; break;
00300     case BFD_RELOC_32:                         mcore_reloc = R_MCORE_ADDR32; break;
00301     case BFD_RELOC_MCORE_PCREL_IMM8BY4:        mcore_reloc = R_MCORE_PCRELIMM8BY4; break;
00302     case BFD_RELOC_MCORE_PCREL_IMM11BY2:     mcore_reloc = R_MCORE_PCRELIMM11BY2; break;
00303     case BFD_RELOC_MCORE_PCREL_IMM4BY2:        mcore_reloc = R_MCORE_PCRELIMM4BY2; break;
00304     case BFD_RELOC_32_PCREL:                   mcore_reloc = R_MCORE_PCREL32; break;
00305     case BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2: mcore_reloc = R_MCORE_PCRELJSR_IMM11BY2; break;
00306     case BFD_RELOC_VTABLE_INHERIT:           mcore_reloc = R_MCORE_GNU_VTINHERIT; break;
00307     case BFD_RELOC_VTABLE_ENTRY:             mcore_reloc = R_MCORE_GNU_VTENTRY; break;
00308     case BFD_RELOC_RVA:                      mcore_reloc = R_MCORE_RELATIVE; break;
00309     default:
00310       return NULL;
00311     }
00312 
00313   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])
00314     /* Initialize howto table if needed.  */
00315     mcore_elf_howto_init ();
00316 
00317   return mcore_elf_howto_table [(int) mcore_reloc];
00318 };
00319 
00320 static reloc_howto_type *
00321 mcore_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00322                           const char *r_name)
00323 {
00324   unsigned int i;
00325 
00326   for (i = 0;
00327        i < sizeof (mcore_elf_howto_raw) / sizeof (mcore_elf_howto_raw[0]);
00328        i++)
00329     if (mcore_elf_howto_raw[i].name != NULL
00330        && strcasecmp (mcore_elf_howto_raw[i].name, r_name) == 0)
00331       return &mcore_elf_howto_raw[i];
00332 
00333   return NULL;
00334 }
00335 
00336 /* Set the howto pointer for a RCE ELF reloc.  */
00337 
00338 static void
00339 mcore_elf_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
00340                       arelent * cache_ptr,
00341                       Elf_Internal_Rela * dst)
00342 {
00343   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])
00344     /* Initialize howto table if needed.  */
00345     mcore_elf_howto_init ();
00346 
00347   BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MCORE_max);
00348 
00349   cache_ptr->howto = mcore_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
00350 }
00351 
00352 /* The RELOCATE_SECTION function is called by the ELF backend linker
00353    to handle the relocations for a section.
00354 
00355    The relocs are always passed as Rela structures; if the section
00356    actually uses Rel structures, the r_addend field will always be
00357    zero.
00358 
00359    This function is responsible for adjust the section contents as
00360    necessary, and (if using Rela relocs and generating a
00361    relocatable output file) adjusting the reloc addend as
00362    necessary.
00363 
00364    This function does not have to worry about setting the reloc
00365    address or the reloc symbol index.
00366 
00367    LOCAL_SYMS is a pointer to the swapped in local symbols.
00368 
00369    LOCAL_SECTIONS is an array giving the section in the input file
00370    corresponding to the st_shndx field of each local symbol.
00371 
00372    The global hash table entry for the global symbols can be found
00373    via elf_sym_hashes (input_bfd).
00374 
00375    When generating relocatable output, this function must handle
00376    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
00377    going to be the section symbol corresponding to the output
00378    section, which means that the addend must be adjusted
00379    accordingly.  */
00380 
00381 static bfd_boolean
00382 mcore_elf_relocate_section (bfd * output_bfd,
00383                          struct bfd_link_info * info,
00384                          bfd * input_bfd,
00385                          asection * input_section,
00386                          bfd_byte * contents,
00387                          Elf_Internal_Rela * relocs,
00388                          Elf_Internal_Sym * local_syms,
00389                          asection ** local_sections)
00390 {
00391   Elf_Internal_Shdr * symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
00392   struct elf_link_hash_entry ** sym_hashes = elf_sym_hashes (input_bfd);
00393   Elf_Internal_Rela * rel = relocs;
00394   Elf_Internal_Rela * relend = relocs + input_section->reloc_count;
00395   bfd_boolean ret = TRUE;
00396 
00397 #ifdef DEBUG
00398   _bfd_error_handler
00399     ("mcore_elf_relocate_section called for %B section %A, %ld relocations%s",
00400      input_bfd,
00401      input_section,
00402      (long) input_section->reloc_count,
00403      (info->relocatable) ? " (relocatable)" : "");
00404 #endif
00405 
00406   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])   /* Initialize howto table if needed */
00407     mcore_elf_howto_init ();
00408 
00409   for (; rel < relend; rel++)
00410     {
00411       enum elf_mcore_reloc_type    r_type = (enum elf_mcore_reloc_type) ELF32_R_TYPE (rel->r_info);
00412       bfd_vma                      offset = rel->r_offset;
00413       bfd_vma                      addend = rel->r_addend;
00414       bfd_reloc_status_type        r = bfd_reloc_other;
00415       asection *                   sec = NULL;
00416       reloc_howto_type *           howto;
00417       bfd_vma                      relocation;
00418       Elf_Internal_Sym *           sym = NULL;
00419       unsigned long                r_symndx;
00420       struct elf_link_hash_entry * h = NULL;
00421       unsigned short               oldinst = 0;
00422 
00423       /* Unknown relocation handling.  */
00424       if ((unsigned) r_type >= (unsigned) R_MCORE_max
00425          || ! mcore_elf_howto_table [(int)r_type])
00426        {
00427          _bfd_error_handler (_("%B: Unknown relocation type %d\n"),
00428                            input_bfd, (int) r_type);
00429 
00430          bfd_set_error (bfd_error_bad_value);
00431          ret = FALSE;
00432          continue;
00433        }
00434 
00435       howto = mcore_elf_howto_table [(int) r_type];
00436       r_symndx = ELF32_R_SYM (rel->r_info);
00437 
00438       /* Complain about known relocation that are not yet supported.  */
00439       if (howto->special_function == mcore_elf_unsupported_reloc)
00440        {
00441          _bfd_error_handler (_("%B: Relocation %s (%d) is not currently supported.\n"),
00442                            input_bfd,
00443                            howto->name,
00444                            (int)r_type);
00445 
00446          bfd_set_error (bfd_error_bad_value);
00447          ret = FALSE;
00448          continue;
00449        }
00450 
00451       if (r_symndx < symtab_hdr->sh_info)
00452        {
00453          sym = local_syms + r_symndx;
00454          sec = local_sections [r_symndx];
00455          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
00456          addend = rel->r_addend;
00457        }
00458       else
00459        {
00460          bfd_boolean unresolved_reloc, warned;
00461 
00462          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00463                                r_symndx, symtab_hdr, sym_hashes,
00464                                h, sec, relocation,
00465                                unresolved_reloc, warned);
00466        }
00467 
00468       if (sec != NULL && elf_discarded_section (sec))
00469        {
00470          /* For relocs against symbols from removed linkonce sections,
00471             or sections discarded by a linker script, we just want the
00472             section contents zeroed.  Avoid any special processing.  */
00473          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
00474          rel->r_info = 0;
00475          rel->r_addend = 0;
00476          continue;
00477        }
00478 
00479       if (info->relocatable)
00480        continue;
00481 
00482       switch (r_type)
00483        {
00484        default:
00485          break;
00486 
00487        case R_MCORE_PCRELJSR_IMM11BY2:
00488          oldinst = bfd_get_16 (input_bfd, contents + offset);
00489 #define       MCORE_INST_BSR       0xF800
00490          bfd_put_16 (input_bfd, (bfd_vma) MCORE_INST_BSR, contents + offset);
00491          break;
00492        }
00493 
00494 #ifdef DEBUG
00495       fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
00496               howto->name, r_type, r_symndx, (long) offset, (long) addend);
00497 #endif
00498 
00499       r = _bfd_final_link_relocate
00500        (howto, input_bfd, input_section, contents, offset, relocation, addend);
00501 
00502       if (r != bfd_reloc_ok && r_type == R_MCORE_PCRELJSR_IMM11BY2)
00503        {
00504          /* Wasn't ok, back it out and give up.  */
00505          bfd_put_16 (input_bfd, (bfd_vma) oldinst, contents + offset);
00506          r = bfd_reloc_ok;
00507        }
00508 
00509       if (r != bfd_reloc_ok)
00510        {
00511          ret = FALSE;
00512 
00513          switch (r)
00514            {
00515            default:
00516              break;
00517 
00518            case bfd_reloc_overflow:
00519              {
00520               const char * name;
00521 
00522               if (h != NULL)
00523                 name = NULL;
00524               else
00525                 {
00526                   name = bfd_elf_string_from_elf_section
00527                     (input_bfd, symtab_hdr->sh_link, sym->st_name);
00528 
00529                   if (name == NULL)
00530                     break;
00531 
00532                   if (* name == '\0')
00533                     name = bfd_section_name (input_bfd, sec);
00534                 }
00535 
00536               (*info->callbacks->reloc_overflow)
00537                 (info, (h ? &h->root : NULL), name, howto->name,
00538                  (bfd_vma) 0, input_bfd, input_section, offset);
00539              }
00540              break;
00541            }
00542        }
00543     }
00544 
00545 #ifdef DEBUG
00546   fprintf (stderr, "\n");
00547 #endif
00548 
00549   return ret;
00550 }
00551 
00552 /* Return the section that should be marked against GC for a given
00553    relocation.  */
00554 
00555 static asection *
00556 mcore_elf_gc_mark_hook (asection *sec,
00557                      struct bfd_link_info *info,
00558                      Elf_Internal_Rela *rel,
00559                      struct elf_link_hash_entry *h,
00560                      Elf_Internal_Sym *sym)
00561 {
00562   if (h != NULL)
00563     switch (ELF32_R_TYPE (rel->r_info))
00564       {
00565       case R_MCORE_GNU_VTINHERIT:
00566       case R_MCORE_GNU_VTENTRY:
00567        return NULL;
00568       }
00569 
00570   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
00571 }
00572 
00573 /* Update the got entry reference counts for the section being removed.  */
00574 
00575 static bfd_boolean
00576 mcore_elf_gc_sweep_hook (bfd * abfd ATTRIBUTE_UNUSED,
00577                       struct bfd_link_info * info ATTRIBUTE_UNUSED,
00578                       asection * sec ATTRIBUTE_UNUSED,
00579                       const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
00580 {
00581   return TRUE;
00582 }
00583 
00584 /* Look through the relocs for a section during the first phase.
00585    Since we don't do .gots or .plts, we just need to consider the
00586    virtual table relocs for gc.  */
00587 
00588 static bfd_boolean
00589 mcore_elf_check_relocs (bfd * abfd,
00590                      struct bfd_link_info * info,
00591                      asection * sec,
00592                      const Elf_Internal_Rela * relocs)
00593 {
00594   Elf_Internal_Shdr * symtab_hdr;
00595   struct elf_link_hash_entry ** sym_hashes;
00596   struct elf_link_hash_entry ** sym_hashes_end;
00597   const Elf_Internal_Rela * rel;
00598   const Elf_Internal_Rela * rel_end;
00599 
00600   if (info->relocatable)
00601     return TRUE;
00602 
00603   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
00604   sym_hashes = elf_sym_hashes (abfd);
00605   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
00606   if (!elf_bad_symtab (abfd))
00607     sym_hashes_end -= symtab_hdr->sh_info;
00608 
00609   rel_end = relocs + sec->reloc_count;
00610 
00611   for (rel = relocs; rel < rel_end; rel++)
00612     {
00613       struct elf_link_hash_entry * h;
00614       unsigned long r_symndx;
00615 
00616       r_symndx = ELF32_R_SYM (rel->r_info);
00617 
00618       if (r_symndx < symtab_hdr->sh_info)
00619         h = NULL;
00620       else
00621        {
00622          h = sym_hashes [r_symndx - symtab_hdr->sh_info];
00623          while (h->root.type == bfd_link_hash_indirect
00624                || h->root.type == bfd_link_hash_warning)
00625            h = (struct elf_link_hash_entry *) h->root.u.i.link;
00626        }
00627 
00628       switch (ELF32_R_TYPE (rel->r_info))
00629         {
00630         /* This relocation describes the C++ object vtable hierarchy.
00631            Reconstruct it for later use during GC.  */
00632         case R_MCORE_GNU_VTINHERIT:
00633           if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00634             return FALSE;
00635           break;
00636 
00637         /* This relocation describes which C++ vtable entries are actually
00638            used.  Record for later use during GC.  */
00639         case R_MCORE_GNU_VTENTRY:
00640           if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00641             return FALSE;
00642           break;
00643         }
00644     }
00645 
00646   return TRUE;
00647 }
00648 
00649 static const struct bfd_elf_special_section mcore_elf_special_sections[]=
00650 {
00651   { STRING_COMMA_LEN (".ctors"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
00652   { STRING_COMMA_LEN (".dtors"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
00653   { NULL,                     0,  0, 0,            0 }
00654 };
00655 
00656 #define TARGET_BIG_SYM             bfd_elf32_mcore_big_vec
00657 #define TARGET_BIG_NAME            "elf32-mcore-big"
00658 #define TARGET_LITTLE_SYM       bfd_elf32_mcore_little_vec
00659 #define TARGET_LITTLE_NAME      "elf32-mcore-little"
00660 
00661 #define ELF_ARCH            bfd_arch_mcore
00662 #define ELF_MACHINE_CODE    EM_MCORE
00663 #define ELF_MAXPAGESIZE            0x1000        /* 4k, if we ever have 'em */
00664 #define elf_info_to_howto   mcore_elf_info_to_howto
00665 #define elf_info_to_howto_rel      NULL
00666 
00667 #define bfd_elf32_bfd_merge_private_bfd_data     mcore_elf_merge_private_bfd_data
00668 #define bfd_elf32_bfd_set_private_flags          mcore_elf_set_private_flags
00669 #define bfd_elf32_bfd_reloc_type_lookup          mcore_elf_reloc_type_lookup
00670 #define bfd_elf32_bfd_reloc_name_lookup   mcore_elf_reloc_name_lookup
00671 #define elf_backend_relocate_section             mcore_elf_relocate_section
00672 #define elf_backend_gc_mark_hook          mcore_elf_gc_mark_hook
00673 #define elf_backend_gc_sweep_hook         mcore_elf_gc_sweep_hook
00674 #define elf_backend_check_relocs                mcore_elf_check_relocs
00675 #define elf_backend_special_sections             mcore_elf_special_sections
00676 
00677 #define elf_backend_can_gc_sections              1
00678 #define elf_backend_rela_normal                  1
00679 
00680 #include "elf32-target.h"