Home | History | Annotate | Download | only in bfd
      1 /* ARC-specific support for 32-bit ELF
      2    Copyright (C) 1994-2014 Free Software Foundation, Inc.
      3    Contributed by Doug Evans (dje (at) cygnus.com).
      4 
      5    This file is part of BFD, the Binary File Descriptor library.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 #include "sysdep.h"
     23 #include "bfd.h"
     24 #include "libbfd.h"
     25 #include "elf-bfd.h"
     26 #include "elf/arc.h"
     27 #include "libiberty.h"
     28 
     29 /* Try to minimize the amount of space occupied by relocation tables
     30    on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
     31 
     32 #define USE_REL	1
     33 
     34 static bfd_reloc_status_type
     35 arc_elf_b22_pcrel (bfd * abfd,
     36 		   arelent * reloc_entry,
     37 		   asymbol * symbol,
     38 		   void * data,
     39 		   asection * input_section,
     40 		   bfd * output_bfd,
     41 		   char ** error_message)
     42 {
     43   /* If linking, back up the final symbol address by the address of the
     44      reloc.  This cannot be accomplished by setting the pcrel_offset
     45      field to TRUE, as bfd_install_relocation will detect this and refuse
     46      to install the offset in the first place, but bfd_perform_relocation
     47      will still insist on removing it.  */
     48   if (output_bfd == NULL)
     49     reloc_entry->addend -= reloc_entry->address;
     50 
     51   /* Fall through to the default elf reloc handler.  */
     52   return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
     53 				input_section, output_bfd, error_message);
     54 }
     55 
     56 static reloc_howto_type elf_arc_howto_table[] =
     57 {
     58   /* This reloc does nothing.  */
     59   HOWTO (R_ARC_NONE,		/* Type.  */
     60 	 0,			/* Rightshift.  */
     61 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
     62 	 32,			/* Bitsize.  */
     63 	 FALSE,			/* PC_relative.  */
     64 	 0,			/* Bitpos.  */
     65 	 complain_overflow_bitfield, /* Complain_on_overflow.  */
     66 	 bfd_elf_generic_reloc,	/* Special_function.  */
     67 	 "R_ARC_NONE",		/* Name.  */
     68 	 TRUE,			/* Partial_inplace.  */
     69 	 0,			/* Src_mask.  */
     70 	 0,			/* Dst_mask.  */
     71 	 FALSE),		/* PCrel_offset.  */
     72 
     73   /* A standard 32 bit relocation.  */
     74   HOWTO (R_ARC_32,		/* Type.  */
     75 	 0,			/* Rightshift.  */
     76 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
     77 	 32,			/* Bitsize.  */
     78 	 FALSE,			/* PC_relative.  */
     79 	 0,			/* Bitpos.  */
     80 	 complain_overflow_bitfield, /* Complain_on_overflow.  */
     81 	 bfd_elf_generic_reloc,	/* Special_function.  */
     82 	 "R_ARC_32",		/* Name.  */
     83 	 TRUE,			/* Partial_inplace.  */
     84 	 0xffffffff,		/* Src_mask.  */
     85 	 0xffffffff,		/* Dst_mask.  */
     86 	 FALSE),		/* PCrel_offset.  */
     87 
     88   /* A 26 bit absolute branch, right shifted by 2.  */
     89   HOWTO (R_ARC_B26,		/* Type.  */
     90 	 2,			/* Rightshift.  */
     91 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
     92 	 26,			/* Bitsize.  */
     93 	 FALSE,			/* PC_relative.  */
     94 	 0,			/* Bitpos.  */
     95 	 complain_overflow_bitfield, /* Complain_on_overflow.  */
     96 	 bfd_elf_generic_reloc,	/* Special_function.  */
     97 	 "R_ARC_B26",		/* Name.  */
     98 	 TRUE,			/* Partial_inplace.  */
     99 	 0x00ffffff,		/* Src_mask.  */
    100 	 0x00ffffff,		/* Dst_mask.  */
    101 	 FALSE),		/* PCrel_offset.  */
    102 
    103   /* A relative 22 bit branch; bits 21-2 are stored in bits 26-7.  */
    104   HOWTO (R_ARC_B22_PCREL,	/* Type.  */
    105 	 2,			/* Rightshift.  */
    106 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    107 	 22,			/* Bitsize.  */
    108 	 TRUE,			/* PC_relative.  */
    109 	 7,			/* Bitpos.  */
    110 	 complain_overflow_signed, /* Complain_on_overflow.  */
    111 	 arc_elf_b22_pcrel,	/* Special_function.  */
    112 	 "R_ARC_B22_PCREL",	/* Name.  */
    113 	 TRUE,			/* Partial_inplace.  */
    114 	 0x07ffff80,		/* Src_mask.  */
    115 	 0x07ffff80,		/* Dst_mask.  */
    116 	 FALSE),		/* PCrel_offset.  */
    117 };
    118 
    119 /* Map BFD reloc types to ARC ELF reloc types.  */
    120 
    121 struct arc_reloc_map
    122 {
    123   bfd_reloc_code_real_type bfd_reloc_val;
    124   unsigned char elf_reloc_val;
    125 };
    126 
    127 static const struct arc_reloc_map arc_reloc_map[] =
    128 {
    129   { BFD_RELOC_NONE, R_ARC_NONE, },
    130   { BFD_RELOC_32, R_ARC_32 },
    131   { BFD_RELOC_CTOR, R_ARC_32 },
    132   { BFD_RELOC_ARC_B26, R_ARC_B26 },
    133   { BFD_RELOC_ARC_B22_PCREL, R_ARC_B22_PCREL },
    134 };
    135 
    136 static reloc_howto_type *
    137 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    138 				 bfd_reloc_code_real_type code)
    139 {
    140   unsigned int i;
    141 
    142   for (i = ARRAY_SIZE (arc_reloc_map); i--;)
    143     if (arc_reloc_map[i].bfd_reloc_val == code)
    144       return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val;
    145 
    146   return NULL;
    147 }
    148 
    149 static reloc_howto_type *
    150 bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    151 				 const char *r_name)
    152 {
    153   unsigned int i;
    154 
    155   for (i = 0;
    156        i < sizeof (elf_arc_howto_table) / sizeof (elf_arc_howto_table[0]);
    157        i++)
    158     if (elf_arc_howto_table[i].name != NULL
    159 	&& strcasecmp (elf_arc_howto_table[i].name, r_name) == 0)
    160       return &elf_arc_howto_table[i];
    161 
    162   return NULL;
    163 }
    164 
    165 /* Set the howto pointer for an ARC ELF reloc.  */
    166 
    167 static void
    168 arc_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
    169 		       arelent *cache_ptr,
    170 		       Elf_Internal_Rela *dst)
    171 {
    172   unsigned int r_type;
    173 
    174   r_type = ELF32_R_TYPE (dst->r_info);
    175   BFD_ASSERT (r_type < (unsigned int) R_ARC_max);
    176   cache_ptr->howto = &elf_arc_howto_table[r_type];
    177 }
    178 
    179 /* Set the right machine number for an ARC ELF file.  */
    180 
    181 static bfd_boolean
    182 arc_elf_object_p (bfd *abfd)
    183 {
    184   unsigned int mach = bfd_mach_arc_6;
    185 
    186   if (elf_elfheader(abfd)->e_machine == EM_ARC)
    187     {
    188       unsigned long arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH;
    189 
    190       switch (arch)
    191 	{
    192 	case E_ARC_MACH_ARC5:
    193 	  mach = bfd_mach_arc_5;
    194 	  break;
    195 	default:
    196 	case E_ARC_MACH_ARC6:
    197 	  mach = bfd_mach_arc_6;
    198 	  break;
    199 	case E_ARC_MACH_ARC7:
    200 	  mach = bfd_mach_arc_7;
    201 	  break;
    202 	case E_ARC_MACH_ARC8:
    203 	  mach = bfd_mach_arc_8;
    204 	  break;
    205 	}
    206     }
    207   return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach);
    208 }
    209 
    210 /* The final processing done just before writing out an ARC ELF object file.
    211    This gets the ARC architecture right based on the machine number.  */
    212 
    213 static void
    214 arc_elf_final_write_processing (bfd *abfd,
    215 				bfd_boolean linker ATTRIBUTE_UNUSED)
    216 {
    217   unsigned long val;
    218 
    219   switch (bfd_get_mach (abfd))
    220     {
    221     case bfd_mach_arc_5:
    222       val = E_ARC_MACH_ARC5;
    223       break;
    224     default:
    225     case bfd_mach_arc_6:
    226       val = E_ARC_MACH_ARC6;
    227       break;
    228     case bfd_mach_arc_7:
    229       val = E_ARC_MACH_ARC7;
    230       break;
    231     case bfd_mach_arc_8:
    232       val = E_ARC_MACH_ARC8;
    233       break;
    234     }
    235   elf_elfheader (abfd)->e_flags &=~ EF_ARC_MACH;
    236   elf_elfheader (abfd)->e_flags |= val;
    237 }
    238 
    239 #define TARGET_LITTLE_SYM   arc_elf32_le_vec
    240 #define TARGET_LITTLE_NAME  "elf32-littlearc"
    241 #define TARGET_BIG_SYM      arc_elf32_be_vec
    242 #define TARGET_BIG_NAME	    "elf32-bigarc"
    243 #define ELF_ARCH            bfd_arch_arc
    244 #define ELF_MACHINE_CODE    EM_ARC
    245 #define ELF_MAXPAGESIZE     0x1000
    246 
    247 #define elf_info_to_howto                   0
    248 #define elf_info_to_howto_rel               arc_info_to_howto_rel
    249 #define elf_backend_object_p                arc_elf_object_p
    250 #define elf_backend_final_write_processing  arc_elf_final_write_processing
    251 
    252 #include "elf32-target.h"
    253