Back to index

cell-binutils  2.17cvs20070401
coff-h8500.c
Go to the documentation of this file.
00001 /* BFD back-end for Renesas H8/500 COFF binaries.
00002    Copyright 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005
00003    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/h8500.h"
00028 #include "coff/internal.h"
00029 #include "libcoff.h"
00030 
00031 static int  coff_h8500_select_reloc PARAMS ((reloc_howto_type *));
00032 static void rtype2howto      PARAMS ((arelent *, struct internal_reloc *));
00033 static void reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
00034 static void extra_case       PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *, bfd_byte *, unsigned int *, unsigned int *));
00035 
00036 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
00037 
00038 static reloc_howto_type r_imm8 =
00039 HOWTO (R_H8500_IMM8, 0, 1, 8, FALSE, 0,
00040        complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff, FALSE);
00041 
00042 static reloc_howto_type r_imm16 =
00043 HOWTO (R_H8500_IMM16, 0, 1, 16, FALSE, 0,
00044        complain_overflow_bitfield, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff, FALSE);
00045 
00046 static reloc_howto_type r_imm24 =
00047 HOWTO (R_H8500_IMM24, 0, 1, 24, FALSE, 0,
00048        complain_overflow_bitfield, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff, FALSE);
00049 
00050 static reloc_howto_type r_imm32 =
00051 HOWTO (R_H8500_IMM32, 0, 1, 32, FALSE, 0,
00052        complain_overflow_bitfield, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff, FALSE);
00053 
00054 static reloc_howto_type r_high8 =
00055 HOWTO (R_H8500_HIGH8, 0, 1, 8, FALSE, 0,
00056        complain_overflow_dont, 0, "r_high8", TRUE, 0x000000ff, 0x000000ff, FALSE);
00057 
00058 static reloc_howto_type r_low16 =
00059 HOWTO (R_H8500_LOW16, 0, 1, 16, FALSE, 0,
00060        complain_overflow_dont, 0, "r_low16", TRUE, 0x0000ffff, 0x0000ffff, FALSE);
00061 
00062 static reloc_howto_type r_pcrel8 =
00063 HOWTO (R_H8500_PCREL8, 0, 1, 8, TRUE, 0, complain_overflow_signed, 0, "r_pcrel8", TRUE, 0, 0, TRUE);
00064 
00065 static reloc_howto_type r_pcrel16 =
00066 HOWTO (R_H8500_PCREL16, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "r_pcrel16", TRUE, 0, 0, TRUE);
00067 
00068 static reloc_howto_type r_high16 =
00069 HOWTO (R_H8500_HIGH16, 0, 1, 8, FALSE, 0,
00070        complain_overflow_dont, 0, "r_high16", TRUE, 0x000ffff, 0x0000ffff, FALSE);
00071 
00072 /* Turn a howto into a reloc number.  */
00073 
00074 static int
00075 coff_h8500_select_reloc (howto)
00076      reloc_howto_type *howto;
00077 {
00078   return howto->type;
00079 }
00080 
00081 #define SELECT_RELOC(x,howto) x.r_type = coff_h8500_select_reloc(howto)
00082 
00083 #define BADMAG(x) H8500BADMAG(x)
00084 #define H8500 1                    /* Customize coffcode.h */
00085 
00086 #define __A_MAGIC_SET__
00087 
00088 /* Code to swap in the reloc.  */
00089 #define SWAP_IN_RELOC_OFFSET       H_GET_32
00090 #define SWAP_OUT_RELOC_OFFSET      H_PUT_32
00091 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
00092   dst->r_stuff[0] = 'S'; \
00093   dst->r_stuff[1] = 'C';
00094 
00095 /* Code to turn a r_type into a howto ptr, uses the above howto table.  */
00096 
00097 static void
00098 rtype2howto (internal, dst)
00099      arelent * internal;
00100      struct internal_reloc *dst;
00101 {
00102   switch (dst->r_type)
00103     {
00104     default:
00105       abort ();
00106       break;
00107     case R_H8500_IMM8:
00108       internal->howto = &r_imm8;
00109       break;
00110     case R_H8500_IMM16:
00111       internal->howto = &r_imm16;
00112       break;
00113     case R_H8500_IMM24:
00114       internal->howto = &r_imm24;
00115       break;
00116     case R_H8500_IMM32:
00117       internal->howto = &r_imm32;
00118       break;
00119     case R_H8500_PCREL8:
00120       internal->howto = &r_pcrel8;
00121       break;
00122     case R_H8500_PCREL16:
00123       internal->howto = &r_pcrel16;
00124       break;
00125     case R_H8500_HIGH8:
00126       internal->howto = &r_high8;
00127       break;
00128     case R_H8500_HIGH16:
00129       internal->howto = &r_high16;
00130       break;
00131     case R_H8500_LOW16:
00132       internal->howto = &r_low16;
00133       break;
00134     }
00135 }
00136 
00137 #define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
00138 
00139 /* Perform any necessary magic to the addend in a reloc entry.  */
00140 
00141 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
00142  cache_ptr->addend =  ext_reloc.r_offset;
00143 
00144 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
00145  reloc_processing(relent, reloc, symbols, abfd, section)
00146 
00147 static void reloc_processing (relent, reloc, symbols, abfd, section)
00148      arelent * relent;
00149      struct internal_reloc *reloc;
00150      asymbol ** symbols;
00151      bfd * abfd;
00152      asection * section;
00153 {
00154   relent->address = reloc->r_vaddr;
00155   rtype2howto (relent, reloc);
00156 
00157   if (reloc->r_symndx > 0)
00158     relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
00159   else
00160     relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
00161 
00162   relent->addend = reloc->r_offset;
00163   relent->address -= section->vma;
00164 }
00165 
00166 static void
00167 extra_case (in_abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)
00168      bfd *in_abfd;
00169      struct bfd_link_info *link_info;
00170      struct bfd_link_order *link_order;
00171      arelent *reloc;
00172      bfd_byte *data;
00173      unsigned int *src_ptr;
00174      unsigned int *dst_ptr;
00175 {
00176   bfd_byte *d = data+*dst_ptr;
00177   asection *input_section = link_order->u.indirect.section;
00178 
00179   switch (reloc->howto->type)
00180     {
00181     case R_H8500_IMM8:
00182       bfd_put_8 (in_abfd,
00183                bfd_coff_reloc16_get_value (reloc, link_info, input_section),
00184                d);
00185       (*dst_ptr) += 1;
00186       (*src_ptr) += 1;
00187       break;
00188 
00189     case R_H8500_HIGH8:
00190       bfd_put_8 (in_abfd,
00191                (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
00192                 >> 16),
00193                d);
00194       (*dst_ptr) += 1;
00195       (*src_ptr) += 1;
00196       break;
00197 
00198     case R_H8500_IMM16:
00199       bfd_put_16 (in_abfd,
00200                 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
00201                 d);
00202       (*dst_ptr) += 2;
00203       (*src_ptr) += 2;
00204       break;
00205 
00206     case R_H8500_LOW16:
00207       bfd_put_16 (in_abfd,
00208                 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
00209                 d);
00210 
00211       (*dst_ptr) += 2;
00212       (*src_ptr) += 2;
00213       break;
00214 
00215     case R_H8500_HIGH16:
00216       bfd_put_16 (in_abfd,
00217                 (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
00218                  >> 16),
00219                 d);
00220 
00221       (*dst_ptr) += 2;
00222       (*src_ptr) += 2;
00223       break;
00224 
00225     case R_H8500_IMM24:
00226       {
00227        int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00228        int o = bfd_get_32 (in_abfd, data+ *dst_ptr -1);
00229        v = (v & 0x00ffffff) | (o & 0xff00000);
00230        bfd_put_32 (in_abfd, (bfd_vma) v, data  + *dst_ptr -1);
00231        (*dst_ptr) += 3;
00232        (*src_ptr) += 3;;
00233       }
00234       break;
00235     case R_H8500_IMM32:
00236       {
00237        int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00238        bfd_put_32 (in_abfd, (bfd_vma) v, data  + *dst_ptr);
00239        (*dst_ptr) += 4;
00240        (*src_ptr) += 4;;
00241       }
00242       break;
00243 
00244     case R_H8500_PCREL8:
00245       {
00246        bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
00247                                             input_section);
00248        bfd_vma dot = (*dst_ptr
00249                      + input_section->output_offset
00250                      + input_section->output_section->vma);
00251        int gap = dst - dot - 1; /* -1 since were in the odd byte of the
00252                                 word and the pc's been incremented.  */
00253 
00254        if (gap > 128 || gap < -128)
00255          {
00256            if (! ((*link_info->callbacks->reloc_overflow)
00257                  (link_info, NULL,
00258                   bfd_asymbol_name (*reloc->sym_ptr_ptr),
00259                   reloc->howto->name, reloc->addend, input_section->owner,
00260                   input_section, reloc->address)))
00261              abort ();
00262          }
00263        bfd_put_8 (in_abfd, gap, data + *dst_ptr);
00264        (*dst_ptr)++;
00265        (*src_ptr)++;
00266        break;
00267       }
00268     case R_H8500_PCREL16:
00269       {
00270        bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
00271                                             input_section);
00272        bfd_vma dot = (*dst_ptr
00273                      + input_section->output_offset
00274                      + input_section->output_section->vma);
00275        int gap = dst - dot - 1; /* -1 since were in the odd byte of the
00276                                 word and the pc's been incremented.  */
00277 
00278        if (gap > 32767 || gap < -32768)
00279          {
00280            if (! ((*link_info->callbacks->reloc_overflow)
00281                  (link_info, NULL,
00282                   bfd_asymbol_name (*reloc->sym_ptr_ptr),
00283                   reloc->howto->name, reloc->addend, input_section->owner,
00284                   input_section, reloc->address)))
00285              abort ();
00286          }
00287        bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
00288        (*dst_ptr) += 2;
00289        (*src_ptr) += 2;
00290        break;
00291       }
00292 
00293     default:
00294       abort ();
00295     }
00296 }
00297 
00298 #define coff_reloc16_extra_cases extra_case
00299 
00300 #include "coffcode.h"
00301 
00302 #undef  coff_bfd_get_relocated_section_contents
00303 #undef coff_bfd_relax_section
00304 #define coff_bfd_get_relocated_section_contents \
00305   bfd_coff_reloc16_get_relocated_section_contents
00306 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
00307 
00308 CREATE_BIG_COFF_TARGET_VEC (h8500coff_vec, "coff-h8500", 0, 0, '_', NULL, COFF_SWAP_TABLE)