Home | History | Annotate | Line # | Download | only in bfd
coff-z80.c revision 1.5
      1  1.1  christos /* BFD back-end for Zilog Z80 COFF binaries.
      2  1.5  christos    Copyright (C) 2005-2016 Free Software Foundation, Inc.
      3  1.1  christos    Contributed by Arnold Metselaar <arnold_m (at) operamail.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.3  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 "bfdlink.h"
     26  1.1  christos #include "coff/z80.h"
     27  1.1  christos #include "coff/internal.h"
     28  1.1  christos #include "libcoff.h"
     29  1.1  christos 
     30  1.1  christos #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
     31  1.1  christos 
     32  1.1  christos static reloc_howto_type r_imm32 =
     33  1.1  christos HOWTO (R_IMM32, 0, 2, 32, FALSE, 0,
     34  1.1  christos        complain_overflow_dont, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff,
     35  1.1  christos        FALSE);
     36  1.1  christos 
     37  1.1  christos static reloc_howto_type r_imm24 =
     38  1.1  christos HOWTO (R_IMM24, 0, 1, 24, FALSE, 0,
     39  1.1  christos        complain_overflow_dont, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff,
     40  1.1  christos        FALSE);
     41  1.1  christos 
     42  1.1  christos static reloc_howto_type r_imm16 =
     43  1.1  christos HOWTO (R_IMM16, 0, 1, 16, FALSE, 0,
     44  1.1  christos        complain_overflow_dont, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff,
     45  1.1  christos        FALSE);
     46  1.1  christos 
     47  1.1  christos static reloc_howto_type r_imm8 =
     48  1.1  christos HOWTO (R_IMM8, 0, 0, 8, FALSE, 0,
     49  1.1  christos        complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff,
     50  1.1  christos        FALSE);
     51  1.1  christos 
     52  1.1  christos static reloc_howto_type r_jr =
     53  1.3  christos HOWTO (R_JR, 0, 0, 8, TRUE, 0,
     54  1.1  christos        complain_overflow_signed, 0, "r_jr", FALSE, 0, 0xFF,
     55  1.1  christos        FALSE);
     56  1.1  christos 
     57  1.1  christos static reloc_howto_type r_off8 =
     58  1.3  christos HOWTO (R_OFF8, 0, 0, 8, FALSE, 0,
     59  1.1  christos        complain_overflow_signed, 0,"r_off8", FALSE, 0, 0xff,
     60  1.1  christos        FALSE);
     61  1.1  christos 
     62  1.1  christos 
     63  1.1  christos #define BADMAG(x) Z80BADMAG(x)
     64  1.1  christos #define Z80 1			/* Customize coffcode.h.  */
     65  1.1  christos #define __A_MAGIC_SET__
     66  1.1  christos 
     67  1.1  christos /* Code to swap in the reloc.  */
     68  1.1  christos 
     69  1.1  christos #define SWAP_IN_RELOC_OFFSET	H_GET_32
     70  1.1  christos #define SWAP_OUT_RELOC_OFFSET	H_PUT_32
     71  1.1  christos 
     72  1.1  christos #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
     73  1.1  christos   dst->r_stuff[0] = 'S'; \
     74  1.1  christos   dst->r_stuff[1] = 'C';
     75  1.1  christos 
     76  1.1  christos /* Code to turn a r_type into a howto ptr, uses the above howto table.  */
     77  1.1  christos 
     78  1.1  christos static void
     79  1.1  christos rtype2howto (arelent *internal, struct internal_reloc *dst)
     80  1.1  christos {
     81  1.1  christos   switch (dst->r_type)
     82  1.1  christos     {
     83  1.1  christos     default:
     84  1.3  christos       internal->howto = NULL;
     85  1.1  christos       break;
     86  1.1  christos     case R_IMM8:
     87  1.1  christos       internal->howto = &r_imm8;
     88  1.1  christos       break;
     89  1.1  christos     case R_IMM16:
     90  1.1  christos       internal->howto = &r_imm16;
     91  1.1  christos       break;
     92  1.1  christos     case R_IMM24:
     93  1.1  christos       internal->howto = &r_imm24;
     94  1.1  christos       break;
     95  1.1  christos     case R_IMM32:
     96  1.1  christos       internal->howto = &r_imm32;
     97  1.1  christos       break;
     98  1.1  christos     case R_JR:
     99  1.1  christos       internal->howto = &r_jr;
    100  1.1  christos       break;
    101  1.1  christos     case R_OFF8:
    102  1.1  christos       internal->howto = &r_off8;
    103  1.1  christos       break;
    104  1.1  christos     }
    105  1.1  christos }
    106  1.1  christos 
    107  1.1  christos #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
    108  1.1  christos 
    109  1.1  christos static reloc_howto_type *
    110  1.1  christos coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    111  1.1  christos 			    bfd_reloc_code_real_type code)
    112  1.1  christos {
    113  1.1  christos   switch (code)
    114  1.1  christos     {
    115  1.1  christos     case BFD_RELOC_8:		return & r_imm8;
    116  1.1  christos     case BFD_RELOC_16:		return & r_imm16;
    117  1.1  christos     case BFD_RELOC_24:		return & r_imm24;
    118  1.1  christos     case BFD_RELOC_32:		return & r_imm32;
    119  1.1  christos     case BFD_RELOC_8_PCREL:	return & r_jr;
    120  1.1  christos     case BFD_RELOC_Z80_DISP8:	return & r_off8;
    121  1.1  christos     default:			BFD_FAIL ();
    122  1.1  christos       return NULL;
    123  1.1  christos     }
    124  1.1  christos }
    125  1.1  christos 
    126  1.1  christos static reloc_howto_type *
    127  1.1  christos coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    128  1.1  christos 			    const char *r_name)
    129  1.1  christos {
    130  1.1  christos   if (strcasecmp (r_imm8.name, r_name) == 0)
    131  1.1  christos     return &r_imm8;
    132  1.1  christos   if (strcasecmp (r_imm16.name, r_name) == 0)
    133  1.1  christos     return &r_imm16;
    134  1.1  christos   if (strcasecmp (r_imm24.name, r_name) == 0)
    135  1.1  christos     return &r_imm24;
    136  1.1  christos   if (strcasecmp (r_imm32.name, r_name) == 0)
    137  1.1  christos     return &r_imm32;
    138  1.1  christos   if (strcasecmp (r_jr.name, r_name) == 0)
    139  1.1  christos     return &r_jr;
    140  1.1  christos   if (strcasecmp (r_off8.name, r_name) == 0)
    141  1.1  christos     return &r_off8;
    142  1.1  christos 
    143  1.1  christos   return NULL;
    144  1.1  christos }
    145  1.1  christos 
    146  1.1  christos /* Perform any necessary magic to the addend in a reloc entry.  */
    147  1.1  christos 
    148  1.1  christos #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
    149  1.1  christos  cache_ptr->addend =  ext_reloc.r_offset;
    150  1.1  christos 
    151  1.1  christos #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
    152  1.1  christos  reloc_processing(relent, reloc, symbols, abfd, section)
    153  1.1  christos 
    154  1.1  christos static void
    155  1.1  christos reloc_processing (arelent *relent,
    156  1.1  christos                   struct internal_reloc *reloc,
    157  1.1  christos                   asymbol **symbols,
    158  1.1  christos                   bfd *abfd,
    159  1.1  christos                   asection *section)
    160  1.1  christos {
    161  1.1  christos   relent->address = reloc->r_vaddr;
    162  1.1  christos   rtype2howto (relent, reloc);
    163  1.1  christos 
    164  1.1  christos   if (reloc->r_symndx > 0)
    165  1.1  christos     relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
    166  1.1  christos   else
    167  1.1  christos     relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
    168  1.1  christos 
    169  1.1  christos   relent->addend = reloc->r_offset;
    170  1.1  christos   relent->address -= section->vma;
    171  1.1  christos }
    172  1.1  christos 
    173  1.1  christos static void
    174  1.1  christos extra_case (bfd *in_abfd,
    175  1.1  christos             struct bfd_link_info *link_info,
    176  1.1  christos             struct bfd_link_order *link_order,
    177  1.1  christos             arelent *reloc,
    178  1.1  christos             bfd_byte *data,
    179  1.1  christos             unsigned int *src_ptr,
    180  1.1  christos             unsigned int *dst_ptr)
    181  1.1  christos {
    182  1.1  christos   asection * input_section = link_order->u.indirect.section;
    183  1.1  christos   int val;
    184  1.1  christos 
    185  1.1  christos   switch (reloc->howto->type)
    186  1.1  christos     {
    187  1.1  christos     case R_OFF8:
    188  1.1  christos 	val = bfd_coff_reloc16_get_value (reloc, link_info,
    189  1.1  christos 					   input_section);
    190  1.1  christos 	if (val>127 || val<-128) /* Test for overflow.  */
    191  1.5  christos 	  (*link_info->callbacks->reloc_overflow)
    192  1.5  christos 	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
    193  1.5  christos 	     reloc->howto->name, reloc->addend, input_section->owner,
    194  1.5  christos 	     input_section, reloc->address);
    195  1.5  christos 
    196  1.1  christos 	bfd_put_8 (in_abfd, val, data + *dst_ptr);
    197  1.1  christos 	(*dst_ptr) += 1;
    198  1.1  christos 	(*src_ptr) += 1;
    199  1.1  christos       break;
    200  1.1  christos 
    201  1.1  christos     case R_IMM8:
    202  1.1  christos       val = bfd_get_8 ( in_abfd, data+*src_ptr)
    203  1.1  christos 	+ bfd_coff_reloc16_get_value (reloc, link_info, input_section);
    204  1.1  christos       bfd_put_8 (in_abfd, val, data + *dst_ptr);
    205  1.1  christos       (*dst_ptr) += 1;
    206  1.1  christos       (*src_ptr) += 1;
    207  1.1  christos       break;
    208  1.1  christos 
    209  1.1  christos     case R_IMM16:
    210  1.1  christos       val = bfd_get_16 ( in_abfd, data+*src_ptr)
    211  1.1  christos 	+ bfd_coff_reloc16_get_value (reloc, link_info, input_section);
    212  1.1  christos       bfd_put_16 (in_abfd, val, data + *dst_ptr);
    213  1.1  christos       (*dst_ptr) += 2;
    214  1.1  christos       (*src_ptr) += 2;
    215  1.1  christos       break;
    216  1.1  christos 
    217  1.1  christos     case R_IMM24:
    218  1.1  christos       val = bfd_get_16 ( in_abfd, data+*src_ptr)
    219  1.1  christos 	+ (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16)
    220  1.1  christos 	+ bfd_coff_reloc16_get_value (reloc, link_info, input_section);
    221  1.1  christos       bfd_put_16 (in_abfd, val, data + *dst_ptr);
    222  1.1  christos       bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
    223  1.1  christos       (*dst_ptr) += 3;
    224  1.1  christos       (*src_ptr) += 3;
    225  1.1  christos       break;
    226  1.1  christos 
    227  1.1  christos     case R_IMM32:
    228  1.1  christos       val = bfd_get_32 ( in_abfd, data+*src_ptr)
    229  1.1  christos 	+ bfd_coff_reloc16_get_value (reloc, link_info, input_section);
    230  1.1  christos       bfd_put_32 (in_abfd, val, data + *dst_ptr);
    231  1.1  christos       (*dst_ptr) += 4;
    232  1.1  christos       (*src_ptr) += 4;
    233  1.1  christos       break;
    234  1.1  christos 
    235  1.1  christos     case R_JR:
    236  1.1  christos       {
    237  1.1  christos 	bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
    238  1.1  christos 						  input_section);
    239  1.1  christos 	bfd_vma dot = (*dst_ptr
    240  1.1  christos 		       + input_section->output_offset
    241  1.1  christos 		       + input_section->output_section->vma);
    242  1.1  christos 	int gap = dst - dot - 1;  /* -1, Since the offset is relative
    243  1.1  christos 				     to the value of PC after reading
    244  1.1  christos 				     the offset.  */
    245  1.1  christos 
    246  1.1  christos 	if (gap >= 128 || gap < -128)
    247  1.5  christos 	  (*link_info->callbacks->reloc_overflow)
    248  1.5  christos 	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
    249  1.5  christos 	     reloc->howto->name, reloc->addend, input_section->owner,
    250  1.5  christos 	     input_section, reloc->address);
    251  1.5  christos 
    252  1.1  christos 	bfd_put_8 (in_abfd, gap, data + *dst_ptr);
    253  1.1  christos 	(*dst_ptr)++;
    254  1.1  christos 	(*src_ptr)++;
    255  1.1  christos 	break;
    256  1.1  christos       }
    257  1.1  christos 
    258  1.1  christos     default:
    259  1.1  christos       abort ();
    260  1.1  christos     }
    261  1.1  christos }
    262  1.1  christos 
    263  1.1  christos #define coff_reloc16_extra_cases    extra_case
    264  1.1  christos #define coff_bfd_reloc_type_lookup  coff_z80_reloc_type_lookup
    265  1.1  christos #define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
    266  1.1  christos 
    267  1.1  christos #ifndef bfd_pe_print_pdata
    268  1.1  christos #define bfd_pe_print_pdata	NULL
    269  1.1  christos #endif
    270  1.1  christos 
    271  1.1  christos #include "coffcode.h"
    272  1.1  christos 
    273  1.1  christos #undef  coff_bfd_get_relocated_section_contents
    274  1.1  christos #define coff_bfd_get_relocated_section_contents \
    275  1.1  christos   bfd_coff_reloc16_get_relocated_section_contents
    276  1.1  christos 
    277  1.1  christos #undef  coff_bfd_relax_section
    278  1.1  christos #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
    279  1.1  christos 
    280  1.3  christos CREATE_LITTLE_COFF_TARGET_VEC (z80_coff_vec, "coff-z80", 0,
    281  1.3  christos 			       SEC_CODE | SEC_DATA, '\0', NULL,
    282  1.1  christos 			       COFF_SWAP_TABLE)
    283  1.1  christos 
    284