Home | History | Annotate | Line # | Download | only in bfd
elf32-moxie.c revision 1.9
      1 /* moxie-specific support for 32-bit ELF.
      2    Copyright (C) 2009-2020 Free Software Foundation, Inc.
      3 
      4    Copied from elf32-fr30.c which is..
      5    Copyright (C) 1998-2020 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 bfd_boolean
    128 moxie_info_to_howto_rela (bfd *abfd,
    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 (_("%pB: unsupported relocation type %#x"),
    139 			  abfd, r_type);
    140       bfd_set_error (bfd_error_bad_value);
    141       return FALSE;
    142     }
    143   cache_ptr->howto = & moxie_elf_howto_table [r_type];
    144   return TRUE;
    145 }
    146 
    147 /* Perform a single relocation.  By default we use the standard BFD
    149    routines, but a few relocs, we have to do them ourselves.  */
    150 
    151 static bfd_reloc_status_type
    152 moxie_final_link_relocate (reloc_howto_type *howto,
    153 			   bfd *input_bfd,
    154 			   asection *input_section,
    155 			   bfd_byte *contents,
    156 			   Elf_Internal_Rela *rel,
    157 			   bfd_vma relocation)
    158 {
    159   bfd_reloc_status_type r = bfd_reloc_ok;
    160 
    161   switch (howto->type)
    162     {
    163     default:
    164       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    165 				    contents, rel->r_offset,
    166 				    relocation, rel->r_addend);
    167     }
    168 
    169   return r;
    170 }
    171 
    172 /* Relocate an MOXIE ELF section.
    174 
    175    The RELOCATE_SECTION function is called by the new ELF backend linker
    176    to handle the relocations for a section.
    177 
    178    The relocs are always passed as Rela structures; if the section
    179    actually uses Rel structures, the r_addend field will always be
    180    zero.
    181 
    182    This function is responsible for adjusting the section contents as
    183    necessary, and (if using Rela relocs and generating a relocatable
    184    output file) adjusting the reloc addend as necessary.
    185 
    186    This function does not have to worry about setting the reloc
    187    address or the reloc symbol index.
    188 
    189    LOCAL_SYMS is a pointer to the swapped in local symbols.
    190 
    191    LOCAL_SECTIONS is an array giving the section in the input file
    192    corresponding to the st_shndx field of each local symbol.
    193 
    194    The global hash table entry for the global symbols can be found
    195    via elf_sym_hashes (input_bfd).
    196 
    197    When generating relocatable output, this function must handle
    198    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    199    going to be the section symbol corresponding to the output
    200    section, which means that the addend must be adjusted
    201    accordingly.  */
    202 
    203 static bfd_boolean
    204 moxie_elf_relocate_section (bfd *output_bfd,
    205 			    struct bfd_link_info *info,
    206 			    bfd *input_bfd,
    207 			    asection *input_section,
    208 			    bfd_byte *contents,
    209 			    Elf_Internal_Rela *relocs,
    210 			    Elf_Internal_Sym *local_syms,
    211 			    asection **local_sections)
    212 {
    213   Elf_Internal_Shdr *symtab_hdr;
    214   struct elf_link_hash_entry **sym_hashes;
    215   Elf_Internal_Rela *rel;
    216   Elf_Internal_Rela *relend;
    217 
    218   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    219   sym_hashes = elf_sym_hashes (input_bfd);
    220   relend     = relocs + input_section->reloc_count;
    221 
    222   for (rel = relocs; rel < relend; rel ++)
    223     {
    224       reloc_howto_type *howto;
    225       unsigned long r_symndx;
    226       Elf_Internal_Sym *sym;
    227       asection *sec;
    228       struct elf_link_hash_entry *h;
    229       bfd_vma relocation;
    230       bfd_reloc_status_type r;
    231       const char *name;
    232       int r_type;
    233 
    234       r_type = ELF32_R_TYPE (rel->r_info);
    235       r_symndx = ELF32_R_SYM (rel->r_info);
    236       howto  = moxie_elf_howto_table + r_type;
    237       h      = NULL;
    238       sym    = NULL;
    239       sec    = NULL;
    240 
    241       if (r_symndx < symtab_hdr->sh_info)
    242 	{
    243 	  sym = local_syms + r_symndx;
    244 	  sec = local_sections [r_symndx];
    245 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    246 
    247 	  name = bfd_elf_string_from_elf_section
    248 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
    249 	  name = name == NULL ? bfd_section_name (sec) : name;
    250 	}
    251       else
    252 	{
    253 	  bfd_boolean unresolved_reloc, warned, ignored;
    254 
    255 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    256 				   r_symndx, symtab_hdr, sym_hashes,
    257 				   h, sec, relocation,
    258 				   unresolved_reloc, warned, ignored);
    259 
    260 	  name = h->root.root.string;
    261 	}
    262 
    263       if (sec != NULL && discarded_section (sec))
    264 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    265 					 rel, 1, relend, howto, 0, contents);
    266 
    267       if (bfd_link_relocatable (info))
    268 	continue;
    269 
    270       r = moxie_final_link_relocate (howto, input_bfd, input_section,
    271 				     contents, rel, relocation);
    272 
    273       if (r != bfd_reloc_ok)
    274 	{
    275 	  const char * msg = NULL;
    276 
    277 	  switch (r)
    278 	    {
    279 	    case bfd_reloc_overflow:
    280 	      (*info->callbacks->reloc_overflow)
    281 		(info, (h ? &h->root : NULL), name, howto->name,
    282 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    283 	      break;
    284 
    285 	    case bfd_reloc_undefined:
    286 	      (*info->callbacks->undefined_symbol)
    287 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
    288 	      break;
    289 
    290 	    case bfd_reloc_outofrange:
    291 	      msg = _("internal error: out of range error");
    292 	      break;
    293 
    294 	    case bfd_reloc_notsupported:
    295 	      msg = _("internal error: unsupported relocation error");
    296 	      break;
    297 
    298 	    case bfd_reloc_dangerous:
    299 	      msg = _("internal error: dangerous relocation");
    300 	      break;
    301 
    302 	    default:
    303 	      msg = _("internal error: unknown error");
    304 	      break;
    305 	    }
    306 
    307 	  if (msg)
    308 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
    309 					 input_section, rel->r_offset);
    310 	}
    311     }
    312 
    313   return TRUE;
    314 }
    315 
    316 /* Return the section that should be marked against GC for a given
    318    relocation.  */
    319 
    320 static asection *
    321 moxie_elf_gc_mark_hook (asection *sec,
    322 			struct bfd_link_info *info,
    323 			Elf_Internal_Rela *rel,
    324 			struct elf_link_hash_entry *h,
    325 			Elf_Internal_Sym *sym)
    326 {
    327   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
    328 }
    329 
    330 /* Look through the relocs for a section during the first phase.
    331    Since we don't do .gots or .plts, we just need to consider the
    332    virtual table relocs for gc.  */
    333 
    334 static bfd_boolean
    335 moxie_elf_check_relocs (bfd *abfd,
    336 			struct bfd_link_info *info,
    337 			asection *sec,
    338 			const Elf_Internal_Rela *relocs)
    339 {
    340   Elf_Internal_Shdr *symtab_hdr;
    341   struct elf_link_hash_entry **sym_hashes;
    342   const Elf_Internal_Rela *rel;
    343   const Elf_Internal_Rela *rel_end;
    344 
    345   if (bfd_link_relocatable (info))
    346     return TRUE;
    347 
    348   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    349   sym_hashes = elf_sym_hashes (abfd);
    350 
    351   rel_end = relocs + sec->reloc_count;
    352   for (rel = relocs; rel < rel_end; rel++)
    353     {
    354       struct elf_link_hash_entry *h;
    355       unsigned long r_symndx;
    356 
    357       r_symndx = ELF32_R_SYM (rel->r_info);
    358       if (r_symndx < symtab_hdr->sh_info)
    359 	h = NULL;
    360       else
    361 	{
    362 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    363 	  while (h->root.type == bfd_link_hash_indirect
    364 		 || h->root.type == bfd_link_hash_warning)
    365 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    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_MACHINE_ALT1	EM_MOXIE_OLD
    376 #define ELF_MAXPAGESIZE		0x1
    377 
    378 #define TARGET_BIG_SYM		moxie_elf32_be_vec
    379 #define TARGET_BIG_NAME		"elf32-bigmoxie"
    380 #define TARGET_LITTLE_SYM	moxie_elf32_le_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