Home | History | Annotate | Download | only in bfd
      1 /* BFD back-end for Renesas H8/500 COFF binaries.
      2    Copyright (C) 1993-2016 Free Software Foundation, Inc.
      3    Contributed by Cygnus Support.
      4    Written by Steve Chamberlain, <sac (at) cygnus.com>.
      5 
      6    This file is part of BFD, the Binary File Descriptor library.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21    MA 02110-1301, USA.  */
     22 
     23 #include "sysdep.h"
     24 #include "bfd.h"
     25 #include "libbfd.h"
     26 #include "bfdlink.h"
     27 #include "coff/h8500.h"
     28 #include "coff/internal.h"
     29 #include "libcoff.h"
     30 
     31 
     32 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
     33 
     34 static reloc_howto_type r_imm8 =
     35 HOWTO (R_H8500_IMM8, 0, 1, 8, FALSE, 0,
     36        complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff, FALSE);
     37 
     38 static reloc_howto_type r_imm16 =
     39 HOWTO (R_H8500_IMM16, 0, 1, 16, FALSE, 0,
     40        complain_overflow_bitfield, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff, FALSE);
     41 
     42 static reloc_howto_type r_imm24 =
     43 HOWTO (R_H8500_IMM24, 0, 1, 24, FALSE, 0,
     44        complain_overflow_bitfield, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff, FALSE);
     45 
     46 static reloc_howto_type r_imm32 =
     47 HOWTO (R_H8500_IMM32, 0, 1, 32, FALSE, 0,
     48        complain_overflow_bitfield, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff, FALSE);
     49 
     50 static reloc_howto_type r_high8 =
     51 HOWTO (R_H8500_HIGH8, 0, 1, 8, FALSE, 0,
     52        complain_overflow_dont, 0, "r_high8", TRUE, 0x000000ff, 0x000000ff, FALSE);
     53 
     54 static reloc_howto_type r_low16 =
     55 HOWTO (R_H8500_LOW16, 0, 1, 16, FALSE, 0,
     56        complain_overflow_dont, 0, "r_low16", TRUE, 0x0000ffff, 0x0000ffff, FALSE);
     57 
     58 static reloc_howto_type r_pcrel8 =
     59 HOWTO (R_H8500_PCREL8, 0, 1, 8, TRUE, 0, complain_overflow_signed, 0, "r_pcrel8", TRUE, 0, 0, TRUE);
     60 
     61 static reloc_howto_type r_pcrel16 =
     62 HOWTO (R_H8500_PCREL16, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "r_pcrel16", TRUE, 0, 0, TRUE);
     63 
     64 static reloc_howto_type r_high16 =
     65 HOWTO (R_H8500_HIGH16, 0, 1, 8, FALSE, 0,
     66        complain_overflow_dont, 0, "r_high16", TRUE, 0x000ffff, 0x0000ffff, FALSE);
     67 
     68 /* Turn a howto into a reloc number.  */
     70 
     71 static int
     72 coff_h8500_select_reloc (reloc_howto_type *howto)
     73 {
     74   return howto->type;
     75 }
     76 
     77 #define SELECT_RELOC(x,howto) x.r_type = coff_h8500_select_reloc(howto)
     78 
     79 #define BADMAG(x) H8500BADMAG(x)
     80 #define H8500 1			/* Customize coffcode.h */
     81 
     82 #define __A_MAGIC_SET__
     83 
     84 /* Code to swap in the reloc.  */
     85 #define SWAP_IN_RELOC_OFFSET	H_GET_32
     86 #define SWAP_OUT_RELOC_OFFSET	H_PUT_32
     87 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
     88   dst->r_stuff[0] = 'S'; \
     89   dst->r_stuff[1] = 'C';
     90 
     91 /* Code to turn a r_type into a howto ptr, uses the above howto table.  */
     92 
     93 static void
     94 rtype2howto (arelent * internal, struct internal_reloc *dst)
     95 {
     96   switch (dst->r_type)
     97     {
     98     default:
     99       internal->howto = NULL;
    100       break;
    101     case R_H8500_IMM8:
    102       internal->howto = &r_imm8;
    103       break;
    104     case R_H8500_IMM16:
    105       internal->howto = &r_imm16;
    106       break;
    107     case R_H8500_IMM24:
    108       internal->howto = &r_imm24;
    109       break;
    110     case R_H8500_IMM32:
    111       internal->howto = &r_imm32;
    112       break;
    113     case R_H8500_PCREL8:
    114       internal->howto = &r_pcrel8;
    115       break;
    116     case R_H8500_PCREL16:
    117       internal->howto = &r_pcrel16;
    118       break;
    119     case R_H8500_HIGH8:
    120       internal->howto = &r_high8;
    121       break;
    122     case R_H8500_HIGH16:
    123       internal->howto = &r_high16;
    124       break;
    125     case R_H8500_LOW16:
    126       internal->howto = &r_low16;
    127       break;
    128     }
    129 }
    130 
    131 #define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
    132 
    133 /* Perform any necessary magic to the addend in a reloc entry.  */
    134 
    135 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
    136  cache_ptr->addend =  ext_reloc.r_offset;
    137 
    138 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
    139  reloc_processing(relent, reloc, symbols, abfd, section)
    140 
    141 static void
    142 reloc_processing (arelent * relent,
    143 		  struct internal_reloc *reloc,
    144 		  asymbol ** symbols,
    145 		  bfd * abfd,
    146 		  asection * section)
    147 {
    148   relent->address = reloc->r_vaddr;
    149   rtype2howto (relent, reloc);
    150 
    151   if (reloc->r_symndx > 0)
    152     relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
    153   else
    154     relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
    155 
    156   relent->addend = reloc->r_offset;
    157   relent->address -= section->vma;
    158 }
    159 
    160 static void
    161 extra_case (bfd *in_abfd,
    162 	    struct bfd_link_info *link_info,
    163 	    struct bfd_link_order *link_order,
    164 	    arelent *reloc,
    165 	    bfd_byte *data,
    166 	    unsigned int *src_ptr,
    167 	    unsigned int *dst_ptr)
    168 {
    169   bfd_byte *d = data+*dst_ptr;
    170   asection *input_section = link_order->u.indirect.section;
    171 
    172   switch (reloc->howto->type)
    173     {
    174     case R_H8500_IMM8:
    175       bfd_put_8 (in_abfd,
    176 		 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
    177 		 d);
    178       (*dst_ptr) += 1;
    179       (*src_ptr) += 1;
    180       break;
    181 
    182     case R_H8500_HIGH8:
    183       bfd_put_8 (in_abfd,
    184 		 (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
    185 		  >> 16),
    186 		 d);
    187       (*dst_ptr) += 1;
    188       (*src_ptr) += 1;
    189       break;
    190 
    191     case R_H8500_IMM16:
    192       bfd_put_16 (in_abfd,
    193 		  bfd_coff_reloc16_get_value (reloc, link_info, input_section),
    194 		  d);
    195       (*dst_ptr) += 2;
    196       (*src_ptr) += 2;
    197       break;
    198 
    199     case R_H8500_LOW16:
    200       bfd_put_16 (in_abfd,
    201 		  bfd_coff_reloc16_get_value (reloc, link_info, input_section),
    202 		  d);
    203 
    204       (*dst_ptr) += 2;
    205       (*src_ptr) += 2;
    206       break;
    207 
    208     case R_H8500_HIGH16:
    209       bfd_put_16 (in_abfd,
    210 		  (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
    211 		   >> 16),
    212 		  d);
    213 
    214       (*dst_ptr) += 2;
    215       (*src_ptr) += 2;
    216       break;
    217 
    218     case R_H8500_IMM24:
    219       {
    220 	int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
    221 	int o = bfd_get_32 (in_abfd, data+ *dst_ptr -1);
    222 	v = (v & 0x00ffffff) | (o & 0xff00000);
    223 	bfd_put_32 (in_abfd, (bfd_vma) v, data  + *dst_ptr -1);
    224 	(*dst_ptr) += 3;
    225 	(*src_ptr) += 3;
    226       }
    227       break;
    228     case R_H8500_IMM32:
    229       {
    230 	int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
    231 	bfd_put_32 (in_abfd, (bfd_vma) v, data  + *dst_ptr);
    232 	(*dst_ptr) += 4;
    233 	(*src_ptr) += 4;
    234       }
    235       break;
    236 
    237     case R_H8500_PCREL8:
    238       {
    239 	bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
    240 						  input_section);
    241 	bfd_vma dot = (*dst_ptr
    242 		       + input_section->output_offset
    243 		       + input_section->output_section->vma);
    244 	int gap = dst - dot - 1; /* -1 since were in the odd byte of the
    245 				    word and the pc's been incremented.  */
    246 
    247 	if (gap > 128 || gap < -128)
    248 	  (*link_info->callbacks->reloc_overflow)
    249 	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
    250 	     reloc->howto->name, reloc->addend, input_section->owner,
    251 	     input_section, reloc->address);
    252 
    253 	bfd_put_8 (in_abfd, gap, data + *dst_ptr);
    254 	(*dst_ptr)++;
    255 	(*src_ptr)++;
    256 	break;
    257       }
    258     case R_H8500_PCREL16:
    259       {
    260 	bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
    261 						  input_section);
    262 	bfd_vma dot = (*dst_ptr
    263 		       + input_section->output_offset
    264 		       + input_section->output_section->vma);
    265 	int gap = dst - dot - 1; /* -1 since were in the odd byte of the
    266 				    word and the pc's been incremented.  */
    267 
    268 	if (gap > 32767 || gap < -32768)
    269 	  (*link_info->callbacks->reloc_overflow)
    270 	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
    271 	     reloc->howto->name, reloc->addend, input_section->owner,
    272 	     input_section, reloc->address);
    273 
    274 	bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
    275 	(*dst_ptr) += 2;
    276 	(*src_ptr) += 2;
    277 	break;
    278       }
    279 
    280     default:
    281       abort ();
    282     }
    283 }
    284 
    285 #define coff_reloc16_extra_cases extra_case
    286 
    287 #ifndef bfd_pe_print_pdata
    288 #define bfd_pe_print_pdata	NULL
    289 #endif
    290 
    291 #include "coffcode.h"
    292 
    293 #undef  coff_bfd_get_relocated_section_contents
    294 #undef coff_bfd_relax_section
    295 #define coff_bfd_get_relocated_section_contents \
    296   bfd_coff_reloc16_get_relocated_section_contents
    297 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
    298 
    299 CREATE_BIG_COFF_TARGET_VEC (h8500_coff_vec, "coff-h8500", 0, 0, '_', NULL, COFF_SWAP_TABLE)
    300