Home | History | Annotate | Download | only in bfd
      1 /* BFD back-end for Motorola 68000 COFF binaries.
      2    Copyright (C) 1990-2014 Free Software Foundation, Inc.
      3    Written by Cygnus Support.
      4 
      5    This file is part of BFD, the Binary File Descriptor library.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 #include "sysdep.h"
     23 #include "bfd.h"
     24 #include "libbfd.h"
     25 #include "coff/m68k.h"
     26 #include "coff/internal.h"
     27 #include "libcoff.h"
     28 
     29 /* This source file is compiled multiple times for various m68k COFF
     30    variants.  The following macros control its behaviour:
     31 
     32    TARGET_SYM
     33      The C name of the BFD target vector.  The default is m68k_coff_vec.
     34    TARGET_NAME
     35      The user visible target name.  The default is "coff-m68k".
     36    NAMES_HAVE_UNDERSCORE
     37      Whether symbol names have an underscore.
     38    ONLY_DECLARE_RELOCS
     39      Only declare the relocation howto array.  Don't actually compile
     40      it.  The actual array will be picked up in another version of the
     41      file.
     42    STATIC_RELOCS
     43      Make the relocation howto array, and associated functions, static.
     44    COFF_COMMON_ADDEND
     45      If this is defined, then, for a relocation against a common
     46      symbol, the object file holds the value (the size) of the common
     47      symbol.  If this is not defined, then, for a relocation against a
     48      common symbol, the object file holds zero.  */
     49 
     50 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
     51 
     52 #ifndef COFF_PAGE_SIZE
     53 /* The page size is a guess based on ELF.  */
     54 #define COFF_PAGE_SIZE 0x2000
     55 #endif
     56 
     57 #ifndef COFF_COMMON_ADDEND
     58 #define RELOC_SPECIAL_FN 0
     59 #else
     60 static bfd_reloc_status_type m68kcoff_common_addend_special_fn
     61   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
     62 
     63 #define RELOC_SPECIAL_FN m68kcoff_common_addend_special_fn
     64 #endif
     65 
     66 static bfd_boolean m68k_coff_is_local_label_name (bfd *, const char *);
     67 
     68 /* On the delta, a symbol starting with L% is local.  We won't see
     69    such a symbol on other platforms, so it should be safe to always
     70    consider it local here.  */
     71 
     72 static bfd_boolean
     73 m68k_coff_is_local_label_name (bfd *abfd, const char *name)
     74 {
     75   if (name[0] == 'L' && name[1] == '%')
     76     return TRUE;
     77 
     78   return _bfd_coff_is_local_label_name (abfd, name);
     79 }
     80 
     81 #ifndef STATIC_RELOCS
     82 /* Clean up namespace.  */
     83 #define m68kcoff_howto_table	_bfd_m68kcoff_howto_table
     84 #define m68k_rtype2howto	_bfd_m68kcoff_rtype2howto
     85 #define m68k_howto2rtype	_bfd_m68kcoff_howto2rtype
     86 #define m68k_reloc_type_lookup	_bfd_m68kcoff_reloc_type_lookup
     87 #define m68k_reloc_name_lookup _bfd_m68kcoff_reloc_name_lookup
     88 #endif
     89 
     90 #ifdef ONLY_DECLARE_RELOCS
     91 extern reloc_howto_type m68kcoff_howto_table[];
     92 #else
     93 #ifdef STATIC_RELOCS
     94 static
     95 #endif
     96 reloc_howto_type m68kcoff_howto_table[] =
     97   {
     98     HOWTO (R_RELBYTE,	       0,  0,  	8,  FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "8",	TRUE, 0x000000ff,0x000000ff, FALSE),
     99     HOWTO (R_RELWORD,	       0,  1, 	16, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "16",	TRUE, 0x0000ffff,0x0000ffff, FALSE),
    100     HOWTO (R_RELLONG,	       0,  2, 	32, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "32",	TRUE, 0xffffffff,0xffffffff, FALSE),
    101     HOWTO (R_PCRBYTE,	       0,  0, 	8,  TRUE,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP8",    TRUE, 0x000000ff,0x000000ff, FALSE),
    102     HOWTO (R_PCRWORD,	       0,  1, 	16, TRUE,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP16",   TRUE, 0x0000ffff,0x0000ffff, FALSE),
    103     HOWTO (R_PCRLONG,	       0,  2, 	32, TRUE,  0, complain_overflow_signed,   RELOC_SPECIAL_FN, "DISP32",   TRUE, 0xffffffff,0xffffffff, FALSE),
    104     HOWTO (R_RELLONG_NEG,      0, -2, 	32, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "-32",	TRUE, 0xffffffff,0xffffffff, FALSE),
    105   };
    106 #endif /* not ONLY_DECLARE_RELOCS */
    107 
    108 #ifndef BADMAG
    109 #define BADMAG(x) M68KBADMAG(x)
    110 #endif
    111 #define M68 1		/* Customize coffcode.h */
    112 
    113 /* Turn a howto into a reloc number */
    114 
    115 #ifdef ONLY_DECLARE_RELOCS
    116 extern void m68k_rtype2howto (arelent *internal, int relocentry);
    117 extern int m68k_howto2rtype (reloc_howto_type *);
    118 extern reloc_howto_type * m68k_reloc_type_lookup
    119   (bfd *, bfd_reloc_code_real_type);
    120 extern reloc_howto_type * m68k_reloc_name_lookup (bfd *, const char *);
    121 #else
    122 
    123 #ifdef STATIC_RELOCS
    124 #define STAT_REL static
    125 #else
    126 #define STAT_REL
    127 #endif
    128 
    129 STAT_REL void m68k_rtype2howto (arelent *, int);
    130 STAT_REL int  m68k_howto2rtype (reloc_howto_type *);
    131 STAT_REL reloc_howto_type * m68k_reloc_type_lookup (bfd *, bfd_reloc_code_real_type);
    132 STAT_REL reloc_howto_type * m68k_reloc_name_lookup (bfd *, const char *);
    133 
    134 STAT_REL void
    135 m68k_rtype2howto (arelent *internal, int relocentry)
    136 {
    137   switch (relocentry)
    138     {
    139     case R_RELBYTE:	internal->howto = m68kcoff_howto_table + 0; break;
    140     case R_RELWORD:	internal->howto = m68kcoff_howto_table + 1; break;
    141     case R_RELLONG:	internal->howto = m68kcoff_howto_table + 2; break;
    142     case R_PCRBYTE:	internal->howto = m68kcoff_howto_table + 3; break;
    143     case R_PCRWORD:	internal->howto = m68kcoff_howto_table + 4; break;
    144     case R_PCRLONG:	internal->howto = m68kcoff_howto_table + 5; break;
    145     case R_RELLONG_NEG:	internal->howto = m68kcoff_howto_table + 6; break;
    146     }
    147 }
    148 
    149 STAT_REL int
    150 m68k_howto2rtype (reloc_howto_type * internal)
    151 {
    152   if (internal->pc_relative)
    153     {
    154       switch (internal->bitsize)
    155 	{
    156 	case 32: return R_PCRLONG;
    157 	case 16: return R_PCRWORD;
    158 	case 8: return R_PCRBYTE;
    159 	}
    160     }
    161   else
    162     {
    163       switch (internal->bitsize)
    164 	{
    165 	case 32: return R_RELLONG;
    166 	case 16: return R_RELWORD;
    167 	case 8: return R_RELBYTE;
    168 	}
    169     }
    170   return R_RELLONG;
    171 }
    172 
    173 STAT_REL reloc_howto_type *
    174 m68k_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    175 			bfd_reloc_code_real_type code)
    176 {
    177   switch (code)
    178     {
    179     default:			return NULL;
    180     case BFD_RELOC_8:		return m68kcoff_howto_table + 0;
    181     case BFD_RELOC_16:		return m68kcoff_howto_table + 1;
    182     case BFD_RELOC_CTOR:
    183     case BFD_RELOC_32:		return m68kcoff_howto_table + 2;
    184     case BFD_RELOC_8_PCREL:	return m68kcoff_howto_table + 3;
    185     case BFD_RELOC_16_PCREL:	return m68kcoff_howto_table + 4;
    186     case BFD_RELOC_32_PCREL:	return m68kcoff_howto_table + 5;
    187       /* FIXME: There doesn't seem to be a code for R_RELLONG_NEG.  */
    188     }
    189   /*NOTREACHED*/
    190 }
    191 
    192 STAT_REL reloc_howto_type *
    193 m68k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    194 		        const char *r_name)
    195 {
    196   unsigned int i;
    197 
    198   for (i = 0;
    199        i < sizeof (m68kcoff_howto_table) / sizeof (m68kcoff_howto_table[0]);
    200        i++)
    201     if (m68kcoff_howto_table[i].name != NULL
    202 	&& strcasecmp (m68kcoff_howto_table[i].name, r_name) == 0)
    203       return &m68kcoff_howto_table[i];
    204 
    205   return NULL;
    206 }
    207 
    208 #endif /* not ONLY_DECLARE_RELOCS */
    209 
    210 #define RTYPE2HOWTO(internal, relocentry) \
    211   m68k_rtype2howto(internal, (relocentry)->r_type)
    212 
    213 #define SELECT_RELOC(external, internal) \
    214   external.r_type = m68k_howto2rtype (internal)
    215 
    216 #define coff_bfd_reloc_type_lookup m68k_reloc_type_lookup
    217 #define coff_bfd_reloc_name_lookup m68k_reloc_name_lookup
    218 
    219 #ifndef COFF_COMMON_ADDEND
    220 #ifndef coff_rtype_to_howto
    221 
    222 #define coff_rtype_to_howto m68kcoff_rtype_to_howto
    223 
    224 static reloc_howto_type *
    225 m68kcoff_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
    226 			 asection *sec,
    227 			 struct internal_reloc *rel,
    228 			 struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
    229 			 struct internal_syment *sym ATTRIBUTE_UNUSED,
    230 			 bfd_vma *addendp)
    231 {
    232   arelent relent;
    233   reloc_howto_type *howto;
    234 
    235   relent.howto = NULL;
    236   RTYPE2HOWTO (&relent, rel);
    237 
    238   howto = relent.howto;
    239 
    240   if (howto != NULL && howto->pc_relative)
    241     *addendp += sec->vma;
    242 
    243   return howto;
    244 }
    245 
    246 #endif /* ! defined (coff_rtype_to_howto) */
    247 #endif /* ! defined (COFF_COMMON_ADDEND) */
    248 
    249 #ifdef COFF_COMMON_ADDEND
    251 
    252 /* If COFF_COMMON_ADDEND is defined, then when using m68k COFF the
    253    value stored in the .text section for a reference to a common
    254    symbol is the value itself plus any desired offset.  (taken from
    255    work done by Ian Taylor, Cygnus Support, for I386 COFF).  */
    256 
    257 /* If we are producing relocatable output, we need to do some
    258    adjustments to the object file that are not done by the
    259    bfd_perform_relocation function.  This function is called by every
    260    reloc type to make any required adjustments.  */
    261 
    262 static bfd_reloc_status_type
    263 m68kcoff_common_addend_special_fn (bfd *abfd,
    264 				   arelent *reloc_entry,
    265 				   asymbol *symbol,
    266 				   void * data,
    267 				   asection *input_section ATTRIBUTE_UNUSED,
    268 				   bfd *output_bfd,
    269 				   char **error_message ATTRIBUTE_UNUSED)
    270 {
    271   symvalue diff;
    272 
    273   if (output_bfd == (bfd *) NULL)
    274     return bfd_reloc_continue;
    275 
    276   if (bfd_is_com_section (symbol->section))
    277     {
    278       /* We are relocating a common symbol.  The current value in the
    279 	 object file is ORIG + OFFSET, where ORIG is the value of the
    280 	 common symbol as seen by the object file when it was compiled
    281 	 (this may be zero if the symbol was undefined) and OFFSET is
    282 	 the offset into the common symbol (normally zero, but may be
    283 	 non-zero when referring to a field in a common structure).
    284 	 ORIG is the negative of reloc_entry->addend, which is set by
    285 	 the CALC_ADDEND macro below.  We want to replace the value in
    286 	 the object file with NEW + OFFSET, where NEW is the value of
    287 	 the common symbol which we are going to put in the final
    288 	 object file.  NEW is symbol->value.  */
    289       diff = symbol->value + reloc_entry->addend;
    290     }
    291   else
    292     {
    293       /* For some reason bfd_perform_relocation always effectively
    294 	 ignores the addend for a COFF target when producing
    295 	 relocatable output.  This seems to be always wrong for 386
    296 	 COFF, so we handle the addend here instead.  */
    297       diff = reloc_entry->addend;
    298     }
    299 
    300 #define DOIT(x) \
    301   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
    302 
    303   if (diff != 0)
    304     {
    305       reloc_howto_type *howto = reloc_entry->howto;
    306       unsigned char *addr = (unsigned char *) data + reloc_entry->address;
    307 
    308       switch (howto->size)
    309 	{
    310 	case 0:
    311 	  {
    312 	    char x = bfd_get_8 (abfd, addr);
    313 	    DOIT (x);
    314 	    bfd_put_8 (abfd, x, addr);
    315 	  }
    316 	  break;
    317 
    318 	case 1:
    319 	  {
    320 	    short x = bfd_get_16 (abfd, addr);
    321 	    DOIT (x);
    322 	    bfd_put_16 (abfd, (bfd_vma) x, addr);
    323 	  }
    324 	  break;
    325 
    326 	case 2:
    327 	  {
    328 	    long x = bfd_get_32 (abfd, addr);
    329 	    DOIT (x);
    330 	    bfd_put_32 (abfd, (bfd_vma) x, addr);
    331 	  }
    332 	  break;
    333 
    334 	default:
    335 	  abort ();
    336 	}
    337     }
    338 
    339   /* Now let bfd_perform_relocation finish everything up.  */
    340   return bfd_reloc_continue;
    341 }
    342 
    343 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
    344    the object file contains the value of the common symbol.  By the
    345    time this is called, the linker may be using a different symbol
    346    from a different object file with a different value.  Therefore, we
    347    hack wildly to locate the original symbol from this file so that we
    348    can make the correct adjustment.  This macro sets coffsym to the
    349    symbol from the original file, and uses it to set the addend value
    350    correctly.  If this is not a common symbol, the usual addend
    351    calculation is done, except that an additional tweak is needed for
    352    PC relative relocs.
    353    FIXME: This macro refers to symbols and asect; these are from the
    354    calling function, not the macro arguments.  */
    355 
    356 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)		\
    357   {								\
    358     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;	\
    359     if (ptr && bfd_asymbol_bfd (ptr) != abfd)			\
    360       coffsym = (obj_symbols (abfd)				\
    361 	         + (cache_ptr->sym_ptr_ptr - symbols));		\
    362     else if (ptr)						\
    363       coffsym = coff_symbol_from (abfd, ptr);			\
    364     if (coffsym != (coff_symbol_type *) NULL			\
    365 	&& coffsym->native->u.syment.n_scnum == 0)		\
    366       cache_ptr->addend = - coffsym->native->u.syment.n_value;	\
    367     else if (ptr && bfd_asymbol_bfd (ptr) == abfd		\
    368 	     && ptr->section != (asection *) NULL)		\
    369       cache_ptr->addend = - (ptr->section->vma + ptr->value);	\
    370     else							\
    371       cache_ptr->addend = 0;					\
    372     if (ptr && (reloc.r_type == R_PCRBYTE			\
    373 		|| reloc.r_type == R_PCRWORD			\
    374 		|| reloc.r_type == R_PCRLONG))			\
    375       cache_ptr->addend += asect->vma;				\
    376   }
    377 
    378 #ifndef coff_rtype_to_howto
    379 
    380 /* coff-m68k.c uses the special COFF backend linker.  We need to
    381    adjust common symbols.  */
    382 
    383 static reloc_howto_type *
    384 m68kcoff_common_addend_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
    385 				       asection *sec,
    386 				       struct internal_reloc *rel,
    387 				       struct coff_link_hash_entry *h,
    388 				       struct internal_syment *sym,
    389 				       bfd_vma *addendp)
    390 {
    391   arelent relent;
    392   reloc_howto_type *howto;
    393 
    394   relent.howto = NULL;
    395   RTYPE2HOWTO (&relent, rel);
    396 
    397   howto = relent.howto;
    398 
    399   if (howto->pc_relative)
    400     *addendp += sec->vma;
    401 
    402   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
    403     {
    404       /* This is a common symbol.  The section contents include the
    405 	 size (sym->n_value) as an addend.  The relocate_section
    406 	 function will be adding in the final value of the symbol.  We
    407 	 need to subtract out the current size in order to get the
    408 	 correct result.  */
    409       BFD_ASSERT (h != NULL);
    410       *addendp -= sym->n_value;
    411     }
    412 
    413   /* If the output symbol is common (in which case this must be a
    414      relocatable link), we need to add in the final size of the
    415      common symbol.  */
    416   if (h != NULL && h->root.type == bfd_link_hash_common)
    417     *addendp += h->root.u.c.size;
    418 
    419   return howto;
    420 }
    421 
    422 #define coff_rtype_to_howto m68kcoff_common_addend_rtype_to_howto
    423 
    424 #endif /* ! defined (coff_rtype_to_howto) */
    425 
    426 #endif /* COFF_COMMON_ADDEND */
    427 
    428 #if !defined ONLY_DECLARE_RELOCS && ! defined STATIC_RELOCS
    429 /* Given a .data section and a .emreloc in-memory section, store
    430    relocation information into the .emreloc section which can be
    431    used at runtime to relocate the section.  This is called by the
    432    linker when the --embedded-relocs switch is used.  This is called
    433    after the add_symbols entry point has been called for all the
    434    objects, and before the final_link entry point is called.  */
    435 
    436 bfd_boolean
    437 bfd_m68k_coff_create_embedded_relocs (bfd *abfd,
    438 				      struct bfd_link_info *info,
    439 				      asection *datasec,
    440 				      asection *relsec,
    441 				      char **errmsg)
    442 {
    443   char *extsyms;
    444   bfd_size_type symesz;
    445   struct internal_reloc *irel, *irelend;
    446   bfd_byte *p;
    447   bfd_size_type amt;
    448 
    449   BFD_ASSERT (! info->relocatable);
    450 
    451   *errmsg = NULL;
    452 
    453   if (datasec->reloc_count == 0)
    454     return TRUE;
    455 
    456   extsyms = obj_coff_external_syms (abfd);
    457   symesz = bfd_coff_symesz (abfd);
    458 
    459   irel = _bfd_coff_read_internal_relocs (abfd, datasec, TRUE, NULL, FALSE,
    460 					 NULL);
    461   irelend = irel + datasec->reloc_count;
    462 
    463   amt = (bfd_size_type) datasec->reloc_count * 12;
    464   relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
    465   if (relsec->contents == NULL)
    466     return FALSE;
    467 
    468   p = relsec->contents;
    469 
    470   for (; irel < irelend; irel++, p += 12)
    471     {
    472       asection *targetsec;
    473 
    474       /* We are going to write a four byte longword into the runtime
    475        reloc section.  The longword will be the address in the data
    476        section which must be relocated.  It is followed by the name
    477        of the target section NUL-padded or truncated to 8
    478        characters.  */
    479 
    480       /* We can only relocate absolute longword relocs at run time.  */
    481       if (irel->r_type != R_RELLONG)
    482 	{
    483 	  *errmsg = _("unsupported reloc type");
    484 	  bfd_set_error (bfd_error_bad_value);
    485 	  return FALSE;
    486 	}
    487 
    488       if (irel->r_symndx == -1)
    489 	targetsec = bfd_abs_section_ptr;
    490       else
    491 	{
    492 	  struct coff_link_hash_entry *h;
    493 
    494 	  h = obj_coff_sym_hashes (abfd)[irel->r_symndx];
    495 	  if (h == NULL)
    496 	    {
    497 	      struct internal_syment isym;
    498 
    499 	      bfd_coff_swap_sym_in (abfd, extsyms + symesz * irel->r_symndx,
    500 				    &isym);
    501 	      targetsec = coff_section_from_bfd_index (abfd, isym.n_scnum);
    502 	    }
    503 	  else if (h->root.type == bfd_link_hash_defined
    504 		   || h->root.type == bfd_link_hash_defweak)
    505 	    targetsec = h->root.u.def.section;
    506 	  else
    507 	    targetsec = NULL;
    508 	}
    509 
    510       bfd_put_32 (abfd,
    511 		  (irel->r_vaddr - datasec->vma + datasec->output_offset), p);
    512       memset (p + 4, 0, 8);
    513       if (targetsec != NULL)
    514 	strncpy ((char *) p + 4, targetsec->output_section->name, 8);
    515     }
    516 
    517   return TRUE;
    518 }
    519 #endif /* neither ONLY_DECLARE_RELOCS not STATIC_RELOCS  */
    520 
    521 #define coff_bfd_is_local_label_name m68k_coff_is_local_label_name
    523 
    524 #define coff_relocate_section _bfd_coff_generic_relocate_section
    525 
    526 #ifndef bfd_pe_print_pdata
    527 #define bfd_pe_print_pdata	NULL
    528 #endif
    529 
    530 #include "coffcode.h"
    531 
    532 #ifndef TARGET_SYM
    533 #define TARGET_SYM m68k_coff_vec
    534 #endif
    535 
    536 #ifndef TARGET_NAME
    537 #define TARGET_NAME "coff-m68k"
    538 #endif
    539 
    540 #ifdef NAMES_HAVE_UNDERSCORE
    541 CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE)
    542 #else
    543 CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, 0, NULL, COFF_SWAP_TABLE)
    544 #endif
    545