Back to index

cell-binutils  2.17cvs20070401
elf32-arc.c
Go to the documentation of this file.
00001 /* ARC-specific support for 32-bit ELF
00002    Copyright 1994, 1995, 1997, 1999, 2001, 2002, 2005, 2007
00003    Free Software Foundation, Inc.
00004    Contributed by Doug Evans (dje@cygnus.com).
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00021    MA 02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "sysdep.h"
00025 #include "libbfd.h"
00026 #include "elf-bfd.h"
00027 #include "elf/arc.h"
00028 #include "libiberty.h"
00029 
00030 /* Try to minimize the amount of space occupied by relocation tables
00031    on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
00032 
00033 #define USE_REL      1
00034 
00035 static bfd_reloc_status_type
00036 arc_elf_b22_pcrel (bfd * abfd,
00037                  arelent * reloc_entry,
00038                  asymbol * symbol,
00039                  void * data,
00040                  asection * input_section,
00041                  bfd * output_bfd,
00042                  char ** error_message)
00043 {
00044   /* If linking, back up the final symbol address by the address of the
00045      reloc.  This cannot be accomplished by setting the pcrel_offset
00046      field to TRUE, as bfd_install_relocation will detect this and refuse
00047      to install the offset in the first place, but bfd_perform_relocation
00048      will still insist on removing it.  */
00049   if (output_bfd == NULL)
00050     reloc_entry->addend -= reloc_entry->address;
00051 
00052   /* Fall through to the default elf reloc handler.  */
00053   return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
00054                             input_section, output_bfd, error_message);
00055 }
00056 
00057 static reloc_howto_type elf_arc_howto_table[] =
00058 {
00059   /* This reloc does nothing.  */
00060   HOWTO (R_ARC_NONE,        /* Type.  */
00061         0,                  /* Rightshift.  */
00062         2,                  /* Size (0 = byte, 1 = short, 2 = long).  */
00063         32,                 /* Bitsize.  */
00064         FALSE,                     /* PC_relative.  */
00065         0,                  /* Bitpos.  */
00066         complain_overflow_bitfield, /* Complain_on_overflow.  */
00067         bfd_elf_generic_reloc,     /* Special_function.  */
00068         "R_ARC_NONE",              /* Name.  */
00069         TRUE,               /* Partial_inplace.  */
00070         0,                  /* Src_mask.  */
00071         0,                  /* Dst_mask.  */
00072         FALSE),             /* PCrel_offset.  */
00073 
00074   /* A standard 32 bit relocation.  */
00075   HOWTO (R_ARC_32,          /* Type.  */
00076         0,                  /* Rightshift.  */
00077         2,                  /* Size (0 = byte, 1 = short, 2 = long).  */
00078         32,                 /* Bitsize.  */
00079         FALSE,                     /* PC_relative.  */
00080         0,                  /* Bitpos.  */
00081         complain_overflow_bitfield, /* Complain_on_overflow.  */
00082         bfd_elf_generic_reloc,     /* Special_function.  */
00083         "R_ARC_32",         /* Name.  */
00084         TRUE,               /* Partial_inplace.  */
00085         0xffffffff,         /* Src_mask.  */
00086         0xffffffff,         /* Dst_mask.  */
00087         FALSE),             /* PCrel_offset.  */
00088 
00089   /* A 26 bit absolute branch, right shifted by 2.  */
00090   HOWTO (R_ARC_B26,         /* Type.  */
00091         2,                  /* Rightshift.  */
00092         2,                  /* Size (0 = byte, 1 = short, 2 = long).  */
00093         26,                 /* Bitsize.  */
00094         FALSE,                     /* PC_relative.  */
00095         0,                  /* Bitpos.  */
00096         complain_overflow_bitfield, /* Complain_on_overflow.  */
00097         bfd_elf_generic_reloc,     /* Special_function.  */
00098         "R_ARC_B26",        /* Name.  */
00099         TRUE,               /* Partial_inplace.  */
00100         0x00ffffff,         /* Src_mask.  */
00101         0x00ffffff,         /* Dst_mask.  */
00102         FALSE),             /* PCrel_offset.  */
00103 
00104   /* A relative 22 bit branch; bits 21-2 are stored in bits 26-7.  */
00105   HOWTO (R_ARC_B22_PCREL,   /* Type.  */
00106         2,                  /* Rightshift.  */
00107         2,                  /* Size (0 = byte, 1 = short, 2 = long).  */
00108         22,                 /* Bitsize.  */
00109         TRUE,               /* PC_relative.  */
00110         7,                  /* Bitpos.  */
00111         complain_overflow_signed, /* Complain_on_overflow.  */
00112         arc_elf_b22_pcrel,  /* Special_function.  */
00113         "R_ARC_B22_PCREL",  /* Name.  */
00114         TRUE,               /* Partial_inplace.  */
00115         0x07ffff80,         /* Src_mask.  */
00116         0x07ffff80,         /* Dst_mask.  */
00117         FALSE),             /* PCrel_offset.  */
00118 };
00119 
00120 /* Map BFD reloc types to ARC ELF reloc types.  */
00121 
00122 struct arc_reloc_map
00123 {
00124   bfd_reloc_code_real_type bfd_reloc_val;
00125   unsigned char elf_reloc_val;
00126 };
00127 
00128 static const struct arc_reloc_map arc_reloc_map[] =
00129 {
00130   { BFD_RELOC_NONE, R_ARC_NONE, },
00131   { BFD_RELOC_32, R_ARC_32 },
00132   { BFD_RELOC_CTOR, R_ARC_32 },
00133   { BFD_RELOC_ARC_B26, R_ARC_B26 },
00134   { BFD_RELOC_ARC_B22_PCREL, R_ARC_B22_PCREL },
00135 };
00136 
00137 static reloc_howto_type *
00138 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00139                              bfd_reloc_code_real_type code)
00140 {
00141   unsigned int i;
00142 
00143   for (i = ARRAY_SIZE (arc_reloc_map); i--;)
00144     if (arc_reloc_map[i].bfd_reloc_val == code)
00145       return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val;
00146 
00147   return NULL;
00148 }
00149 
00150 static reloc_howto_type *
00151 bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00152                              const char *r_name)
00153 {
00154   unsigned int i;
00155 
00156   for (i = 0;
00157        i < sizeof (elf_arc_howto_table) / sizeof (elf_arc_howto_table[0]);
00158        i++)
00159     if (elf_arc_howto_table[i].name != NULL
00160        && strcasecmp (elf_arc_howto_table[i].name, r_name) == 0)
00161       return &elf_arc_howto_table[i];
00162 
00163   return NULL;
00164 }
00165 
00166 /* Set the howto pointer for an ARC ELF reloc.  */
00167 
00168 static void
00169 arc_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
00170                      arelent *cache_ptr,
00171                      Elf_Internal_Rela *dst)
00172 {
00173   unsigned int r_type;
00174 
00175   r_type = ELF32_R_TYPE (dst->r_info);
00176   BFD_ASSERT (r_type < (unsigned int) R_ARC_max);
00177   cache_ptr->howto = &elf_arc_howto_table[r_type];
00178 }
00179 
00180 /* Set the right machine number for an ARC ELF file.  */
00181 
00182 static bfd_boolean
00183 arc_elf_object_p (bfd *abfd)
00184 {
00185   unsigned int mach = bfd_mach_arc_6;
00186 
00187   if (elf_elfheader(abfd)->e_machine == EM_ARC)
00188     {
00189       unsigned long arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH;
00190 
00191       switch (arch)
00192        {
00193        case E_ARC_MACH_ARC5:
00194          mach = bfd_mach_arc_5;
00195          break;
00196        default:
00197        case E_ARC_MACH_ARC6:
00198          mach = bfd_mach_arc_6;
00199          break;
00200        case E_ARC_MACH_ARC7:
00201          mach = bfd_mach_arc_7;
00202          break;
00203        case E_ARC_MACH_ARC8:
00204          mach = bfd_mach_arc_8;
00205          break;
00206        }
00207     }
00208   return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach);
00209 }
00210 
00211 /* The final processing done just before writing out an ARC ELF object file.
00212    This gets the ARC architecture right based on the machine number.  */
00213 
00214 static void
00215 arc_elf_final_write_processing (bfd *abfd,
00216                             bfd_boolean linker ATTRIBUTE_UNUSED)
00217 {
00218   unsigned long val;
00219 
00220   switch (bfd_get_mach (abfd))
00221     {
00222     case bfd_mach_arc_5:
00223       val = E_ARC_MACH_ARC5;
00224       break;
00225     default:
00226     case bfd_mach_arc_6:
00227       val = E_ARC_MACH_ARC6;
00228       break;
00229     case bfd_mach_arc_7:
00230       val = E_ARC_MACH_ARC7;
00231       break;
00232     case bfd_mach_arc_8:
00233       val = E_ARC_MACH_ARC8;
00234       break;
00235     }
00236   elf_elfheader (abfd)->e_flags &=~ EF_ARC_MACH;
00237   elf_elfheader (abfd)->e_flags |= val;
00238 }
00239 
00240 #define TARGET_LITTLE_SYM   bfd_elf32_littlearc_vec
00241 #define TARGET_LITTLE_NAME  "elf32-littlearc"
00242 #define TARGET_BIG_SYM      bfd_elf32_bigarc_vec
00243 #define TARGET_BIG_NAME         "elf32-bigarc"
00244 #define ELF_ARCH            bfd_arch_arc
00245 #define ELF_MACHINE_CODE    EM_ARC
00246 #define ELF_MAXPAGESIZE     0x1000
00247 
00248 #define elf_info_to_howto                   0
00249 #define elf_info_to_howto_rel               arc_info_to_howto_rel
00250 #define elf_backend_object_p                arc_elf_object_p
00251 #define elf_backend_final_write_processing  arc_elf_final_write_processing
00252 
00253 #include "elf32-target.h"