Home | History | Annotate | Line # | Download | only in bfd
elf32-moxie.c revision 1.7
      1 /* moxie-specific support for 32-bit ELF.
      2    Copyright (C) 2009-2017 Free Software Foundation, Inc.
      3 
      4    Copied from elf32-fr30.c which is..
      5    Copyright (C) 1998-2017 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 	 3,			/* size (0 = byte, 1 = short, 2 = long) */
     38 	 0,			/* bitsize */
     39 	 FALSE,			/* pc_relative */
     40 	 0,			/* bitpos */
     41 	 complain_overflow_dont, /* 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   if (r_type >= (unsigned int) R_MOXIE_max)
    136     {
    137       /* xgettext:c-format */
    138       _bfd_error_handler (_("%B: invalid Moxie reloc number: %d"), abfd, r_type);
    139       r_type = 0;
    140     }
    141   cache_ptr->howto = & moxie_elf_howto_table [r_type];
    142 }
    143 
    144 /* Perform a single relocation.  By default we use the standard BFD
    146    routines, but a few relocs, we have to do them ourselves.  */
    147 
    148 static bfd_reloc_status_type
    149 moxie_final_link_relocate (reloc_howto_type *howto,
    150 			   bfd *input_bfd,
    151 			   asection *input_section,
    152 			   bfd_byte *contents,
    153 			   Elf_Internal_Rela *rel,
    154 			   bfd_vma relocation)
    155 {
    156   bfd_reloc_status_type r = bfd_reloc_ok;
    157 
    158   switch (howto->type)
    159     {
    160     default:
    161       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    162 				    contents, rel->r_offset,
    163 				    relocation, rel->r_addend);
    164     }
    165 
    166   return r;
    167 }
    168 
    169 /* Relocate an MOXIE ELF section.
    171 
    172    The RELOCATE_SECTION function is called by the new ELF backend linker
    173    to handle the relocations for a section.
    174 
    175    The relocs are always passed as Rela structures; if the section
    176    actually uses Rel structures, the r_addend field will always be
    177    zero.
    178 
    179    This function is responsible for adjusting the section contents as
    180    necessary, and (if using Rela relocs and generating a relocatable
    181    output file) adjusting the reloc addend as necessary.
    182 
    183    This function does not have to worry about setting the reloc
    184    address or the reloc symbol index.
    185 
    186    LOCAL_SYMS is a pointer to the swapped in local symbols.
    187 
    188    LOCAL_SECTIONS is an array giving the section in the input file
    189    corresponding to the st_shndx field of each local symbol.
    190 
    191    The global hash table entry for the global symbols can be found
    192    via elf_sym_hashes (input_bfd).
    193 
    194    When generating relocatable output, this function must handle
    195    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    196    going to be the section symbol corresponding to the output
    197    section, which means that the addend must be adjusted
    198    accordingly.  */
    199 
    200 static bfd_boolean
    201 moxie_elf_relocate_section (bfd *output_bfd,
    202 			    struct bfd_link_info *info,
    203 			    bfd *input_bfd,
    204 			    asection *input_section,
    205 			    bfd_byte *contents,
    206 			    Elf_Internal_Rela *relocs,
    207 			    Elf_Internal_Sym *local_syms,
    208 			    asection **local_sections)
    209 {
    210   Elf_Internal_Shdr *symtab_hdr;
    211   struct elf_link_hash_entry **sym_hashes;
    212   Elf_Internal_Rela *rel;
    213   Elf_Internal_Rela *relend;
    214 
    215   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    216   sym_hashes = elf_sym_hashes (input_bfd);
    217   relend     = relocs + input_section->reloc_count;
    218 
    219   for (rel = relocs; rel < relend; rel ++)
    220     {
    221       reloc_howto_type *howto;
    222       unsigned long r_symndx;
    223       Elf_Internal_Sym *sym;
    224       asection *sec;
    225       struct elf_link_hash_entry *h;
    226       bfd_vma relocation;
    227       bfd_reloc_status_type r;
    228       const char *name;
    229       int r_type;
    230 
    231       r_type = ELF32_R_TYPE (rel->r_info);
    232       r_symndx = ELF32_R_SYM (rel->r_info);
    233       howto  = moxie_elf_howto_table + r_type;
    234       h      = NULL;
    235       sym    = NULL;
    236       sec    = NULL;
    237 
    238       if (r_symndx < symtab_hdr->sh_info)
    239 	{
    240 	  sym = local_syms + r_symndx;
    241 	  sec = local_sections [r_symndx];
    242 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    243 
    244 	  name = bfd_elf_string_from_elf_section
    245 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
    246 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
    247 	}
    248       else
    249 	{
    250 	  bfd_boolean unresolved_reloc, warned, ignored;
    251 
    252 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    253 				   r_symndx, symtab_hdr, sym_hashes,
    254 				   h, sec, relocation,
    255 				   unresolved_reloc, warned, ignored);
    256 
    257 	  name = h->root.root.string;
    258 	}
    259 
    260       if (sec != NULL && discarded_section (sec))
    261 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    262 					 rel, 1, relend, howto, 0, contents);
    263 
    264       if (bfd_link_relocatable (info))
    265 	continue;
    266 
    267       r = moxie_final_link_relocate (howto, input_bfd, input_section,
    268 				     contents, rel, relocation);
    269 
    270       if (r != bfd_reloc_ok)
    271 	{
    272 	  const char * msg = NULL;
    273 
    274 	  switch (r)
    275 	    {
    276 	    case bfd_reloc_overflow:
    277 	      (*info->callbacks->reloc_overflow)
    278 		(info, (h ? &h->root : NULL), name, howto->name,
    279 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    280 	      break;
    281 
    282 	    case bfd_reloc_undefined:
    283 	      (*info->callbacks->undefined_symbol)
    284 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
    285 	      break;
    286 
    287 	    case bfd_reloc_outofrange:
    288 	      msg = _("internal error: out of range error");
    289 	      break;
    290 
    291 	    case bfd_reloc_notsupported:
    292 	      msg = _("internal error: unsupported relocation error");
    293 	      break;
    294 
    295 	    case bfd_reloc_dangerous:
    296 	      msg = _("internal error: dangerous relocation");
    297 	      break;
    298 
    299 	    default:
    300 	      msg = _("internal error: unknown error");
    301 	      break;
    302 	    }
    303 
    304 	  if (msg)
    305 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
    306 					 input_section, rel->r_offset);
    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 (bfd_link_relocatable (info))
    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_MACHINE_ALT1        EM_MOXIE_OLD
    377 #define ELF_MAXPAGESIZE		0x1
    378 
    379 #define TARGET_BIG_SYM          moxie_elf32_be_vec
    380 #define TARGET_BIG_NAME		"elf32-bigmoxie"
    381 #define TARGET_LITTLE_SYM       moxie_elf32_le_vec
    382 #define TARGET_LITTLE_NAME	"elf32-littlemoxie"
    383 
    384 #define elf_info_to_howto_rel			NULL
    385 #define elf_info_to_howto			moxie_info_to_howto_rela
    386 #define elf_backend_relocate_section		moxie_elf_relocate_section
    387 #define elf_backend_gc_mark_hook		moxie_elf_gc_mark_hook
    388 #define elf_backend_check_relocs                moxie_elf_check_relocs
    389 
    390 #define elf_backend_can_gc_sections		1
    391 #define elf_backend_rela_normal			1
    392 
    393 #define bfd_elf32_bfd_reloc_type_lookup		moxie_reloc_type_lookup
    394 #define bfd_elf32_bfd_reloc_name_lookup		moxie_reloc_name_lookup
    395 
    396 #include "elf32-target.h"
    397