Home | History | Annotate | Line # | Download | only in bfd
elf32-d10v.c revision 1.3
      1  1.1  christos /* D10V-specific support for 32-bit ELF
      2  1.3  christos    Copyright (C) 1996-2015 Free Software Foundation, Inc.
      3  1.1  christos    Contributed by Martin Hunt (hunt (at) cygnus.com).
      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/d10v.h"
     27  1.1  christos 
     28  1.1  christos /* Use REL instead of RELA to save space.  */
     29  1.1  christos #define USE_REL	1
     30  1.1  christos 
     31  1.1  christos static reloc_howto_type elf_d10v_howto_table[] =
     32  1.1  christos {
     33  1.1  christos   /* This reloc does nothing.  */
     34  1.1  christos   HOWTO (R_D10V_NONE,		/* Type.  */
     35  1.1  christos 	 0,			/* Rightshift.  */
     36  1.3  christos 	 3,			/* Size (0 = byte, 1 = short, 2 = long).  */
     37  1.3  christos 	 0,			/* Bitsize.  */
     38  1.1  christos 	 FALSE,			/* PC_relative.  */
     39  1.1  christos 	 0,			/* Bitpos.  */
     40  1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
     41  1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
     42  1.1  christos 	 "R_D10V_NONE",		/* Name.  */
     43  1.1  christos 	 FALSE,			/* Partial_inplace.  */
     44  1.1  christos 	 0,			/* Src_mask.  */
     45  1.1  christos 	 0,			/* Dst_mask.  */
     46  1.1  christos 	 FALSE),		/* PCrel_offset.  */
     47  1.1  christos 
     48  1.1  christos   /* An PC Relative 10-bit relocation, shifted by 2, right container.  */
     49  1.1  christos   HOWTO (R_D10V_10_PCREL_R,	/* Type.  */
     50  1.1  christos 	 2,	                /* Rightshift.  */
     51  1.1  christos 	 2,	                /* Size (0 = byte, 1 = short, 2 = long).  */
     52  1.1  christos 	 8,	                /* Bitsize.  */
     53  1.1  christos 	 TRUE,	        	/* PC_relative.  */
     54  1.1  christos 	 0,	                /* Bitpos.  */
     55  1.1  christos 	 complain_overflow_signed, /* Complain_on_overflow.  */
     56  1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
     57  1.1  christos 	 "R_D10V_10_PCREL_R",	/* Name.  */
     58  1.1  christos 	 FALSE,	        	/* Partial_inplace.  */
     59  1.1  christos 	 0xff,			/* Src_mask.  */
     60  1.1  christos 	 0xff,   		/* Dst_mask.  */
     61  1.1  christos 	 TRUE),			/* PCrel_offset.  */
     62  1.1  christos 
     63  1.1  christos   /* An PC Relative 10-bit relocation, shifted by 2, left container.  */
     64  1.1  christos   HOWTO (R_D10V_10_PCREL_L,	/* Type.  */
     65  1.1  christos 	 2,	                /* Rightshift.  */
     66  1.1  christos 	 2,	                /* Size (0 = byte, 1 = short, 2 = long).  */
     67  1.1  christos 	 8,	                /* Bitsize.  */
     68  1.1  christos 	 TRUE,	        	/* PC_relative.  */
     69  1.1  christos 	 15,	                /* Bitpos.  */
     70  1.1  christos 	 complain_overflow_signed, /* Complain_on_overflow.  */
     71  1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
     72  1.1  christos 	 "R_D10V_10_PCREL_L",	/* Name.  */
     73  1.1  christos 	 FALSE,	        	/* Partial_inplace.  */
     74  1.1  christos 	 0x07f8000,		/* Src_mask.  */
     75  1.1  christos 	 0x07f8000,   		/* Dst_mask.  */
     76  1.1  christos 	 TRUE),			/* PCrel_offset.  */
     77  1.1  christos 
     78  1.1  christos   /* A 16 bit absolute relocation.  */
     79  1.1  christos   HOWTO (R_D10V_16,		/* Type.  */
     80  1.1  christos 	 0,			/* Rightshift.  */
     81  1.1  christos 	 1,			/* Size (0 = byte, 1 = short, 2 = long).  */
     82  1.1  christos 	 16,			/* Bitsize.  */
     83  1.1  christos 	 FALSE,			/* PC_relative.  */
     84  1.1  christos 	 0,			/* Bitpos.  */
     85  1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
     86  1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
     87  1.1  christos 	 "R_D10V_16",		/* Name.  */
     88  1.1  christos 	 FALSE,			/* Partial_inplace.  */
     89  1.1  christos 	 0xffff,		/* Src_mask.  */
     90  1.1  christos 	 0xffff,		/* Dst_mask.  */
     91  1.1  christos 	 FALSE),		/* PCrel_offset.  */
     92  1.1  christos 
     93  1.1  christos   /* An 18 bit absolute relocation, right shifted 2.  */
     94  1.1  christos   HOWTO (R_D10V_18,		/* Type.  */
     95  1.1  christos 	 2,			/* Rightshift.  */
     96  1.1  christos 	 1,			/* Size (0 = byte, 1 = short, 2 = long).  */
     97  1.1  christos 	 16,			/* Bitsize.  */
     98  1.1  christos 	 FALSE,			/* PC_relative.  */
     99  1.1  christos 	 0,			/* Bitpos.  */
    100  1.1  christos 	 complain_overflow_dont, /* Complain_on_overflow.  */
    101  1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
    102  1.1  christos 	 "R_D10V_18",		/* Name.  */
    103  1.1  christos 	 FALSE,			/* Partial_inplace.  */
    104  1.1  christos 	 0xffff,		/* Src_mask.  */
    105  1.1  christos 	 0xffff,		/* Dst_mask.  */
    106  1.1  christos 	 FALSE),		/* PCrel_offset.  */
    107  1.1  christos 
    108  1.1  christos   /* A relative 18 bit relocation, right shifted by 2.  */
    109  1.1  christos   HOWTO (R_D10V_18_PCREL,	/* Type.  */
    110  1.1  christos 	 2,			/* Rightshift.  */
    111  1.1  christos 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    112  1.1  christos 	 16,			/* Bitsize.  */
    113  1.1  christos 	 TRUE,			/* PC_relative.  */
    114  1.1  christos 	 0,			/* Bitpos.  */
    115  1.1  christos 	 complain_overflow_signed, /* Complain_on_overflow.  */
    116  1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
    117  1.1  christos 	 "R_D10V_18_PCREL",	/* Name.  */
    118  1.1  christos 	 FALSE,			/* Partial_inplace.  */
    119  1.1  christos 	 0xffff,		/* Src_mask.  */
    120  1.1  christos 	 0xffff,		/* Dst_mask.  */
    121  1.1  christos 	 TRUE),			/* PCrel_offset.  */
    122  1.1  christos 
    123  1.1  christos   /* A 32 bit absolute relocation.  */
    124  1.1  christos   HOWTO (R_D10V_32,		/* Type.  */
    125  1.1  christos 	 0,			/* Rightshift.  */
    126  1.1  christos 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    127  1.1  christos 	 32,			/* Bitsize.  */
    128  1.1  christos 	 FALSE,			/* PC_relative.  */
    129  1.1  christos 	 0,			/* Bitpos.  */
    130  1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    131  1.1  christos 	 bfd_elf_generic_reloc, /* Special_function.  */
    132  1.1  christos 	 "R_D10V_32",		/* Name.  */
    133  1.1  christos 	 FALSE,			/* Partial_inplace.  */
    134  1.1  christos 	 0xffffffff,		/* Src_mask.  */
    135  1.1  christos 	 0xffffffff,		/* Dst_mask.  */
    136  1.1  christos 	 FALSE),		/* PCrel_offset.  */
    137  1.1  christos 
    138  1.1  christos   /* GNU extension to record C++ vtable hierarchy.  */
    139  1.1  christos   HOWTO (R_D10V_GNU_VTINHERIT,	/* Type.  */
    140  1.1  christos 	 0,                     /* Rightshift.  */
    141  1.1  christos 	 2,                     /* Size (0 = byte, 1 = short, 2 = long).  */
    142  1.1  christos 	 0,                     /* Bitsize.  */
    143  1.1  christos 	 FALSE,                 /* PC_relative.  */
    144  1.1  christos 	 0,                     /* Bitpos.  */
    145  1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    146  1.1  christos 	 NULL,                  /* Special_function.  */
    147  1.1  christos 	 "R_D10V_GNU_VTINHERIT",/* Name.  */
    148  1.1  christos 	 FALSE,                 /* Partial_inplace.  */
    149  1.1  christos 	 0,                     /* Src_mask.  */
    150  1.1  christos 	 0,                     /* Dst_mask.  */
    151  1.1  christos 	 FALSE),                /* PCrel_offset.  */
    152  1.1  christos 
    153  1.1  christos   /* GNU extension to record C++ vtable member usage.  */
    154  1.1  christos   HOWTO (R_D10V_GNU_VTENTRY,    /* Type.  */
    155  1.1  christos 	 0,                     /* Rightshift.  */
    156  1.1  christos 	 2,                     /* Size (0 = byte, 1 = short, 2 = long).  */
    157  1.1  christos 	 0,                     /* Bitsize.  */
    158  1.1  christos 	 FALSE,                 /* PC_relative.  */
    159  1.1  christos 	 0,                     /* Bitpos.  */
    160  1.1  christos 	 complain_overflow_dont,/* Complain_on_overflow.  */
    161  1.1  christos 	 _bfd_elf_rel_vtable_reloc_fn,  /* Special_function.  */
    162  1.1  christos 	 "R_D10V_GNU_VTENTRY",  /* Name.  */
    163  1.1  christos 	 FALSE,                 /* Partial_inplace.  */
    164  1.1  christos 	 0,                     /* Src_mask.  */
    165  1.1  christos 	 0,                     /* Dst_mask.  */
    166  1.1  christos 	 FALSE),                /* PCrel_offset.  */
    167  1.1  christos };
    168  1.1  christos 
    169  1.1  christos /* Map BFD reloc types to D10V ELF reloc types.  */
    170  1.1  christos 
    171  1.1  christos struct d10v_reloc_map
    172  1.1  christos {
    173  1.1  christos   bfd_reloc_code_real_type bfd_reloc_val;
    174  1.1  christos   unsigned char elf_reloc_val;
    175  1.1  christos };
    176  1.1  christos 
    177  1.1  christos static const struct d10v_reloc_map d10v_reloc_map[] =
    178  1.1  christos {
    179  1.1  christos   { BFD_RELOC_NONE, R_D10V_NONE, },
    180  1.1  christos   { BFD_RELOC_D10V_10_PCREL_R, R_D10V_10_PCREL_R },
    181  1.1  christos   { BFD_RELOC_D10V_10_PCREL_L, R_D10V_10_PCREL_L },
    182  1.1  christos   { BFD_RELOC_16, R_D10V_16 },
    183  1.1  christos   { BFD_RELOC_D10V_18, R_D10V_18 },
    184  1.1  christos   { BFD_RELOC_D10V_18_PCREL, R_D10V_18_PCREL },
    185  1.1  christos   { BFD_RELOC_32, R_D10V_32 },
    186  1.1  christos   { BFD_RELOC_VTABLE_INHERIT, R_D10V_GNU_VTINHERIT },
    187  1.1  christos   { BFD_RELOC_VTABLE_ENTRY, R_D10V_GNU_VTENTRY },
    188  1.1  christos };
    189  1.1  christos 
    190  1.1  christos static reloc_howto_type *
    191  1.1  christos bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    192  1.1  christos 				 bfd_reloc_code_real_type code)
    193  1.1  christos {
    194  1.1  christos   unsigned int i;
    195  1.1  christos 
    196  1.1  christos   for (i = 0;
    197  1.1  christos        i < sizeof (d10v_reloc_map) / sizeof (struct d10v_reloc_map);
    198  1.1  christos        i++)
    199  1.1  christos     if (d10v_reloc_map[i].bfd_reloc_val == code)
    200  1.1  christos       return &elf_d10v_howto_table[d10v_reloc_map[i].elf_reloc_val];
    201  1.1  christos 
    202  1.1  christos   return NULL;
    203  1.1  christos }
    204  1.1  christos 
    205  1.1  christos static reloc_howto_type *
    206  1.1  christos bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    207  1.1  christos 				 const char *r_name)
    208  1.1  christos {
    209  1.1  christos   unsigned int i;
    210  1.1  christos 
    211  1.1  christos   for (i = 0;
    212  1.1  christos        i < sizeof (elf_d10v_howto_table) / sizeof (elf_d10v_howto_table[0]);
    213  1.1  christos        i++)
    214  1.1  christos     if (elf_d10v_howto_table[i].name != NULL
    215  1.1  christos 	&& strcasecmp (elf_d10v_howto_table[i].name, r_name) == 0)
    216  1.1  christos       return &elf_d10v_howto_table[i];
    217  1.1  christos 
    218  1.1  christos   return NULL;
    219  1.1  christos }
    220  1.1  christos 
    221  1.1  christos /* Set the howto pointer for an D10V ELF reloc.  */
    222  1.1  christos 
    223  1.1  christos static void
    224  1.1  christos d10v_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
    225  1.1  christos 			arelent *cache_ptr,
    226  1.1  christos 			Elf_Internal_Rela *dst)
    227  1.1  christos {
    228  1.1  christos   unsigned int r_type;
    229  1.1  christos 
    230  1.1  christos   r_type = ELF32_R_TYPE (dst->r_info);
    231  1.3  christos   if (r_type >= (unsigned int) R_D10V_max)
    232  1.3  christos     {
    233  1.3  christos       _bfd_error_handler (_("%B: invalid D10V reloc number: %d"), abfd, r_type);
    234  1.3  christos       r_type = 0;
    235  1.3  christos     }
    236  1.1  christos   cache_ptr->howto = &elf_d10v_howto_table[r_type];
    237  1.1  christos }
    238  1.1  christos 
    239  1.1  christos static asection *
    240  1.1  christos elf32_d10v_gc_mark_hook (asection *sec,
    241  1.1  christos 			 struct bfd_link_info *info,
    242  1.1  christos 			 Elf_Internal_Rela *rel,
    243  1.1  christos 			 struct elf_link_hash_entry *h,
    244  1.1  christos 			 Elf_Internal_Sym *sym)
    245  1.1  christos {
    246  1.1  christos   if (h != NULL)
    247  1.1  christos     switch (ELF32_R_TYPE (rel->r_info))
    248  1.1  christos       {
    249  1.1  christos       case R_D10V_GNU_VTINHERIT:
    250  1.1  christos       case R_D10V_GNU_VTENTRY:
    251  1.1  christos 	return NULL;
    252  1.1  christos       }
    253  1.1  christos 
    254  1.1  christos   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
    255  1.1  christos }
    256  1.1  christos 
    257  1.1  christos /* Look through the relocs for a section during the first phase.
    258  1.1  christos    Since we don't do .gots or .plts, we just need to consider the
    259  1.1  christos    virtual table relocs for gc.  */
    260  1.1  christos 
    261  1.1  christos static bfd_boolean
    262  1.1  christos elf32_d10v_check_relocs (bfd *abfd,
    263  1.1  christos 			 struct bfd_link_info *info,
    264  1.1  christos 			 asection *sec,
    265  1.1  christos 			 const Elf_Internal_Rela *relocs)
    266  1.1  christos {
    267  1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    268  1.1  christos   struct elf_link_hash_entry **sym_hashes;
    269  1.1  christos   const Elf_Internal_Rela *rel;
    270  1.1  christos   const Elf_Internal_Rela *rel_end;
    271  1.1  christos 
    272  1.3  christos   if (bfd_link_relocatable (info))
    273  1.1  christos     return TRUE;
    274  1.1  christos 
    275  1.1  christos   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    276  1.1  christos   sym_hashes = elf_sym_hashes (abfd);
    277  1.1  christos 
    278  1.1  christos   rel_end = relocs + sec->reloc_count;
    279  1.1  christos   for (rel = relocs; rel < rel_end; rel++)
    280  1.1  christos     {
    281  1.1  christos       struct elf_link_hash_entry *h;
    282  1.1  christos       unsigned long r_symndx;
    283  1.1  christos 
    284  1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    285  1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    286  1.1  christos         h = NULL;
    287  1.1  christos       else
    288  1.1  christos 	{
    289  1.1  christos 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    290  1.1  christos 	  while (h->root.type == bfd_link_hash_indirect
    291  1.1  christos 		 || h->root.type == bfd_link_hash_warning)
    292  1.1  christos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    293  1.3  christos 
    294  1.3  christos 	  /* PR15323, ref flags aren't set for references in the same
    295  1.3  christos 	     object.  */
    296  1.3  christos 	  h->root.non_ir_ref = 1;
    297  1.1  christos 	}
    298  1.1  christos 
    299  1.1  christos       switch (ELF32_R_TYPE (rel->r_info))
    300  1.1  christos         {
    301  1.1  christos         /* This relocation describes the C++ object vtable hierarchy.
    302  1.1  christos            Reconstruct it for later use during GC.  */
    303  1.1  christos         case R_D10V_GNU_VTINHERIT:
    304  1.1  christos           if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
    305  1.1  christos             return FALSE;
    306  1.1  christos           break;
    307  1.1  christos 
    308  1.1  christos         /* This relocation describes which C++ vtable entries are actually
    309  1.1  christos            used.  Record for later use during GC.  */
    310  1.1  christos         case R_D10V_GNU_VTENTRY:
    311  1.1  christos           BFD_ASSERT (h != NULL);
    312  1.1  christos           if (h != NULL
    313  1.1  christos               && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
    314  1.1  christos             return FALSE;
    315  1.1  christos           break;
    316  1.1  christos         }
    317  1.1  christos     }
    318  1.1  christos 
    319  1.1  christos   return TRUE;
    320  1.1  christos }
    321  1.1  christos 
    322  1.1  christos static bfd_vma
    323  1.1  christos extract_rel_addend (bfd *abfd,
    324  1.1  christos 		    bfd_byte *where,
    325  1.1  christos 		    reloc_howto_type *howto)
    326  1.1  christos {
    327  1.1  christos   bfd_vma insn, val;
    328  1.1  christos 
    329  1.1  christos   switch (howto->size)
    330  1.1  christos     {
    331  1.1  christos     case 0:
    332  1.1  christos       insn = bfd_get_8 (abfd, where);
    333  1.1  christos       break;
    334  1.1  christos     case 1:
    335  1.1  christos       insn = bfd_get_16 (abfd, where);
    336  1.1  christos       break;
    337  1.1  christos     case 2:
    338  1.1  christos       insn = bfd_get_32 (abfd, where);
    339  1.1  christos       break;
    340  1.1  christos     default:
    341  1.1  christos       abort ();
    342  1.1  christos     }
    343  1.1  christos 
    344  1.1  christos   val = (insn & howto->dst_mask) >> howto->bitpos << howto->rightshift;
    345  1.1  christos   /* We should really be testing for signed addends here, but we don't
    346  1.1  christos      have that info directly in the howto.  */
    347  1.1  christos   if (howto->pc_relative)
    348  1.1  christos     {
    349  1.1  christos       bfd_vma sign;
    350  1.1  christos       sign = howto->dst_mask & (~howto->dst_mask >> 1 | ~(-(bfd_vma) 1 >> 1));
    351  1.1  christos       sign = sign >> howto->bitpos << howto->rightshift;
    352  1.1  christos       val = (val ^ sign) - sign;
    353  1.1  christos     }
    354  1.1  christos   return val;
    355  1.1  christos }
    356  1.1  christos 
    357  1.1  christos static void
    358  1.1  christos insert_rel_addend (bfd *abfd,
    359  1.1  christos 		   bfd_byte *where,
    360  1.1  christos 		   reloc_howto_type *howto,
    361  1.1  christos 		   bfd_vma addend)
    362  1.1  christos {
    363  1.1  christos   bfd_vma insn;
    364  1.1  christos 
    365  1.1  christos   addend = (addend >> howto->rightshift << howto->bitpos) & howto->dst_mask;
    366  1.1  christos   insn = ~howto->dst_mask;
    367  1.1  christos   switch (howto->size)
    368  1.1  christos     {
    369  1.1  christos     case 0:
    370  1.1  christos       insn &= bfd_get_8 (abfd, where);
    371  1.1  christos       insn |= addend;
    372  1.1  christos       bfd_put_8 (abfd, insn, where);
    373  1.1  christos       break;
    374  1.1  christos     case 1:
    375  1.1  christos       insn &= bfd_get_16 (abfd, where);
    376  1.1  christos       insn |= addend;
    377  1.1  christos       bfd_put_16 (abfd, insn, where);
    378  1.1  christos       break;
    379  1.1  christos     case 2:
    380  1.1  christos       insn &= bfd_get_32 (abfd, where);
    381  1.1  christos       insn |= addend;
    382  1.1  christos       bfd_put_32 (abfd, insn, where);
    383  1.1  christos       break;
    384  1.1  christos     default:
    385  1.1  christos       abort ();
    386  1.1  christos     }
    387  1.1  christos }
    388  1.1  christos 
    389  1.1  christos /* Relocate a D10V ELF section.  */
    390  1.1  christos 
    391  1.1  christos static bfd_boolean
    392  1.1  christos elf32_d10v_relocate_section (bfd *output_bfd,
    393  1.1  christos 			     struct bfd_link_info *info,
    394  1.1  christos 			     bfd *input_bfd,
    395  1.1  christos 			     asection *input_section,
    396  1.1  christos 			     bfd_byte *contents,
    397  1.1  christos 			     Elf_Internal_Rela *relocs,
    398  1.1  christos 			     Elf_Internal_Sym *local_syms,
    399  1.1  christos 			     asection **local_sections)
    400  1.1  christos {
    401  1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    402  1.1  christos   struct elf_link_hash_entry **sym_hashes;
    403  1.1  christos   Elf_Internal_Rela *rel, *relend;
    404  1.1  christos   const char *name;
    405  1.1  christos 
    406  1.1  christos   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
    407  1.1  christos   sym_hashes = elf_sym_hashes (input_bfd);
    408  1.1  christos 
    409  1.1  christos   rel = relocs;
    410  1.1  christos   relend = relocs + input_section->reloc_count;
    411  1.1  christos   for (; rel < relend; rel++)
    412  1.1  christos     {
    413  1.1  christos       int r_type;
    414  1.1  christos       reloc_howto_type *howto;
    415  1.1  christos       unsigned long r_symndx;
    416  1.1  christos       Elf_Internal_Sym *sym;
    417  1.1  christos       asection *sec;
    418  1.1  christos       struct elf_link_hash_entry *h;
    419  1.1  christos       bfd_vma relocation;
    420  1.1  christos       bfd_reloc_status_type r;
    421  1.1  christos 
    422  1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    423  1.1  christos       r_type = ELF32_R_TYPE (rel->r_info);
    424  1.1  christos 
    425  1.1  christos       if (r_type == R_D10V_GNU_VTENTRY
    426  1.1  christos           || r_type == R_D10V_GNU_VTINHERIT)
    427  1.1  christos         continue;
    428  1.1  christos 
    429  1.1  christos       howto = elf_d10v_howto_table + r_type;
    430  1.1  christos       h = NULL;
    431  1.1  christos       sym = NULL;
    432  1.1  christos       sec = NULL;
    433  1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    434  1.1  christos 	{
    435  1.1  christos 	  sym = local_syms + r_symndx;
    436  1.1  christos 	  sec = local_sections[r_symndx];
    437  1.1  christos 	  relocation = (sec->output_section->vma
    438  1.1  christos 			+ sec->output_offset
    439  1.1  christos 			+ sym->st_value);
    440  1.1  christos 	  if (ELF_ST_TYPE (sym->st_info) == STT_SECTION
    441  1.1  christos 	      && ((sec->flags & SEC_MERGE) != 0
    442  1.3  christos 		  || (bfd_link_relocatable (info)
    443  1.1  christos 		      && sec->output_offset != 0)))
    444  1.1  christos 	    {
    445  1.1  christos 	      bfd_vma addend;
    446  1.1  christos 	      bfd_byte *where = contents + rel->r_offset;
    447  1.1  christos 
    448  1.1  christos 	      addend = extract_rel_addend (input_bfd, where, howto);
    449  1.1  christos 
    450  1.3  christos 	      if (bfd_link_relocatable (info))
    451  1.1  christos 		addend += sec->output_offset;
    452  1.1  christos 	      else
    453  1.1  christos 		{
    454  1.1  christos 		  asection *msec = sec;
    455  1.1  christos 		  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec,
    456  1.1  christos 						   addend);
    457  1.1  christos 		  addend -= relocation;
    458  1.1  christos 		  addend += msec->output_section->vma + msec->output_offset;
    459  1.1  christos 		}
    460  1.1  christos 	      insert_rel_addend (input_bfd, where, howto, addend);
    461  1.1  christos 	    }
    462  1.1  christos 	}
    463  1.1  christos       else
    464  1.1  christos 	{
    465  1.3  christos 	  bfd_boolean unresolved_reloc, warned, ignored;
    466  1.1  christos 
    467  1.1  christos 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    468  1.1  christos 				   r_symndx, symtab_hdr, sym_hashes,
    469  1.1  christos 				   h, sec, relocation,
    470  1.3  christos 				   unresolved_reloc, warned, ignored);
    471  1.1  christos 	}
    472  1.1  christos 
    473  1.1  christos       if (sec != NULL && discarded_section (sec))
    474  1.1  christos 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    475  1.1  christos 					 rel, 1, relend, howto, 0, contents);
    476  1.1  christos 
    477  1.3  christos       if (bfd_link_relocatable (info))
    478  1.1  christos 	continue;
    479  1.1  christos 
    480  1.1  christos       if (h != NULL)
    481  1.1  christos 	name = h->root.root.string;
    482  1.1  christos       else
    483  1.1  christos 	{
    484  1.1  christos 	  name = (bfd_elf_string_from_elf_section
    485  1.1  christos 		  (input_bfd, symtab_hdr->sh_link, sym->st_name));
    486  1.1  christos 	  if (name == NULL || *name == '\0')
    487  1.1  christos 	    name = bfd_section_name (input_bfd, sec);
    488  1.1  christos 	}
    489  1.1  christos 
    490  1.1  christos       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    491  1.1  christos                                     contents, rel->r_offset,
    492  1.1  christos                                     relocation, (bfd_vma) 0);
    493  1.1  christos 
    494  1.1  christos       if (r != bfd_reloc_ok)
    495  1.1  christos 	{
    496  1.1  christos 	  const char * msg = (const char *) 0;
    497  1.1  christos 
    498  1.1  christos 	  switch (r)
    499  1.1  christos 	    {
    500  1.1  christos 	    case bfd_reloc_overflow:
    501  1.1  christos 	      if (!((*info->callbacks->reloc_overflow)
    502  1.1  christos 		    (info, (h ? &h->root : NULL), name, howto->name,
    503  1.1  christos 		     (bfd_vma) 0, input_bfd, input_section,
    504  1.1  christos 		     rel->r_offset)))
    505  1.1  christos 		return FALSE;
    506  1.1  christos 	      break;
    507  1.1  christos 
    508  1.1  christos 	    case bfd_reloc_undefined:
    509  1.1  christos 	      if (!((*info->callbacks->undefined_symbol)
    510  1.1  christos 		    (info, name, input_bfd, input_section,
    511  1.1  christos 		     rel->r_offset, TRUE)))
    512  1.1  christos 		return FALSE;
    513  1.1  christos 	      break;
    514  1.1  christos 
    515  1.1  christos 	    case bfd_reloc_outofrange:
    516  1.1  christos 	      msg = _("internal error: out of range error");
    517  1.1  christos 	      goto common_error;
    518  1.1  christos 
    519  1.1  christos 	    case bfd_reloc_notsupported:
    520  1.1  christos 	      msg = _("internal error: unsupported relocation error");
    521  1.1  christos 	      goto common_error;
    522  1.1  christos 
    523  1.1  christos 	    case bfd_reloc_dangerous:
    524  1.1  christos 	      msg = _("internal error: dangerous error");
    525  1.1  christos 	      goto common_error;
    526  1.1  christos 
    527  1.1  christos 	    default:
    528  1.1  christos 	      msg = _("internal error: unknown error");
    529  1.1  christos 	      /* fall through */
    530  1.1  christos 
    531  1.1  christos 	    common_error:
    532  1.1  christos 	      if (!((*info->callbacks->warning)
    533  1.1  christos 		    (info, msg, name, input_bfd, input_section,
    534  1.1  christos 		     rel->r_offset)))
    535  1.1  christos 		return FALSE;
    536  1.1  christos 	      break;
    537  1.1  christos 	    }
    538  1.1  christos 	}
    539  1.1  christos     }
    540  1.1  christos 
    541  1.1  christos   return TRUE;
    542  1.1  christos }
    543  1.1  christos #define ELF_ARCH		bfd_arch_d10v
    544  1.1  christos #define ELF_MACHINE_CODE	EM_D10V
    545  1.1  christos #define ELF_MACHINE_ALT1	EM_CYGNUS_D10V
    546  1.1  christos #define ELF_MAXPAGESIZE		0x1000
    547  1.1  christos 
    548  1.3  christos #define TARGET_BIG_SYM          d10v_elf32_vec
    549  1.1  christos #define TARGET_BIG_NAME		"elf32-d10v"
    550  1.1  christos 
    551  1.1  christos #define elf_info_to_howto	             0
    552  1.1  christos #define elf_info_to_howto_rel	             d10v_info_to_howto_rel
    553  1.1  christos #define elf_backend_object_p	             0
    554  1.1  christos #define elf_backend_final_write_processing   0
    555  1.1  christos #define elf_backend_gc_mark_hook             elf32_d10v_gc_mark_hook
    556  1.1  christos #define elf_backend_check_relocs             elf32_d10v_check_relocs
    557  1.1  christos #define elf_backend_relocate_section         elf32_d10v_relocate_section
    558  1.1  christos #define elf_backend_can_gc_sections          1
    559  1.1  christos 
    560  1.1  christos #include "elf32-target.h"
    561