Home | History | Annotate | Line # | Download | only in bfd
elf32-epiphany.c revision 1.1.1.4
      1      1.1  christos /* Adapteva epiphany specific support for 32-bit ELF
      2  1.1.1.4  christos    Copyright (C) 2000-2018 Free Software Foundation, Inc.
      3      1.1  christos    Contributed by Embecosm on behalf of Adapteva, Inc.
      4      1.1  christos 
      5      1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      6      1.1  christos 
      7      1.1  christos    This program is free software; you can redistribute it and/or modify
      8      1.1  christos    it under the terms of the GNU General Public License as published by
      9      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10      1.1  christos    (at your option) any later version.
     11      1.1  christos 
     12      1.1  christos    This program is distributed in the hope that it will be useful,
     13      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  christos    GNU General Public License for more details.
     16      1.1  christos 
     17      1.1  christos    You should have received a copy of the GNU General Public License
     18      1.1  christos    along with this program; if not, write to the Free Software
     19      1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20      1.1  christos    MA 02110-1301, USA.  */
     21      1.1  christos 
     22      1.1  christos #include "sysdep.h"
     23      1.1  christos #include "bfd.h"
     24      1.1  christos #include "libbfd.h"
     25      1.1  christos #include "elf-bfd.h"
     26      1.1  christos #include "elf/epiphany.h"
     27      1.1  christos #include "libiberty.h"
     28      1.1  christos 
     29      1.1  christos /* Struct used to pass miscellaneous paramaters which
     30      1.1  christos    helps to avoid overly long parameter lists.  */
     31      1.1  christos struct misc
     32      1.1  christos {
     33      1.1  christos   Elf_Internal_Shdr *  symtab_hdr;
     34      1.1  christos   Elf_Internal_Rela *  irelbase;
     35  1.1.1.4  christos   bfd_byte *	       contents;
     36      1.1  christos   Elf_Internal_Sym *   isymbuf;
     37      1.1  christos };
     38      1.1  christos 
     39      1.1  christos struct epiphany_opcode
     40      1.1  christos {
     41      1.1  christos   unsigned short opcode;
     42      1.1  christos   unsigned short mask;
     43      1.1  christos };
     44      1.1  christos 
     45      1.1  christos static bfd_boolean epiphany_relaxed = FALSE;
     46      1.1  christos 
     47      1.1  christos /* Relocation tables.  */
     48      1.1  christos static reloc_howto_type epiphany_elf_howto_table [] =
     49      1.1  christos {
     50      1.1  christos #define AHOW(t,rs,s,bs,pr,bp,co,name,sm,dm)	\
     51  1.1.1.4  christos     HOWTO(t,			/* type */ \
     52  1.1.1.4  christos 	  rs,			/* rightshift */ \
     53  1.1.1.4  christos 	  s,			/* size (0 = byte, 1 = short, 2 = long) */ \
     54  1.1.1.4  christos 	  bs,			/* bitsize */ \
     55  1.1.1.4  christos 	  pr,			/* pc_relative */ \
     56  1.1.1.4  christos 	  bp,			/* bitpos */ \
     57      1.1  christos 	  co,			/* complain_on_overflow */	       \
     58      1.1  christos 	  bfd_elf_generic_reloc,/* special_function */ \
     59  1.1.1.4  christos 	  name,			/* name */ \
     60  1.1.1.4  christos 	  FALSE,		/* partial_inplace */ \
     61  1.1.1.4  christos 	  sm,			/* src_mask */ \
     62  1.1.1.4  christos 	  dm,			/* dst_mask */ \
     63  1.1.1.4  christos 	  pr)			/* pcrel_offset */
     64      1.1  christos 
     65      1.1  christos   /* This reloc does nothing.  */
     66  1.1.1.4  christos   AHOW (R_EPIPHANY_NONE,    0, 3,0, FALSE, 0, complain_overflow_dont,	  "R_EPIPHANY_NONE",	    0,		0),
     67      1.1  christos 
     68      1.1  christos   /* 8 bit absolute (not likely) */
     69  1.1.1.4  christos   AHOW (R_EPIPHANY_8,	    0, 0, 8, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_8",	0x000000ff, 0x000000ff),
     70      1.1  christos   /* 16 bit absolute */
     71  1.1.1.4  christos   AHOW (R_EPIPHANY_16,	    0, 1,16, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_16",	0x0000ffff, 0x00ff1fe0),
     72      1.1  christos   /* A 32 bit absolute relocation.  */
     73  1.1.1.4  christos   AHOW (R_EPIPHANY_32,	    0, 2,32, FALSE, 0, complain_overflow_dont,	   "R_EPIPHANY_32",	0xffffffff, 0xffffffff),
     74      1.1  christos 
     75      1.1  christos   /*  8 bit relative relocation */
     76      1.1  christos   HOWTO ( R_EPIPHANY_8_PCREL,  0, 0,  8, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE),
     77      1.1  christos   /* 16 bit relative relocation */
     78      1.1  christos   HOWTO ( R_EPIPHANY_16_PCREL, 0, 1, 16, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE),
     79      1.1  christos   /* 32 bit relative relocation */
     80      1.1  christos   HOWTO ( R_EPIPHANY_32_PCREL, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE),
     81      1.1  christos 
     82      1.1  christos   /* 8 bit pc-relative relocation */
     83  1.1.1.4  christos   AHOW (R_EPIPHANY_SIMM8,   1, 0, 8,  TRUE, 8, complain_overflow_signed,   "R_EPIPHANY_SIMM8",	 0x000000ff, 0x0000ff00),
     84      1.1  christos   /* 24 bit pc-relative relocation */
     85  1.1.1.4  christos   AHOW (R_EPIPHANY_SIMM24,  1, 2,24,  TRUE, 8, complain_overflow_signed,   "R_EPIPHANY_SIMM24",	 0x00ffffff, 0xffffff00),
     86      1.1  christos 
     87      1.1  christos   /* %HIGH(EA) */
     88  1.1.1.4  christos   AHOW (R_EPIPHANY_HIGH,    0, 2,16, FALSE, 0, complain_overflow_dont,	   "R_EPIPHANY_HIGH",	 0x0ff01fe0, 0x0ff01fe0),
     89      1.1  christos 
     90      1.1  christos   /* %LOW(EA) */
     91  1.1.1.4  christos   AHOW (R_EPIPHANY_LOW,	    0, 2,16, FALSE, 0, complain_overflow_dont,	"R_EPIPHANY_LOW",     0x0ff01fe0, 0x0ff01fe0),
     92      1.1  christos 
     93      1.1  christos   /* simm11 */
     94  1.1.1.4  christos   AHOW (R_EPIPHANY_SIMM11,  0, 2,11, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_SIMM11",	 0x00ff0380, 0x00ff0380),
     95      1.1  christos   /* imm12 - sign-magnitude */
     96  1.1.1.4  christos   AHOW (R_EPIPHANY_IMM11,   0, 2,11, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_IMM12",	 0x00ff0380, 0x00ff0380),
     97      1.1  christos   /* imm8 */
     98  1.1.1.4  christos   AHOW (R_EPIPHANY_IMM8,    0, 1, 8, FALSE, 8, complain_overflow_signed,   "R_EPIPHANY_IMM8",	 0x0000ff00, 0x0000ff00)
     99      1.1  christos 
    100      1.1  christos 
    101      1.1  christos };
    102      1.1  christos #undef AHOW
    103      1.1  christos 
    104      1.1  christos /* Map BFD reloc types to EPIPHANY ELF reloc types.  */
    105      1.1  christos 
    106      1.1  christos static reloc_howto_type *
    107      1.1  christos epiphany_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
    108      1.1  christos 			    bfd_reloc_code_real_type code)
    109      1.1  christos {
    110      1.1  christos   /* Note that the epiphany_elf_howto_table is indxed by the R_
    111      1.1  christos      constants.  Thus, the order that the howto records appear in the
    112      1.1  christos      table *must* match the order of the relocation types defined in
    113      1.1  christos      include/elf/epiphany.h.  */
    114      1.1  christos 
    115      1.1  christos   switch (code)
    116      1.1  christos     {
    117      1.1  christos     case BFD_RELOC_NONE:
    118      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_NONE];
    119      1.1  christos 
    120      1.1  christos     case BFD_RELOC_EPIPHANY_SIMM8:
    121      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM8];
    122      1.1  christos     case BFD_RELOC_EPIPHANY_SIMM24:
    123      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM24];
    124      1.1  christos 
    125      1.1  christos     case BFD_RELOC_8_PCREL:
    126      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8_PCREL];
    127      1.1  christos     case BFD_RELOC_16_PCREL:
    128      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16_PCREL];
    129      1.1  christos     case BFD_RELOC_32_PCREL:
    130      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32_PCREL];
    131      1.1  christos 
    132      1.1  christos     case BFD_RELOC_8:
    133      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8];
    134      1.1  christos     case BFD_RELOC_16:
    135      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16];
    136      1.1  christos     case BFD_RELOC_32:
    137      1.1  christos       return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32];
    138      1.1  christos 
    139      1.1  christos     case BFD_RELOC_EPIPHANY_HIGH:
    140      1.1  christos       return & epiphany_elf_howto_table[ (int) R_EPIPHANY_HIGH];
    141      1.1  christos     case BFD_RELOC_EPIPHANY_LOW:
    142      1.1  christos       return & epiphany_elf_howto_table[ (int) R_EPIPHANY_LOW];
    143      1.1  christos 
    144      1.1  christos     case BFD_RELOC_EPIPHANY_SIMM11:
    145      1.1  christos       return & epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM11];
    146      1.1  christos     case BFD_RELOC_EPIPHANY_IMM11:
    147      1.1  christos       return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM11];
    148      1.1  christos 
    149      1.1  christos     case BFD_RELOC_EPIPHANY_IMM8:
    150      1.1  christos       return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM8];
    151      1.1  christos 
    152      1.1  christos     default:
    153      1.1  christos       /* Pacify gcc -Wall.  */
    154      1.1  christos       return NULL;
    155      1.1  christos     }
    156      1.1  christos   return NULL;
    157      1.1  christos }
    158      1.1  christos 
    159      1.1  christos static reloc_howto_type *
    160      1.1  christos epiphany_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
    161      1.1  christos {
    162      1.1  christos   unsigned int i;
    163      1.1  christos 
    164      1.1  christos   for (i = 0; i < ARRAY_SIZE (epiphany_elf_howto_table); i++)
    165      1.1  christos     if (epiphany_elf_howto_table[i].name != NULL
    166      1.1  christos 	&& strcasecmp (epiphany_elf_howto_table[i].name, r_name) == 0)
    167      1.1  christos       return &epiphany_elf_howto_table[i];
    168      1.1  christos 
    169      1.1  christos   return NULL;
    170      1.1  christos }
    171      1.1  christos 
    172      1.1  christos #define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000)
    173      1.1  christos #define BASEADDR(SEC)	((SEC)->output_section->vma + (SEC)->output_offset)
    174      1.1  christos 
    175      1.1  christos /* This function handles relaxing for the epiphany.
    176      1.1  christos    Dummy placeholder for future optimizations.  */
    177      1.1  christos 
    178      1.1  christos static bfd_boolean
    179      1.1  christos epiphany_elf_relax_section (bfd *abfd, asection *sec,
    180      1.1  christos 			    struct bfd_link_info *link_info,
    181      1.1  christos 			    bfd_boolean *again)
    182      1.1  christos {
    183      1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    184      1.1  christos   Elf_Internal_Rela *internal_relocs;
    185      1.1  christos   bfd_byte *contents = NULL;
    186      1.1  christos   Elf_Internal_Sym *isymbuf = NULL;
    187      1.1  christos   static asection * first_section = NULL;
    188      1.1  christos   static unsigned long search_addr;
    189      1.1  christos   static unsigned long page_start = 0;
    190      1.1  christos   static unsigned long page_end = 0;
    191      1.1  christos   static unsigned int pass = 0;
    192      1.1  christos   static bfd_boolean new_pass = FALSE;
    193      1.1  christos   static bfd_boolean changed = FALSE;
    194      1.1  christos   struct misc misc ATTRIBUTE_UNUSED;
    195      1.1  christos   asection *stab;
    196      1.1  christos 
    197      1.1  christos   /* Assume nothing changes.  */
    198      1.1  christos   *again = FALSE;
    199      1.1  christos 
    200      1.1  christos   if (first_section == NULL)
    201      1.1  christos     {
    202      1.1  christos       epiphany_relaxed = TRUE;
    203      1.1  christos       first_section = sec;
    204      1.1  christos     }
    205      1.1  christos 
    206      1.1  christos   if (first_section == sec)
    207      1.1  christos     {
    208      1.1  christos       pass++;
    209      1.1  christos       new_pass = TRUE;
    210      1.1  christos     }
    211      1.1  christos 
    212      1.1  christos   /* We don't have to do anything for a relocatable link,
    213      1.1  christos      if this section does not have relocs, or if this is
    214      1.1  christos      not a code section.  */
    215  1.1.1.2  christos   if (bfd_link_relocatable (link_info)
    216      1.1  christos       || (sec->flags & SEC_RELOC) == 0
    217      1.1  christos       || sec->reloc_count == 0
    218      1.1  christos       || (sec->flags & SEC_CODE) == 0)
    219      1.1  christos     return TRUE;
    220      1.1  christos 
    221      1.1  christos   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    222      1.1  christos 
    223      1.1  christos   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
    224      1.1  christos 					       link_info->keep_memory);
    225      1.1  christos   if (internal_relocs == NULL)
    226      1.1  christos     goto error_return;
    227      1.1  christos 
    228      1.1  christos   /* Make sure the stac.rela stuff gets read in.  */
    229      1.1  christos   stab = bfd_get_section_by_name (abfd, ".stab");
    230      1.1  christos 
    231      1.1  christos   if (stab)
    232      1.1  christos     {
    233      1.1  christos       /* So stab does exits.  */
    234      1.1  christos       Elf_Internal_Rela * irelbase ATTRIBUTE_UNUSED;
    235      1.1  christos 
    236      1.1  christos       irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
    237      1.1  christos 					    link_info->keep_memory);
    238      1.1  christos     }
    239      1.1  christos 
    240      1.1  christos   /* Get section contents cached copy if it exists.  */
    241      1.1  christos   if (contents == NULL)
    242      1.1  christos     {
    243      1.1  christos       /* Get cached copy if it exists.  */
    244      1.1  christos       if (elf_section_data (sec)->this_hdr.contents != NULL)
    245      1.1  christos 	contents = elf_section_data (sec)->this_hdr.contents;
    246      1.1  christos       else
    247      1.1  christos 	{
    248      1.1  christos 	  /* Go get them off disk.  */
    249      1.1  christos 	  if (!bfd_malloc_and_get_section (abfd, sec, &contents))
    250      1.1  christos 	    goto error_return;
    251      1.1  christos 	}
    252      1.1  christos     }
    253      1.1  christos 
    254      1.1  christos   /* Read this BFD's symbols cached copy if it exists.  */
    255      1.1  christos   if (isymbuf == NULL && symtab_hdr->sh_info != 0)
    256      1.1  christos     {
    257      1.1  christos       isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
    258      1.1  christos       if (isymbuf == NULL)
    259      1.1  christos 	isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
    260      1.1  christos 					symtab_hdr->sh_info, 0,
    261      1.1  christos 					NULL, NULL, NULL);
    262      1.1  christos       if (isymbuf == NULL)
    263      1.1  christos 	goto error_return;
    264      1.1  christos     }
    265      1.1  christos 
    266      1.1  christos   misc.symtab_hdr = symtab_hdr;
    267      1.1  christos   misc.isymbuf = isymbuf;
    268      1.1  christos   misc.irelbase = internal_relocs;
    269      1.1  christos   misc.contents = contents;
    270      1.1  christos 
    271      1.1  christos   /* This is where all the relaxation actually get done.  */
    272      1.1  christos   if ((pass == 1) || (new_pass && !changed))
    273      1.1  christos     {
    274      1.1  christos       /* On the first pass we simply search for the lowest page that
    275      1.1  christos 	 we havn't relaxed yet. Note that the pass count is reset
    276      1.1  christos 	 each time a page is complete in order to move on to the next page.
    277      1.1  christos 	 If we can't find any more pages then we are finished.  */
    278      1.1  christos       if (new_pass)
    279      1.1  christos 	{
    280      1.1  christos 	  pass = 1;
    281      1.1  christos 	  new_pass = FALSE;
    282      1.1  christos 	  changed = TRUE; /* Pre-initialize to break out of pass 1.  */
    283      1.1  christos 	  search_addr = 0xFFFFFFFF;
    284      1.1  christos 	}
    285      1.1  christos 
    286      1.1  christos       if ((BASEADDR (sec) + sec->size < search_addr)
    287      1.1  christos 	  && (BASEADDR (sec) + sec->size > page_end))
    288      1.1  christos 	{
    289      1.1  christos 	  if (BASEADDR (sec) <= page_end)
    290      1.1  christos 	    search_addr = page_end + 1;
    291      1.1  christos 	  else
    292      1.1  christos 	    search_addr = BASEADDR (sec);
    293      1.1  christos 
    294      1.1  christos 	  /* Found a page => more work to do.  */
    295      1.1  christos 	  *again = TRUE;
    296      1.1  christos 	}
    297      1.1  christos     }
    298      1.1  christos   else
    299      1.1  christos     {
    300      1.1  christos       if (new_pass)
    301      1.1  christos 	{
    302      1.1  christos 	  new_pass = FALSE;
    303      1.1  christos 	  changed = FALSE;
    304      1.1  christos 	  page_start = PAGENO (search_addr);
    305      1.1  christos 	  page_end = page_start | 0x00003FFF;
    306      1.1  christos 	}
    307      1.1  christos 
    308      1.1  christos       /* Only process sections in range.  */
    309      1.1  christos       if ((BASEADDR (sec) + sec->size >= page_start)
    310      1.1  christos 	  && (BASEADDR (sec) <= page_end))
    311      1.1  christos 	{
    312      1.1  christos #if 0
    313      1.1  christos 	  if (!epiphany_elf_relax_section_page (abfd, sec, &changed, &misc,
    314      1.1  christos 						page_start, page_end))
    315      1.1  christos #endif
    316      1.1  christos 	    return FALSE;
    317      1.1  christos 	}
    318      1.1  christos       *again = TRUE;
    319      1.1  christos     }
    320      1.1  christos 
    321      1.1  christos   /* Perform some house keeping after relaxing the section.  */
    322      1.1  christos 
    323      1.1  christos   if (isymbuf != NULL
    324      1.1  christos       && symtab_hdr->contents != (unsigned char *) isymbuf)
    325      1.1  christos     {
    326      1.1  christos       if (! link_info->keep_memory)
    327      1.1  christos 	free (isymbuf);
    328      1.1  christos       else
    329      1.1  christos 	symtab_hdr->contents = (unsigned char *) isymbuf;
    330      1.1  christos     }
    331      1.1  christos 
    332      1.1  christos   if (contents != NULL
    333      1.1  christos       && elf_section_data (sec)->this_hdr.contents != contents)
    334      1.1  christos     {
    335      1.1  christos       if (! link_info->keep_memory)
    336      1.1  christos 	free (contents);
    337      1.1  christos       else
    338      1.1  christos 	{
    339      1.1  christos 	  /* Cache the section contents for elf_link_input_bfd.  */
    340      1.1  christos 	  elf_section_data (sec)->this_hdr.contents = contents;
    341      1.1  christos 	}
    342      1.1  christos     }
    343      1.1  christos 
    344      1.1  christos   if (internal_relocs != NULL
    345      1.1  christos       && elf_section_data (sec)->relocs != internal_relocs)
    346      1.1  christos     free (internal_relocs);
    347      1.1  christos 
    348      1.1  christos   return TRUE;
    349      1.1  christos 
    350      1.1  christos  error_return:
    351      1.1  christos   if (isymbuf != NULL
    352      1.1  christos       && symtab_hdr->contents != (unsigned char *) isymbuf)
    353      1.1  christos     free (isymbuf);
    354      1.1  christos   if (contents != NULL
    355      1.1  christos       && elf_section_data (sec)->this_hdr.contents != contents)
    356      1.1  christos     free (contents);
    357      1.1  christos   if (internal_relocs != NULL
    358      1.1  christos       && elf_section_data (sec)->relocs != internal_relocs)
    359      1.1  christos     free (internal_relocs);
    360      1.1  christos   return FALSE;
    361      1.1  christos }
    362      1.1  christos 
    363      1.1  christos /* Set the howto pointer for a EPIPHANY ELF reloc.  */
    364      1.1  christos 
    365  1.1.1.4  christos static bfd_boolean
    366  1.1.1.4  christos epiphany_info_to_howto_rela (bfd * abfd,
    367      1.1  christos 			     arelent * cache_ptr,
    368      1.1  christos 			     Elf_Internal_Rela * dst)
    369      1.1  christos {
    370      1.1  christos   unsigned int r_type;
    371      1.1  christos 
    372      1.1  christos   r_type = ELF32_R_TYPE (dst->r_info);
    373  1.1.1.2  christos   if (r_type >= (unsigned int) R_EPIPHANY_max)
    374  1.1.1.2  christos     {
    375  1.1.1.4  christos       /* xgettext:c-format */
    376  1.1.1.4  christos       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    377  1.1.1.4  christos 			  abfd, r_type);
    378  1.1.1.4  christos       bfd_set_error (bfd_error_bad_value);
    379  1.1.1.4  christos       return FALSE;
    380  1.1.1.2  christos     }
    381      1.1  christos   cache_ptr->howto = & epiphany_elf_howto_table [r_type];
    382  1.1.1.4  christos   return TRUE;
    383      1.1  christos }
    384      1.1  christos 
    385      1.1  christos /* Perform a single relocation.
    386      1.1  christos    By default we use the standard BFD routines.  */
    387      1.1  christos 
    388      1.1  christos static bfd_reloc_status_type
    389      1.1  christos epiphany_final_link_relocate (reloc_howto_type *  howto,
    390  1.1.1.4  christos 			      bfd *		  input_bfd,
    391  1.1.1.4  christos 			      asection *	  input_section,
    392  1.1.1.4  christos 			      bfd_byte *	  contents,
    393      1.1  christos 			      Elf_Internal_Rela * rel,
    394  1.1.1.4  christos 			      bfd_vma		  relocation)
    395      1.1  christos {
    396      1.1  christos   switch (howto->type)
    397      1.1  christos     {
    398      1.1  christos       /* Handle 16 bit immediates.  */
    399      1.1  christos     case R_EPIPHANY_HIGH:
    400      1.1  christos       relocation += rel->r_addend;
    401      1.1  christos       relocation >>= 16;
    402      1.1  christos       goto common;
    403      1.1  christos 
    404      1.1  christos     case R_EPIPHANY_LOW:
    405      1.1  christos       relocation += rel->r_addend;
    406      1.1  christos     common:
    407      1.1  christos       relocation = ((relocation & 0xff00L) << 12)
    408      1.1  christos 	| ((relocation & 0x00ffL) << 5);
    409      1.1  christos       /* Sanity check the address.  */
    410      1.1  christos       if (rel->r_offset > bfd_get_section_limit (input_bfd, input_section))
    411      1.1  christos 	return bfd_reloc_outofrange;
    412      1.1  christos 
    413      1.1  christos       return _bfd_relocate_contents (howto, input_bfd, relocation,
    414      1.1  christos 				     contents + rel->r_offset);
    415      1.1  christos 
    416      1.1  christos     case R_EPIPHANY_SIMM11:
    417      1.1  christos       relocation += rel->r_addend;
    418      1.1  christos       /* Check signed overflow.  */
    419      1.1  christos       if ((int)relocation > 1023 || (int)relocation < -1024)
    420      1.1  christos 	return bfd_reloc_outofrange;
    421      1.1  christos       goto disp11;
    422      1.1  christos 
    423      1.1  christos     case R_EPIPHANY_IMM11:
    424      1.1  christos       relocation += rel->r_addend;
    425      1.1  christos       if ((unsigned int) relocation > 0x7ff)
    426      1.1  christos 	return bfd_reloc_outofrange;
    427  1.1.1.4  christos       /* Fall through.  */
    428      1.1  christos     disp11:
    429  1.1.1.4  christos       relocation = (((relocation & 7) << 5)
    430  1.1.1.4  christos 		    | ((relocation & 0x7f8 ) << 13));
    431      1.1  christos       return _bfd_relocate_contents (howto, input_bfd, relocation,
    432      1.1  christos 				     contents + rel->r_offset);
    433      1.1  christos 
    434      1.1  christos       /* Pass others through.  */
    435      1.1  christos     default:
    436      1.1  christos       break;
    437      1.1  christos     }
    438      1.1  christos 
    439      1.1  christos   /* Only install relocation if above tests did not disqualify it.  */
    440      1.1  christos   return _bfd_final_link_relocate (howto, input_bfd, input_section,
    441      1.1  christos 				   contents, rel->r_offset,
    442      1.1  christos 				   relocation, rel->r_addend);
    443      1.1  christos }
    444      1.1  christos 
    445      1.1  christos /* Relocate an EPIPHANY ELF section.
    446      1.1  christos 
    447      1.1  christos    The RELOCATE_SECTION function is called by the new ELF backend linker
    448      1.1  christos    to handle the relocations for a section.
    449      1.1  christos 
    450      1.1  christos    The relocs are always passed as Rela structures; if the section
    451      1.1  christos    actually uses Rel structures, the r_addend field will always be
    452      1.1  christos    zero.
    453      1.1  christos 
    454      1.1  christos    This function is responsible for adjusting the section contents as
    455      1.1  christos    necessary, and (if using Rela relocs and generating a relocatable
    456      1.1  christos    output file) adjusting the reloc addend as necessary.
    457      1.1  christos 
    458      1.1  christos    This function does not have to worry about setting the reloc
    459      1.1  christos    address or the reloc symbol index.
    460      1.1  christos 
    461      1.1  christos    LOCAL_SYMS is a pointer to the swapped in local symbols.
    462      1.1  christos 
    463      1.1  christos    LOCAL_SECTIONS is an array giving the section in the input file
    464      1.1  christos    corresponding to the st_shndx field of each local symbol.
    465      1.1  christos 
    466      1.1  christos    The global hash table entry for the global symbols can be found
    467      1.1  christos    via elf_sym_hashes (input_bfd).
    468      1.1  christos 
    469      1.1  christos    When generating relocatable output, this function must handle
    470      1.1  christos    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    471      1.1  christos    going to be the section symbol corresponding to the output
    472      1.1  christos    section, which means that the addend must be adjusted
    473      1.1  christos    accordingly.  */
    474      1.1  christos 
    475      1.1  christos static bfd_boolean
    476      1.1  christos epiphany_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
    477      1.1  christos 			       struct bfd_link_info *info,
    478      1.1  christos 			       bfd *input_bfd,
    479      1.1  christos 			       asection *input_section,
    480      1.1  christos 			       bfd_byte *contents,
    481      1.1  christos 			       Elf_Internal_Rela *relocs,
    482      1.1  christos 			       Elf_Internal_Sym *local_syms,
    483      1.1  christos 			       asection **local_sections)
    484      1.1  christos {
    485      1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    486      1.1  christos   struct elf_link_hash_entry **sym_hashes;
    487      1.1  christos   Elf_Internal_Rela *rel;
    488      1.1  christos   Elf_Internal_Rela *relend;
    489      1.1  christos 
    490      1.1  christos   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    491      1.1  christos   sym_hashes = elf_sym_hashes (input_bfd);
    492      1.1  christos   relend     = relocs + input_section->reloc_count;
    493      1.1  christos 
    494      1.1  christos   for (rel = relocs; rel < relend; rel ++)
    495      1.1  christos     {
    496  1.1.1.4  christos       reloc_howto_type *	   howto;
    497  1.1.1.4  christos       unsigned long		   r_symndx;
    498  1.1.1.4  christos       Elf_Internal_Sym *	   sym;
    499  1.1.1.4  christos       asection *		   sec;
    500      1.1  christos       struct elf_link_hash_entry * h;
    501  1.1.1.4  christos       bfd_vma			   relocation;
    502  1.1.1.4  christos       bfd_reloc_status_type	   r;
    503  1.1.1.4  christos       const char *		   name = NULL;
    504  1.1.1.4  christos       int			   r_type ATTRIBUTE_UNUSED;
    505      1.1  christos 
    506      1.1  christos       r_type = ELF32_R_TYPE (rel->r_info);
    507      1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    508      1.1  christos       howto  = epiphany_elf_howto_table + ELF32_R_TYPE (rel->r_info);
    509      1.1  christos       h      = NULL;
    510      1.1  christos       sym    = NULL;
    511      1.1  christos       sec    = NULL;
    512      1.1  christos 
    513      1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    514      1.1  christos 	{
    515      1.1  christos 	  sym = local_syms + r_symndx;
    516      1.1  christos 	  sec = local_sections [r_symndx];
    517      1.1  christos 	  relocation = BASEADDR (sec) + sym->st_value;
    518      1.1  christos 
    519      1.1  christos 	  name = bfd_elf_string_from_elf_section
    520      1.1  christos 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
    521      1.1  christos 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
    522      1.1  christos 	}
    523      1.1  christos       else
    524      1.1  christos 	{
    525      1.1  christos 	  bfd_boolean warned ATTRIBUTE_UNUSED;
    526      1.1  christos 	  bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED;
    527  1.1.1.2  christos 	  bfd_boolean ignored ATTRIBUTE_UNUSED;
    528      1.1  christos 
    529      1.1  christos 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    530      1.1  christos 				   r_symndx, symtab_hdr, sym_hashes,
    531      1.1  christos 				   h, sec, relocation,
    532  1.1.1.2  christos 				   unresolved_reloc, warned, ignored);
    533      1.1  christos 
    534      1.1  christos 	  name = h->root.root.string;
    535      1.1  christos 	}
    536      1.1  christos 
    537      1.1  christos       if (sec != NULL && discarded_section (sec))
    538      1.1  christos 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    539      1.1  christos 					 rel, 1, relend, howto, 0, contents);
    540      1.1  christos 
    541  1.1.1.2  christos       if (bfd_link_relocatable (info))
    542      1.1  christos 	continue;
    543      1.1  christos 
    544      1.1  christos       /* Finally, the sole EPIPHANY-specific part.  */
    545      1.1  christos       r = epiphany_final_link_relocate (howto, input_bfd, input_section,
    546      1.1  christos 				     contents, rel, relocation);
    547      1.1  christos 
    548      1.1  christos       if (r != bfd_reloc_ok)
    549      1.1  christos 	{
    550      1.1  christos 	  const char * msg = NULL;
    551      1.1  christos 
    552      1.1  christos 	  switch (r)
    553      1.1  christos 	    {
    554      1.1  christos 	    case bfd_reloc_overflow:
    555  1.1.1.3  christos 	      (*info->callbacks->reloc_overflow)
    556      1.1  christos 		(info, (h ? &h->root : NULL), name, howto->name,
    557      1.1  christos 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    558      1.1  christos 	      break;
    559      1.1  christos 
    560      1.1  christos 	    case bfd_reloc_undefined:
    561  1.1.1.3  christos 	      (*info->callbacks->undefined_symbol)
    562      1.1  christos 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
    563      1.1  christos 	      break;
    564      1.1  christos 
    565      1.1  christos 	    case bfd_reloc_outofrange:
    566      1.1  christos 	      msg = _("internal error: out of range error");
    567      1.1  christos 	      break;
    568      1.1  christos 
    569      1.1  christos 	      /* This is how epiphany_final_link_relocate tells us of a
    570      1.1  christos 		 non-kosher reference between insn & data address spaces.  */
    571      1.1  christos 	    case bfd_reloc_notsupported:
    572      1.1  christos 	      if (sym != NULL) /* Only if it's not an unresolved symbol.  */
    573      1.1  christos 		 msg = _("unsupported relocation between data/insn address spaces");
    574      1.1  christos 	      break;
    575      1.1  christos 
    576      1.1  christos 	    case bfd_reloc_dangerous:
    577      1.1  christos 	      msg = _("internal error: dangerous relocation");
    578      1.1  christos 	      break;
    579      1.1  christos 
    580      1.1  christos 	    default:
    581      1.1  christos 	      msg = _("internal error: unknown error");
    582      1.1  christos 	      break;
    583      1.1  christos 	    }
    584      1.1  christos 
    585      1.1  christos 	  if (msg)
    586  1.1.1.3  christos 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
    587  1.1.1.3  christos 					 input_section, rel->r_offset);
    588      1.1  christos 	}
    589      1.1  christos     }
    590      1.1  christos 
    591      1.1  christos   return TRUE;
    592      1.1  christos }
    593      1.1  christos 
    594      1.1  christos /* We only have a little-endian target.  */
    595  1.1.1.2  christos #define TARGET_LITTLE_SYM	 epiphany_elf32_vec
    596      1.1  christos #define TARGET_LITTLE_NAME  "elf32-epiphany"
    597      1.1  christos 
    598      1.1  christos #define ELF_ARCH	 bfd_arch_epiphany
    599      1.1  christos #define ELF_MACHINE_CODE EM_ADAPTEVA_EPIPHANY
    600      1.1  christos 
    601      1.1  christos #define ELF_MAXPAGESIZE  0x8000 /* No pages on the EPIPHANY.  */
    602      1.1  christos 
    603      1.1  christos #define elf_info_to_howto_rel			NULL
    604      1.1  christos #define elf_info_to_howto			epiphany_info_to_howto_rela
    605      1.1  christos 
    606  1.1.1.4  christos #define elf_backend_can_gc_sections		1
    607      1.1  christos #define elf_backend_rela_normal			1
    608      1.1  christos #define elf_backend_relocate_section		epiphany_elf_relocate_section
    609      1.1  christos 
    610      1.1  christos #define elf_symbol_leading_char			'_'
    611      1.1  christos #define bfd_elf32_bfd_reloc_type_lookup		epiphany_reloc_type_lookup
    612      1.1  christos #define bfd_elf32_bfd_reloc_name_lookup		epiphany_reloc_name_lookup
    613      1.1  christos #define bfd_elf32_bfd_relax_section		epiphany_elf_relax_section
    614      1.1  christos 
    615      1.1  christos #include "elf32-target.h"
    616