Back to index

cell-binutils  2.17cvs20070401
coff-z8k.c
Go to the documentation of this file.
00001 /* BFD back-end for Zilog Z800n COFF binaries.
00002    Copyright 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003,
00003    2004, 2005, 2007 Free Software Foundation, Inc.
00004    Contributed by Cygnus Support.
00005    Written by Steve Chamberlain, <sac@cygnus.com>.
00006 
00007    This file is part of BFD, the Binary File Descriptor library.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "sysdep.h"
00025 #include "libbfd.h"
00026 #include "bfdlink.h"
00027 #include "coff/z8k.h"
00028 #include "coff/internal.h"
00029 #include "libcoff.h"
00030 
00031 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
00032 
00033 static reloc_howto_type r_imm32 =
00034 HOWTO (R_IMM32, 0, 2, 32, FALSE, 0,
00035        complain_overflow_bitfield, 0, "r_imm32", TRUE, 0xffffffff,
00036        0xffffffff, FALSE);
00037 
00038 static reloc_howto_type r_imm4l =
00039 HOWTO (R_IMM4L, 0, 0, 4, FALSE, 0,
00040        complain_overflow_bitfield, 0, "r_imm4l", TRUE, 0xf, 0xf, FALSE);
00041 
00042 static reloc_howto_type r_da =
00043 HOWTO (R_IMM16, 0, 1, 16, FALSE, 0,
00044        complain_overflow_bitfield, 0, "r_da", TRUE, 0x0000ffff, 0x0000ffff,
00045        FALSE);
00046 
00047 static reloc_howto_type r_imm8 =
00048 HOWTO (R_IMM8, 0, 0, 8, FALSE, 0,
00049        complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff,
00050        FALSE);
00051 
00052 static reloc_howto_type r_rel16 =
00053 HOWTO (R_REL16, 0, 1, 16, FALSE, 0,
00054        complain_overflow_bitfield, 0, "r_rel16", TRUE, 0x0000ffff, 0x0000ffff,
00055        TRUE);
00056 
00057 static reloc_howto_type r_jr =
00058 HOWTO (R_JR, 1, 0, 8, TRUE, 0, complain_overflow_signed, 0,
00059        "r_jr", TRUE, 0xff, 0xff, TRUE);
00060 
00061 static reloc_howto_type r_disp7 =
00062 HOWTO (R_DISP7, 0, 0, 7, TRUE, 0, complain_overflow_bitfield, 0,
00063        "r_disp7", TRUE, 0x7f, 0x7f, TRUE);
00064 
00065 static reloc_howto_type r_callr =
00066 HOWTO (R_CALLR, 1, 1, 12, TRUE, 0, complain_overflow_signed, 0,
00067        "r_callr", TRUE, 0xfff, 0xfff, TRUE);
00068 
00069 #define BADMAG(x) Z8KBADMAG(x)
00070 #define Z8K 1               /* Customize coffcode.h.  */
00071 #define __A_MAGIC_SET__
00072 
00073 /* Code to swap in the reloc.  */
00074 #define SWAP_IN_RELOC_OFFSET       H_GET_32
00075 #define SWAP_OUT_RELOC_OFFSET      H_PUT_32
00076 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
00077   dst->r_stuff[0] = 'S'; \
00078   dst->r_stuff[1] = 'C';
00079 
00080 /* Code to turn a r_type into a howto ptr, uses the above howto table.  */
00081 
00082 static void
00083 rtype2howto (arelent *internal, struct internal_reloc *dst)
00084 {
00085   switch (dst->r_type)
00086     {
00087     default:
00088       abort ();
00089       break;
00090     case R_IMM8:
00091       internal->howto = &r_imm8;
00092       break;
00093      case R_IMM16:
00094       internal->howto = &r_da;
00095       break;
00096     case R_JR:
00097       internal->howto = &r_jr;
00098       break;
00099     case R_DISP7:
00100       internal->howto = &r_disp7;
00101       break;
00102     case R_CALLR:
00103       internal->howto = &r_callr;
00104       break;
00105     case R_REL16:
00106       internal->howto = &r_rel16;
00107       break;
00108     case R_IMM32:
00109       internal->howto = &r_imm32;
00110       break;
00111     case R_IMM4L:
00112       internal->howto = &r_imm4l;
00113       break;
00114     }
00115 }
00116 
00117 #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
00118 
00119 static reloc_howto_type *
00120 coff_z8k_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00121                             bfd_reloc_code_real_type code)
00122 {
00123   switch (code)
00124     {
00125     case BFD_RELOC_8:       return & r_imm8;
00126     case BFD_RELOC_16:             return & r_da;
00127     case BFD_RELOC_32:             return & r_imm32;
00128     case BFD_RELOC_8_PCREL:     return & r_jr;
00129     case BFD_RELOC_16_PCREL:    return & r_rel16;
00130     case BFD_RELOC_Z8K_DISP7:   return & r_disp7;
00131     case BFD_RELOC_Z8K_CALLR:   return & r_callr;
00132     case BFD_RELOC_Z8K_IMM4L:   return & r_imm4l;
00133     default:                BFD_FAIL ();
00134       return 0;
00135     }
00136 }
00137 
00138 static reloc_howto_type *
00139 coff_z8k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00140                          const char *r_name)
00141 {
00142   if (strcasecmp (r_imm8.name, r_name) == 0)
00143     return &r_imm8;
00144   if (strcasecmp (r_da.name, r_name) == 0)
00145     return &r_da;
00146   if (strcasecmp (r_imm32.name, r_name) == 0)
00147     return &r_imm32;
00148   if (strcasecmp (r_jr.name, r_name) == 0)
00149     return &r_jr;
00150   if (strcasecmp (r_rel16.name, r_name) == 0)
00151     return &r_rel16;
00152   if (strcasecmp (r_disp7.name, r_name) == 0)
00153     return &r_disp7;
00154   if (strcasecmp (r_callr.name, r_name) == 0)
00155     return &r_callr;
00156   if (strcasecmp (r_imm4l.name, r_name) == 0)
00157     return &r_imm4l;
00158 
00159   return NULL;
00160 }
00161 
00162 /* Perform any necessary magic to the addend in a reloc entry.  */
00163 
00164 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
00165  cache_ptr->addend =  ext_reloc.r_offset;
00166 
00167 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
00168  reloc_processing(relent, reloc, symbols, abfd, section)
00169 
00170 static void
00171 reloc_processing (arelent *relent,
00172                   struct internal_reloc *reloc,
00173                   asymbol **symbols,
00174                   bfd *abfd,
00175                   asection *section)
00176 {
00177   relent->address = reloc->r_vaddr;
00178   rtype2howto (relent, reloc);
00179 
00180   if (reloc->r_symndx > 0)
00181     relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
00182   else
00183     relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
00184 
00185   relent->addend = reloc->r_offset;
00186   relent->address -= section->vma;
00187 }
00188 
00189 static void
00190 extra_case (bfd *in_abfd,
00191             struct bfd_link_info *link_info,
00192             struct bfd_link_order *link_order,
00193             arelent *reloc,
00194             bfd_byte *data,
00195             unsigned int *src_ptr,
00196             unsigned int *dst_ptr)
00197 {
00198   asection * input_section = link_order->u.indirect.section;
00199 
00200   switch (reloc->howto->type)
00201     {
00202     case R_IMM8:
00203       bfd_put_8 (in_abfd,
00204                bfd_coff_reloc16_get_value (reloc, link_info, input_section),
00205                data + *dst_ptr);
00206       (*dst_ptr) += 1;
00207       (*src_ptr) += 1;
00208       break;
00209 
00210     case R_IMM32:
00211       /* If no flags are set, assume immediate value.  */
00212       if (! (*reloc->sym_ptr_ptr)->section->flags)
00213        {
00214          bfd_put_32 (in_abfd,
00215                     bfd_coff_reloc16_get_value (reloc, link_info,
00216                                             input_section),
00217                     data + *dst_ptr);
00218        }
00219       else
00220        {
00221          bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
00222                                               input_section);
00223          /* Addresses are 23 bit, and the layout of those in a 32-bit
00224             value is as follows:
00225               1AAAAAAA xxxxxxxx AAAAAAAA AAAAAAAA
00226             (A - address bits,  x - ignore).  */
00227          dst = (dst & 0xffff) | ((dst & 0xff0000) << 8) | 0x80000000;
00228          bfd_put_32 (in_abfd, dst, data + *dst_ptr);
00229        }
00230       (*dst_ptr) += 4;
00231       (*src_ptr) += 4;
00232       break;
00233 
00234     case R_IMM4L:
00235       bfd_put_8 (in_abfd,
00236                ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
00237                 | (0x0f
00238                    & bfd_coff_reloc16_get_value (reloc, link_info,
00239                                              input_section))),
00240                data + *dst_ptr);
00241       (*dst_ptr) += 1;
00242       (*src_ptr) += 1;
00243       break;
00244 
00245     case R_IMM16:
00246       bfd_put_16 (in_abfd,
00247                 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
00248                 data + *dst_ptr);
00249       (*dst_ptr) += 2;
00250       (*src_ptr) += 2;
00251       break;
00252 
00253     case R_JR:
00254       {
00255        bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
00256                                             input_section);
00257        bfd_vma dot = (*dst_ptr
00258                      + input_section->output_offset
00259                      + input_section->output_section->vma);
00260        int gap = dst - dot - 1;  /* -1, since we're in the odd byte of the
00261                                      word and the pc's been incremented.  */
00262 
00263        if (gap & 1)
00264          abort ();
00265        gap /= 2;
00266        if (gap > 128 || gap < -128)
00267          {
00268            if (! ((*link_info->callbacks->reloc_overflow)
00269                  (link_info, NULL,
00270                   bfd_asymbol_name (*reloc->sym_ptr_ptr),
00271                   reloc->howto->name, reloc->addend, input_section->owner,
00272                   input_section, reloc->address)))
00273              abort ();
00274          }
00275        bfd_put_8 (in_abfd, gap, data + *dst_ptr);
00276        (*dst_ptr)++;
00277        (*src_ptr)++;
00278        break;
00279       }
00280 
00281     case R_DISP7:
00282       {
00283        bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
00284                                             input_section);
00285        bfd_vma dot = (*dst_ptr
00286                      + input_section->output_offset
00287                      + input_section->output_section->vma);
00288        int gap = dst - dot - 1;  /* -1, since we're in the odd byte of the
00289                                      word and the pc's been incremented.  */
00290 
00291        if (gap & 1)
00292          abort ();
00293        gap /= 2;
00294 
00295        if (gap > 0 || gap < -127)
00296          {
00297            if (! ((*link_info->callbacks->reloc_overflow)
00298                  (link_info, NULL,
00299                   bfd_asymbol_name (*reloc->sym_ptr_ptr),
00300                   reloc->howto->name, reloc->addend, input_section->owner,
00301                   input_section, reloc->address)))
00302              abort ();
00303          }
00304        bfd_put_8 (in_abfd,
00305                    (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
00306                    data + *dst_ptr);
00307        (*dst_ptr)++;
00308        (*src_ptr)++;
00309        break;
00310       }
00311 
00312     case R_CALLR:
00313       {
00314        bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
00315                                             input_section);
00316        bfd_vma dot = (*dst_ptr
00317                      + input_section->output_offset
00318                      + input_section->output_section->vma);
00319        int gap = dst - dot - 2;
00320 
00321        if (gap & 1)
00322          abort ();
00323        if (gap > 4096 || gap < -4095)
00324          {
00325            if (! ((*link_info->callbacks->reloc_overflow)
00326                  (link_info, NULL,
00327                   bfd_asymbol_name (*reloc->sym_ptr_ptr),
00328                   reloc->howto->name, reloc->addend, input_section->owner,
00329                   input_section, reloc->address)))
00330              abort ();
00331          }
00332        gap /= 2;
00333        bfd_put_16 (in_abfd,
00334                     (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
00335                     data + *dst_ptr);
00336        (*dst_ptr) += 2;
00337        (*src_ptr) += 2;
00338        break;
00339       }
00340 
00341     case R_REL16:
00342       {
00343        bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
00344                                             input_section);
00345        bfd_vma dot = (*dst_ptr
00346                      + input_section->output_offset
00347                      + input_section->output_section->vma);
00348        int gap = dst - dot - 2;
00349 
00350        if (gap > 32767 || gap < -32768)
00351          {
00352            if (! ((*link_info->callbacks->reloc_overflow)
00353                  (link_info, NULL,
00354                   bfd_asymbol_name (*reloc->sym_ptr_ptr),
00355                   reloc->howto->name, reloc->addend, input_section->owner,
00356                   input_section, reloc->address)))
00357              abort ();
00358          }
00359        bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
00360        (*dst_ptr) += 2;
00361        (*src_ptr) += 2;
00362        break;
00363       }
00364 
00365     default:
00366       abort ();
00367     }
00368 }
00369 
00370 #define coff_reloc16_extra_cases    extra_case
00371 #define coff_bfd_reloc_type_lookup  coff_z8k_reloc_type_lookup
00372 #define coff_bfd_reloc_name_lookup coff_z8k_reloc_name_lookup
00373 
00374 #include "coffcode.h"
00375 
00376 #undef  coff_bfd_get_relocated_section_contents
00377 #define coff_bfd_get_relocated_section_contents \
00378   bfd_coff_reloc16_get_relocated_section_contents
00379 
00380 #undef  coff_bfd_relax_section
00381 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
00382 
00383 CREATE_BIG_COFF_TARGET_VEC (z8kcoff_vec, "coff-z8k", 0, 0, '_', NULL, COFF_SWAP_TABLE)