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