Home | History | Annotate | Line # | Download | only in bfd
elf32-moxie.c revision 1.1
      1 /* moxie-specific support for 32-bit ELF.
      2    Copyright 2009, 2010, 2012 Free Software Foundation, Inc.
      3 
      4    Copied from elf32-fr30.c which is..
      5    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
      6    Free Software Foundation, Inc.
      7 
      8    This file is part of BFD, the Binary File Descriptor library.
      9 
     10    This program is free software; you can redistribute it and/or modify
     11    it under the terms of the GNU General Public License as published by
     12    the Free Software Foundation; either version 3 of the License, or
     13    (at your option) any later version.
     14 
     15    This program is distributed in the hope that it will be useful,
     16    but WITHOUT ANY WARRANTY; without even the implied warranty of
     17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18    GNU General Public License for more details.
     19 
     20    You should have received a copy of the GNU General Public License
     21    along with this program; if not, write to the Free Software
     22    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     23    MA 02110-1301, USA.  */
     24 
     25 #include "sysdep.h"
     26 #include "bfd.h"
     27 #include "libbfd.h"
     28 #include "elf-bfd.h"
     29 #include "elf/moxie.h"
     30 
     31 /* Forward declarations.  */
     32 
     33 static reloc_howto_type moxie_elf_howto_table [] =
     34 {
     35   /* This reloc does nothing.  */
     36   HOWTO (R_MOXIE_NONE,		/* type */
     37 	 0,			/* rightshift */
     38 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
     39 	 32,			/* bitsize */
     40 	 FALSE,			/* pc_relative */
     41 	 0,			/* bitpos */
     42 	 complain_overflow_bitfield, /* complain_on_overflow */
     43 	 bfd_elf_generic_reloc,	/* special_function */
     44 	 "R_MOXIE_NONE",		/* name */
     45 	 FALSE,			/* partial_inplace */
     46 	 0,			/* src_mask */
     47 	 0,			/* dst_mask */
     48 	 FALSE),		/* pcrel_offset */
     49 
     50   /* A 32 bit absolute relocation.  */
     51   HOWTO (R_MOXIE_32,		/* type */
     52 	 0,			/* rightshift */
     53 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
     54 	 32,			/* bitsize */
     55 	 FALSE,			/* pc_relative */
     56 	 0,			/* bitpos */
     57 	 complain_overflow_bitfield, /* complain_on_overflow */
     58 	 bfd_elf_generic_reloc,	/* special_function */
     59 	 "R_MOXIE_32",		/* name */
     60 	 FALSE,			/* partial_inplace */
     61 	 0x00000000,		/* src_mask */
     62 	 0xffffffff,		/* dst_mask */
     63 	 FALSE),		/* pcrel_offset */
     64 
     65   /* A 10 bit PC-relative relocation.  */
     66   HOWTO (R_MOXIE_PCREL10,	/* type.  */
     67 	 1,			/* rightshift.  */
     68 	 1,			/* size (0 = byte, 1 = short, 2 = long).  */
     69 	 10,			/* bitsize.  */
     70 	 TRUE,			/* pc_relative.  */
     71 	 0,			/* bitpos.  */
     72 	 complain_overflow_signed, /* complain_on_overflow.  */
     73 	 bfd_elf_generic_reloc,	/* special_function.  */
     74 	 "R_MOXIE_PCREL10",		/* name.  */
     75 	 FALSE,			/* partial_inplace.  */
     76 	 0,			/* src_mask.  */
     77 	 0x000003FF,		/* dst_mask.  */
     78 	 TRUE),			/* pcrel_offset.  */
     79 };
     80 
     81 /* Map BFD reloc types to MOXIE ELF reloc types.  */
     83 
     84 struct moxie_reloc_map
     85 {
     86   bfd_reloc_code_real_type bfd_reloc_val;
     87   unsigned int moxie_reloc_val;
     88 };
     89 
     90 static const struct moxie_reloc_map moxie_reloc_map [] =
     91 {
     92   { BFD_RELOC_NONE,            R_MOXIE_NONE },
     93   { BFD_RELOC_32,              R_MOXIE_32 },
     94   { BFD_RELOC_MOXIE_10_PCREL,  R_MOXIE_PCREL10 },
     95 };
     96 
     97 static reloc_howto_type *
     98 moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     99 			 bfd_reloc_code_real_type code)
    100 {
    101   unsigned int i;
    102 
    103   for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]);
    104        --i;)
    105     if (moxie_reloc_map [i].bfd_reloc_val == code)
    106       return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val];
    107 
    108   return NULL;
    109 }
    110 
    111 static reloc_howto_type *
    112 moxie_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
    113 {
    114   unsigned int i;
    115 
    116   for (i = 0;
    117        i < sizeof (moxie_elf_howto_table) / sizeof (moxie_elf_howto_table[0]);
    118        i++)
    119     if (moxie_elf_howto_table[i].name != NULL
    120 	&& strcasecmp (moxie_elf_howto_table[i].name, r_name) == 0)
    121       return &moxie_elf_howto_table[i];
    122 
    123   return NULL;
    124 }
    125 
    126 /* Set the howto pointer for an MOXIE ELF reloc.  */
    127 
    128 static void
    129 moxie_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
    130 			  arelent *cache_ptr,
    131 			  Elf_Internal_Rela *dst)
    132 {
    133   unsigned int r_type;
    134 
    135   r_type = ELF32_R_TYPE (dst->r_info);
    136   BFD_ASSERT (r_type < (unsigned int) R_MOXIE_max);
    137   cache_ptr->howto = & moxie_elf_howto_table [r_type];
    138 }
    139 
    140 /* Perform a single relocation.  By default we use the standard BFD
    142    routines, but a few relocs, we have to do them ourselves.  */
    143 
    144 static bfd_reloc_status_type
    145 moxie_final_link_relocate (reloc_howto_type *howto,
    146 			   bfd *input_bfd,
    147 			   asection *input_section,
    148 			   bfd_byte *contents,
    149 			   Elf_Internal_Rela *rel,
    150 			   bfd_vma relocation)
    151 {
    152   bfd_reloc_status_type r = bfd_reloc_ok;
    153 
    154   switch (howto->type)
    155     {
    156     default:
    157       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    158 				    contents, rel->r_offset,
    159 				    relocation, rel->r_addend);
    160     }
    161 
    162   return r;
    163 }
    164 
    165 /* Relocate an MOXIE ELF section.
    167 
    168    The RELOCATE_SECTION function is called by the new ELF backend linker
    169    to handle the relocations for a section.
    170 
    171    The relocs are always passed as Rela structures; if the section
    172    actually uses Rel structures, the r_addend field will always be
    173    zero.
    174 
    175    This function is responsible for adjusting the section contents as
    176    necessary, and (if using Rela relocs and generating a relocatable
    177    output file) adjusting the reloc addend as necessary.
    178 
    179    This function does not have to worry about setting the reloc
    180    address or the reloc symbol index.
    181 
    182    LOCAL_SYMS is a pointer to the swapped in local symbols.
    183 
    184    LOCAL_SECTIONS is an array giving the section in the input file
    185    corresponding to the st_shndx field of each local symbol.
    186 
    187    The global hash table entry for the global symbols can be found
    188    via elf_sym_hashes (input_bfd).
    189 
    190    When generating relocatable output, this function must handle
    191    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    192    going to be the section symbol corresponding to the output
    193    section, which means that the addend must be adjusted
    194    accordingly.  */
    195 
    196 static bfd_boolean
    197 moxie_elf_relocate_section (bfd *output_bfd,
    198 			    struct bfd_link_info *info,
    199 			    bfd *input_bfd,
    200 			    asection *input_section,
    201 			    bfd_byte *contents,
    202 			    Elf_Internal_Rela *relocs,
    203 			    Elf_Internal_Sym *local_syms,
    204 			    asection **local_sections)
    205 {
    206   Elf_Internal_Shdr *symtab_hdr;
    207   struct elf_link_hash_entry **sym_hashes;
    208   Elf_Internal_Rela *rel;
    209   Elf_Internal_Rela *relend;
    210 
    211   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    212   sym_hashes = elf_sym_hashes (input_bfd);
    213   relend     = relocs + input_section->reloc_count;
    214 
    215   for (rel = relocs; rel < relend; rel ++)
    216     {
    217       reloc_howto_type *howto;
    218       unsigned long r_symndx;
    219       Elf_Internal_Sym *sym;
    220       asection *sec;
    221       struct elf_link_hash_entry *h;
    222       bfd_vma relocation;
    223       bfd_reloc_status_type r;
    224       const char *name;
    225       int r_type;
    226 
    227       r_type = ELF32_R_TYPE (rel->r_info);
    228       r_symndx = ELF32_R_SYM (rel->r_info);
    229       howto  = moxie_elf_howto_table + r_type;
    230       h      = NULL;
    231       sym    = NULL;
    232       sec    = NULL;
    233 
    234       if (r_symndx < symtab_hdr->sh_info)
    235 	{
    236 	  sym = local_syms + r_symndx;
    237 	  sec = local_sections [r_symndx];
    238 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    239 
    240 	  name = bfd_elf_string_from_elf_section
    241 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
    242 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
    243 	}
    244       else
    245 	{
    246 	  bfd_boolean unresolved_reloc, warned, ignored;
    247 
    248 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    249 				   r_symndx, symtab_hdr, sym_hashes,
    250 				   h, sec, relocation,
    251 				   unresolved_reloc, warned, ignored);
    252 
    253 	  name = h->root.root.string;
    254 	}
    255 
    256       if (sec != NULL && discarded_section (sec))
    257 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    258 					 rel, 1, relend, howto, 0, contents);
    259 
    260       if (info->relocatable)
    261 	continue;
    262 
    263       r = moxie_final_link_relocate (howto, input_bfd, input_section,
    264 				     contents, rel, relocation);
    265 
    266       if (r != bfd_reloc_ok)
    267 	{
    268 	  const char * msg = NULL;
    269 
    270 	  switch (r)
    271 	    {
    272 	    case bfd_reloc_overflow:
    273 	      r = info->callbacks->reloc_overflow
    274 		(info, (h ? &h->root : NULL), name, howto->name,
    275 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    276 	      break;
    277 
    278 	    case bfd_reloc_undefined:
    279 	      r = info->callbacks->undefined_symbol
    280 		(info, name, input_bfd, input_section, rel->r_offset,
    281 		 TRUE);
    282 	      break;
    283 
    284 	    case bfd_reloc_outofrange:
    285 	      msg = _("internal error: out of range error");
    286 	      break;
    287 
    288 	    case bfd_reloc_notsupported:
    289 	      msg = _("internal error: unsupported relocation error");
    290 	      break;
    291 
    292 	    case bfd_reloc_dangerous:
    293 	      msg = _("internal error: dangerous relocation");
    294 	      break;
    295 
    296 	    default:
    297 	      msg = _("internal error: unknown error");
    298 	      break;
    299 	    }
    300 
    301 	  if (msg)
    302 	    r = info->callbacks->warning
    303 	      (info, msg, name, input_bfd, input_section, rel->r_offset);
    304 
    305 	  if (! r)
    306 	    return FALSE;
    307 	}
    308     }
    309 
    310   return TRUE;
    311 }
    312 
    313 /* Return the section that should be marked against GC for a given
    315    relocation.  */
    316 
    317 static asection *
    318 moxie_elf_gc_mark_hook (asection *sec,
    319 			struct bfd_link_info *info,
    320 			Elf_Internal_Rela *rel,
    321 			struct elf_link_hash_entry *h,
    322 			Elf_Internal_Sym *sym)
    323 {
    324   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
    325 }
    326 
    327 /* Look through the relocs for a section during the first phase.
    328    Since we don't do .gots or .plts, we just need to consider the
    329    virtual table relocs for gc.  */
    330 
    331 static bfd_boolean
    332 moxie_elf_check_relocs (bfd *abfd,
    333 			struct bfd_link_info *info,
    334 			asection *sec,
    335 			const Elf_Internal_Rela *relocs)
    336 {
    337   Elf_Internal_Shdr *symtab_hdr;
    338   struct elf_link_hash_entry **sym_hashes;
    339   const Elf_Internal_Rela *rel;
    340   const Elf_Internal_Rela *rel_end;
    341 
    342   if (info->relocatable)
    343     return TRUE;
    344 
    345   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    346   sym_hashes = elf_sym_hashes (abfd);
    347 
    348   rel_end = relocs + sec->reloc_count;
    349   for (rel = relocs; rel < rel_end; rel++)
    350     {
    351       struct elf_link_hash_entry *h;
    352       unsigned long r_symndx;
    353 
    354       r_symndx = ELF32_R_SYM (rel->r_info);
    355       if (r_symndx < symtab_hdr->sh_info)
    356         h = NULL;
    357       else
    358 	{
    359 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    360 	  while (h->root.type == bfd_link_hash_indirect
    361 		 || h->root.type == bfd_link_hash_warning)
    362 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    363 
    364 	  /* PR15323, ref flags aren't set for references in the same
    365 	     object.  */
    366 	  h->root.non_ir_ref = 1;
    367 	}
    368     }
    369 
    370   return TRUE;
    371 }
    372 
    373 #define ELF_ARCH		bfd_arch_moxie
    375 #define ELF_MACHINE_CODE	EM_MOXIE
    376 #define ELF_MAXPAGESIZE		0x1
    377 
    378 #define TARGET_BIG_SYM          bfd_elf32_bigmoxie_vec
    379 #define TARGET_BIG_NAME		"elf32-bigmoxie"
    380 #define TARGET_LITTLE_SYM       bfd_elf32_littlemoxie_vec
    381 #define TARGET_LITTLE_NAME	"elf32-littlemoxie"
    382 
    383 #define elf_info_to_howto_rel			NULL
    384 #define elf_info_to_howto			moxie_info_to_howto_rela
    385 #define elf_backend_relocate_section		moxie_elf_relocate_section
    386 #define elf_backend_gc_mark_hook		moxie_elf_gc_mark_hook
    387 #define elf_backend_check_relocs                moxie_elf_check_relocs
    388 
    389 #define elf_backend_can_gc_sections		1
    390 #define elf_backend_rela_normal			1
    391 
    392 #define bfd_elf32_bfd_reloc_type_lookup		moxie_reloc_type_lookup
    393 #define bfd_elf32_bfd_reloc_name_lookup		moxie_reloc_name_lookup
    394 
    395 #include "elf32-target.h"
    396