Back to index

cell-binutils  2.17cvs20070401
coff-m68k.c
Go to the documentation of this file.
00001 /* BFD back-end for Motorola 68000 COFF binaries.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999,
00003    2000, 2001, 2002, 2003, 2005, 2007
00004    Free Software Foundation, Inc.
00005    Written by Cygnus Support.
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 "coff/m68k.h"
00027 #include "coff/internal.h"
00028 #include "libcoff.h"
00029 
00030 /* This source file is compiled multiple times for various m68k COFF
00031    variants.  The following macros control its behaviour:
00032 
00033    TARGET_SYM
00034      The C name of the BFD target vector.  The default is m68kcoff_vec.
00035    TARGET_NAME
00036      The user visible target name.  The default is "coff-m68k".
00037    NAMES_HAVE_UNDERSCORE
00038      Whether symbol names have an underscore.
00039    ONLY_DECLARE_RELOCS
00040      Only declare the relocation howto array.  Don't actually compile
00041      it.  The actual array will be picked up in another version of the
00042      file.
00043    STATIC_RELOCS
00044      Make the relocation howto array, and associated functions, static.
00045    COFF_COMMON_ADDEND
00046      If this is defined, then, for a relocation against a common
00047      symbol, the object file holds the value (the size) of the common
00048      symbol.  If this is not defined, then, for a relocation against a
00049      common symbol, the object file holds zero.  */
00050 
00051 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
00052 
00053 #ifndef COFF_PAGE_SIZE
00054 /* The page size is a guess based on ELF.  */
00055 #define COFF_PAGE_SIZE 0x2000
00056 #endif
00057 
00058 #ifndef COFF_COMMON_ADDEND
00059 #define RELOC_SPECIAL_FN 0
00060 #else
00061 static bfd_reloc_status_type m68kcoff_common_addend_special_fn
00062   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00063 static reloc_howto_type *m68kcoff_common_addend_rtype_to_howto
00064   PARAMS ((bfd *, asection *, struct internal_reloc *,
00065           struct coff_link_hash_entry *, struct internal_syment *,
00066           bfd_vma *));
00067 #define RELOC_SPECIAL_FN m68kcoff_common_addend_special_fn
00068 #endif
00069 
00070 static bfd_boolean m68k_coff_is_local_label_name
00071   PARAMS ((bfd *, const char *));
00072 
00073 /* On the delta, a symbol starting with L% is local.  We won't see
00074    such a symbol on other platforms, so it should be safe to always
00075    consider it local here.  */
00076 
00077 static bfd_boolean
00078 m68k_coff_is_local_label_name (abfd, name)
00079      bfd *abfd;
00080      const char *name;
00081 {
00082   if (name[0] == 'L' && name[1] == '%')
00083     return TRUE;
00084 
00085   return _bfd_coff_is_local_label_name (abfd, name);
00086 }
00087 
00088 #ifndef STATIC_RELOCS
00089 /* Clean up namespace.  */
00090 #define m68kcoff_howto_table       _bfd_m68kcoff_howto_table
00091 #define m68k_rtype2howto    _bfd_m68kcoff_rtype2howto
00092 #define m68k_howto2rtype    _bfd_m68kcoff_howto2rtype
00093 #define m68k_reloc_type_lookup     _bfd_m68kcoff_reloc_type_lookup
00094 #define m68k_reloc_name_lookup _bfd_m68kcoff_reloc_name_lookup
00095 #endif
00096 
00097 #ifdef ONLY_DECLARE_RELOCS
00098 extern reloc_howto_type m68kcoff_howto_table[];
00099 #else
00100 #ifdef STATIC_RELOCS
00101 static
00102 #endif
00103 reloc_howto_type m68kcoff_howto_table[] =
00104   {
00105     HOWTO (R_RELBYTE,              0,  0,        8,  FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "8",      TRUE, 0x000000ff,0x000000ff, FALSE),
00106     HOWTO (R_RELWORD,              0,  1,        16, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "16",     TRUE, 0x0000ffff,0x0000ffff, FALSE),
00107     HOWTO (R_RELLONG,              0,  2,        32, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "32",     TRUE, 0xffffffff,0xffffffff, FALSE),
00108     HOWTO (R_PCRBYTE,              0,  0,        8,  TRUE,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP8",    TRUE, 0x000000ff,0x000000ff, FALSE),
00109     HOWTO (R_PCRWORD,              0,  1,        16, TRUE,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP16",   TRUE, 0x0000ffff,0x0000ffff, FALSE),
00110     HOWTO (R_PCRLONG,              0,  2,        32, TRUE,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP32",   TRUE, 0xffffffff,0xffffffff, FALSE),
00111     HOWTO (R_RELLONG_NEG,      0, -2,     32, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "-32",    TRUE, 0xffffffff,0xffffffff, FALSE),
00112   };
00113 #endif /* not ONLY_DECLARE_RELOCS */
00114 
00115 #ifndef BADMAG
00116 #define BADMAG(x) M68KBADMAG(x)
00117 #endif
00118 #define M68 1        /* Customize coffcode.h */
00119 
00120 /* Turn a howto into a reloc number */
00121 
00122 #ifdef ONLY_DECLARE_RELOCS
00123 extern void m68k_rtype2howto PARAMS ((arelent *internal, int relocentry));
00124 extern int m68k_howto2rtype PARAMS ((reloc_howto_type *));
00125 extern reloc_howto_type *m68k_reloc_type_lookup
00126   PARAMS ((bfd *, bfd_reloc_code_real_type));
00127 extern reloc_howto_type *m68k_reloc_name_lookup
00128   PARAMS ((bfd *, const char *));
00129 #else
00130 
00131 #ifdef STATIC_RELOCS
00132 #define STAT_REL static
00133 #else
00134 #define STAT_REL
00135 #endif
00136 
00137 STAT_REL reloc_howto_type * m68k_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
00138 STAT_REL reloc_howto_type * m68k_reloc_name_lookup PARAMS ((bfd *, const char *));
00139 STAT_REL int m68k_howto2rtype PARAMS ((reloc_howto_type *));
00140 STAT_REL void m68k_rtype2howto PARAMS ((arelent *, int));
00141 
00142 
00143 STAT_REL void
00144 m68k_rtype2howto(internal, relocentry)
00145      arelent *internal;
00146      int relocentry;
00147 {
00148   switch (relocentry)
00149     {
00150     case R_RELBYTE:  internal->howto = m68kcoff_howto_table + 0; break;
00151     case R_RELWORD:  internal->howto = m68kcoff_howto_table + 1; break;
00152     case R_RELLONG:  internal->howto = m68kcoff_howto_table + 2; break;
00153     case R_PCRBYTE:  internal->howto = m68kcoff_howto_table + 3; break;
00154     case R_PCRWORD:  internal->howto = m68kcoff_howto_table + 4; break;
00155     case R_PCRLONG:  internal->howto = m68kcoff_howto_table + 5; break;
00156     case R_RELLONG_NEG:     internal->howto = m68kcoff_howto_table + 6; break;
00157     }
00158 }
00159 
00160 STAT_REL int
00161 m68k_howto2rtype (internal)
00162      reloc_howto_type *internal;
00163 {
00164   if (internal->pc_relative)
00165     {
00166       switch (internal->bitsize)
00167        {
00168        case 32: return R_PCRLONG;
00169        case 16: return R_PCRWORD;
00170        case 8: return R_PCRBYTE;
00171        }
00172     }
00173   else
00174     {
00175       switch (internal->bitsize)
00176        {
00177        case 32: return R_RELLONG;
00178        case 16: return R_RELWORD;
00179        case 8: return R_RELBYTE;
00180        }
00181     }
00182   return R_RELLONG;
00183 }
00184 
00185 STAT_REL reloc_howto_type *
00186 m68k_reloc_type_lookup (abfd, code)
00187      bfd *abfd ATTRIBUTE_UNUSED;
00188      bfd_reloc_code_real_type code;
00189 {
00190   switch (code)
00191     {
00192     default:                return NULL;
00193     case BFD_RELOC_8:              return m68kcoff_howto_table + 0;
00194     case BFD_RELOC_16:             return m68kcoff_howto_table + 1;
00195     case BFD_RELOC_CTOR:
00196     case BFD_RELOC_32:             return m68kcoff_howto_table + 2;
00197     case BFD_RELOC_8_PCREL: return m68kcoff_howto_table + 3;
00198     case BFD_RELOC_16_PCREL:       return m68kcoff_howto_table + 4;
00199     case BFD_RELOC_32_PCREL:       return m68kcoff_howto_table + 5;
00200       /* FIXME: There doesn't seem to be a code for R_RELLONG_NEG.  */
00201     }
00202   /*NOTREACHED*/
00203 }
00204 
00205 STAT_REL reloc_howto_type *
00206 m68k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00207                       const char *r_name)
00208 {
00209   unsigned int i;
00210 
00211   for (i = 0;
00212        i < sizeof (m68kcoff_howto_table) / sizeof (m68kcoff_howto_table[0]);
00213        i++)
00214     if (m68kcoff_howto_table[i].name != NULL
00215        && strcasecmp (m68kcoff_howto_table[i].name, r_name) == 0)
00216       return &m68kcoff_howto_table[i];
00217 
00218   return NULL;
00219 }
00220 
00221 #endif /* not ONLY_DECLARE_RELOCS */
00222 
00223 #define RTYPE2HOWTO(internal, relocentry) \
00224   m68k_rtype2howto(internal, (relocentry)->r_type)
00225 
00226 #define SELECT_RELOC(external, internal) \
00227   external.r_type = m68k_howto2rtype (internal)
00228 
00229 #define coff_bfd_reloc_type_lookup m68k_reloc_type_lookup
00230 #define coff_bfd_reloc_name_lookup m68k_reloc_name_lookup
00231 
00232 #ifndef COFF_COMMON_ADDEND
00233 #ifndef coff_rtype_to_howto
00234 
00235 #define coff_rtype_to_howto m68kcoff_rtype_to_howto
00236 
00237 static reloc_howto_type *m68kcoff_rtype_to_howto
00238   PARAMS ((bfd *, asection *, struct internal_reloc *,
00239           struct coff_link_hash_entry *, struct internal_syment *,
00240           bfd_vma *));
00241 
00242 static reloc_howto_type *
00243 m68kcoff_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00244      bfd *abfd ATTRIBUTE_UNUSED;
00245      asection *sec;
00246      struct internal_reloc *rel;
00247      struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
00248      struct internal_syment *sym ATTRIBUTE_UNUSED;
00249      bfd_vma *addendp;
00250 {
00251   arelent relent;
00252   reloc_howto_type *howto;
00253 
00254   RTYPE2HOWTO (&relent, rel);
00255 
00256   howto = relent.howto;
00257 
00258   if (howto->pc_relative)
00259     *addendp += sec->vma;
00260 
00261   return howto;
00262 }
00263 
00264 #endif /* ! defined (coff_rtype_to_howto) */
00265 #endif /* ! defined (COFF_COMMON_ADDEND) */
00266 
00267 #ifdef COFF_COMMON_ADDEND
00268 
00269 /* If COFF_COMMON_ADDEND is defined, then when using m68k COFF the
00270    value stored in the .text section for a reference to a common
00271    symbol is the value itself plus any desired offset.  (taken from
00272    work done by Ian Taylor, Cygnus Support, for I386 COFF).  */
00273 
00274 /* If we are producing relocatable output, we need to do some
00275    adjustments to the object file that are not done by the
00276    bfd_perform_relocation function.  This function is called by every
00277    reloc type to make any required adjustments.  */
00278 
00279 static bfd_reloc_status_type
00280 m68kcoff_common_addend_special_fn (abfd, reloc_entry, symbol, data,
00281                                input_section, output_bfd, error_message)
00282      bfd *abfd;
00283      arelent *reloc_entry;
00284      asymbol *symbol;
00285      PTR data;
00286      asection *input_section ATTRIBUTE_UNUSED;
00287      bfd *output_bfd;
00288      char **error_message ATTRIBUTE_UNUSED;
00289 {
00290   symvalue diff;
00291 
00292   if (output_bfd == (bfd *) NULL)
00293     return bfd_reloc_continue;
00294 
00295   if (bfd_is_com_section (symbol->section))
00296     {
00297       /* We are relocating a common symbol.  The current value in the
00298         object file is ORIG + OFFSET, where ORIG is the value of the
00299         common symbol as seen by the object file when it was compiled
00300         (this may be zero if the symbol was undefined) and OFFSET is
00301         the offset into the common symbol (normally zero, but may be
00302         non-zero when referring to a field in a common structure).
00303         ORIG is the negative of reloc_entry->addend, which is set by
00304         the CALC_ADDEND macro below.  We want to replace the value in
00305         the object file with NEW + OFFSET, where NEW is the value of
00306         the common symbol which we are going to put in the final
00307         object file.  NEW is symbol->value.  */
00308       diff = symbol->value + reloc_entry->addend;
00309     }
00310   else
00311     {
00312       /* For some reason bfd_perform_relocation always effectively
00313         ignores the addend for a COFF target when producing
00314         relocatable output.  This seems to be always wrong for 386
00315         COFF, so we handle the addend here instead.  */
00316       diff = reloc_entry->addend;
00317     }
00318 
00319 #define DOIT(x) \
00320   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
00321 
00322   if (diff != 0)
00323     {
00324       reloc_howto_type *howto = reloc_entry->howto;
00325       unsigned char *addr = (unsigned char *) data + reloc_entry->address;
00326 
00327       switch (howto->size)
00328        {
00329        case 0:
00330          {
00331            char x = bfd_get_8 (abfd, addr);
00332            DOIT (x);
00333            bfd_put_8 (abfd, x, addr);
00334          }
00335          break;
00336 
00337        case 1:
00338          {
00339            short x = bfd_get_16 (abfd, addr);
00340            DOIT (x);
00341            bfd_put_16 (abfd, (bfd_vma) x, addr);
00342          }
00343          break;
00344 
00345        case 2:
00346          {
00347            long x = bfd_get_32 (abfd, addr);
00348            DOIT (x);
00349            bfd_put_32 (abfd, (bfd_vma) x, addr);
00350          }
00351          break;
00352 
00353        default:
00354          abort ();
00355        }
00356     }
00357 
00358   /* Now let bfd_perform_relocation finish everything up.  */
00359   return bfd_reloc_continue;
00360 }
00361 
00362 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
00363    the object file contains the value of the common symbol.  By the
00364    time this is called, the linker may be using a different symbol
00365    from a different object file with a different value.  Therefore, we
00366    hack wildly to locate the original symbol from this file so that we
00367    can make the correct adjustment.  This macro sets coffsym to the
00368    symbol from the original file, and uses it to set the addend value
00369    correctly.  If this is not a common symbol, the usual addend
00370    calculation is done, except that an additional tweak is needed for
00371    PC relative relocs.
00372    FIXME: This macro refers to symbols and asect; these are from the
00373    calling function, not the macro arguments.  */
00374 
00375 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)        \
00376   {                                                     \
00377     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;     \
00378     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                  \
00379       coffsym = (obj_symbols (abfd)                            \
00380                 + (cache_ptr->sym_ptr_ptr - symbols));         \
00381     else if (ptr)                                       \
00382       coffsym = coff_symbol_from (abfd, ptr);                  \
00383     if (coffsym != (coff_symbol_type *) NULL                   \
00384        && coffsym->native->u.syment.n_scnum == 0)              \
00385       cache_ptr->addend = - coffsym->native->u.syment.n_value; \
00386     else if (ptr && bfd_asymbol_bfd (ptr) == abfd              \
00387             && ptr->section != (asection *) NULL)              \
00388       cache_ptr->addend = - (ptr->section->vma + ptr->value);  \
00389     else                                                \
00390       cache_ptr->addend = 0;                                   \
00391     if (ptr && (reloc.r_type == R_PCRBYTE               \
00392               || reloc.r_type == R_PCRWORD                     \
00393               || reloc.r_type == R_PCRLONG))                   \
00394       cache_ptr->addend += asect->vma;                         \
00395   }
00396 
00397 #ifndef coff_rtype_to_howto
00398 
00399 /* coff-m68k.c uses the special COFF backend linker.  We need to
00400    adjust common symbols.  */
00401 
00402 static reloc_howto_type *
00403 m68kcoff_common_addend_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00404      bfd *abfd ATTRIBUTE_UNUSED;
00405      asection *sec;
00406      struct internal_reloc *rel;
00407      struct coff_link_hash_entry *h;
00408      struct internal_syment *sym;
00409      bfd_vma *addendp;
00410 {
00411   arelent relent;
00412   reloc_howto_type *howto;
00413 
00414   RTYPE2HOWTO (&relent, rel);
00415 
00416   howto = relent.howto;
00417 
00418   if (howto->pc_relative)
00419     *addendp += sec->vma;
00420 
00421   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
00422     {
00423       /* This is a common symbol.  The section contents include the
00424         size (sym->n_value) as an addend.  The relocate_section
00425         function will be adding in the final value of the symbol.  We
00426         need to subtract out the current size in order to get the
00427         correct result.  */
00428       BFD_ASSERT (h != NULL);
00429       *addendp -= sym->n_value;
00430     }
00431 
00432   /* If the output symbol is common (in which case this must be a
00433      relocatable link), we need to add in the final size of the
00434      common symbol.  */
00435   if (h != NULL && h->root.type == bfd_link_hash_common)
00436     *addendp += h->root.u.c.size;
00437 
00438   return howto;
00439 }
00440 
00441 #define coff_rtype_to_howto m68kcoff_common_addend_rtype_to_howto
00442 
00443 #endif /* ! defined (coff_rtype_to_howto) */
00444 
00445 #endif /* COFF_COMMON_ADDEND */
00446 
00447 #if !defined ONLY_DECLARE_RELOCS && ! defined STATIC_RELOCS
00448 /* Given a .data section and a .emreloc in-memory section, store
00449    relocation information into the .emreloc section which can be
00450    used at runtime to relocate the section.  This is called by the
00451    linker when the --embedded-relocs switch is used.  This is called
00452    after the add_symbols entry point has been called for all the
00453    objects, and before the final_link entry point is called.  */
00454 
00455 bfd_boolean
00456 bfd_m68k_coff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
00457      bfd *abfd;
00458      struct bfd_link_info *info;
00459      asection *datasec;
00460      asection *relsec;
00461      char **errmsg;
00462 {
00463   char *extsyms;
00464   bfd_size_type symesz;
00465   struct internal_reloc *irel, *irelend;
00466   bfd_byte *p;
00467   bfd_size_type amt;
00468 
00469   BFD_ASSERT (! info->relocatable);
00470 
00471   *errmsg = NULL;
00472 
00473   if (datasec->reloc_count == 0)
00474     return TRUE;
00475 
00476   extsyms = obj_coff_external_syms (abfd);
00477   symesz = bfd_coff_symesz (abfd);
00478 
00479   irel = _bfd_coff_read_internal_relocs (abfd, datasec, TRUE, NULL, FALSE,
00480                                     NULL);
00481   irelend = irel + datasec->reloc_count;
00482 
00483   amt = (bfd_size_type) datasec->reloc_count * 12;
00484   relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
00485   if (relsec->contents == NULL)
00486     return FALSE;
00487 
00488   p = relsec->contents;
00489 
00490   for (; irel < irelend; irel++, p += 12)
00491     {
00492       asection *targetsec;
00493 
00494       /* We are going to write a four byte longword into the runtime
00495        reloc section.  The longword will be the address in the data
00496        section which must be relocated.  It is followed by the name
00497        of the target section NUL-padded or truncated to 8
00498        characters.  */
00499 
00500       /* We can only relocate absolute longword relocs at run time.  */
00501       if (irel->r_type != R_RELLONG)
00502        {
00503          *errmsg = _("unsupported reloc type");
00504          bfd_set_error (bfd_error_bad_value);
00505          return FALSE;
00506        }
00507 
00508       if (irel->r_symndx == -1)
00509        targetsec = bfd_abs_section_ptr;
00510       else
00511        {
00512          struct coff_link_hash_entry *h;
00513 
00514          h = obj_coff_sym_hashes (abfd)[irel->r_symndx];
00515          if (h == NULL)
00516            {
00517              struct internal_syment isym;
00518 
00519              bfd_coff_swap_sym_in (abfd, extsyms + symesz * irel->r_symndx,
00520                                 &isym);
00521              targetsec = coff_section_from_bfd_index (abfd, isym.n_scnum);
00522            }
00523          else if (h->root.type == bfd_link_hash_defined
00524                  || h->root.type == bfd_link_hash_defweak)
00525            targetsec = h->root.u.def.section;
00526          else
00527            targetsec = NULL;
00528        }
00529 
00530       bfd_put_32 (abfd,
00531                 (irel->r_vaddr - datasec->vma + datasec->output_offset), p);
00532       memset (p + 4, 0, 8);
00533       if (targetsec != NULL)
00534        strncpy ((char *) p + 4, targetsec->output_section->name, 8);
00535     }
00536 
00537   return TRUE;
00538 }
00539 #endif /* neither ONLY_DECLARE_RELOCS not STATIC_RELOCS  */
00540 
00541 #define coff_bfd_is_local_label_name m68k_coff_is_local_label_name
00542 
00543 #define coff_relocate_section _bfd_coff_generic_relocate_section
00544 
00545 #include "coffcode.h"
00546 
00547 #ifndef TARGET_SYM
00548 #define TARGET_SYM m68kcoff_vec
00549 #endif
00550 
00551 #ifndef TARGET_NAME
00552 #define TARGET_NAME "coff-m68k"
00553 #endif
00554 
00555 #ifdef NAMES_HAVE_UNDERSCORE
00556 CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE)
00557 #else
00558 CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, 0, NULL, COFF_SWAP_TABLE)
00559 #endif