Home | History | Annotate | Line # | Download | only in bfd
coff-tic4x.c revision 1.1
      1  1.1  christos /* BFD back-end for TMS320C4X coff binaries.
      2  1.1  christos    Copyright 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2005, 2007,
      3  1.1  christos    2008, 2012  Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    Contributed by Michael Hayes (m.hayes (at) elec.canterbury.ac.nz)
      6  1.1  christos 
      7  1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      8  1.1  christos 
      9  1.1  christos    This program is free software; you can redistribute it and/or modify
     10  1.1  christos    it under the terms of the GNU General Public License as published by
     11  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12  1.1  christos    (at your option) any later version.
     13  1.1  christos 
     14  1.1  christos    This program is distributed in the hope that it will be useful,
     15  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  1.1  christos    GNU General Public License for more details.
     18  1.1  christos 
     19  1.1  christos    You should have received a copy of the GNU General Public License
     20  1.1  christos    along with this program; if not, write to the Free Software
     21  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
     22  1.1  christos    02110-1301, USA.  */
     23  1.1  christos 
     24  1.1  christos #include "sysdep.h"
     25  1.1  christos #include "bfd.h"
     26  1.1  christos #include "libbfd.h"
     27  1.1  christos #include "bfdlink.h"
     28  1.1  christos #include "coff/tic4x.h"
     29  1.1  christos #include "coff/internal.h"
     30  1.1  christos #include "libcoff.h"
     31  1.1  christos 
     32  1.1  christos #undef  F_LSYMS
     33  1.1  christos #define	F_LSYMS		F_LSYMS_TICOFF
     34  1.1  christos 
     35  1.1  christos static reloc_howto_type *
     36  1.1  christos coff_tic4x_rtype_to_howto (bfd *, asection *, struct internal_reloc *,
     37  1.1  christos 			   struct coff_link_hash_entry *,
     38  1.1  christos 			   struct internal_syment *,  bfd_vma *);
     39  1.1  christos static void
     40  1.1  christos tic4x_reloc_processing (arelent *, struct internal_reloc *,
     41  1.1  christos 			asymbol **, bfd *, asection *);
     42  1.1  christos 
     43  1.1  christos /* Replace the stock _bfd_coff_is_local_label_name to recognize TI COFF local
     44  1.1  christos    labels.  */
     45  1.1  christos static bfd_boolean
     46  1.1  christos ticoff_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
     47  1.1  christos 				const char *name)
     48  1.1  christos {
     49  1.1  christos   if (TICOFF_LOCAL_LABEL_P(name))
     50  1.1  christos     return TRUE;
     51  1.1  christos   return FALSE;
     52  1.1  christos }
     53  1.1  christos 
     54  1.1  christos #define coff_bfd_is_local_label_name ticoff_bfd_is_local_label_name
     55  1.1  christos 
     56  1.1  christos #define RELOC_PROCESSING(RELENT,RELOC,SYMS,ABFD,SECT)\
     57  1.1  christos  tic4x_reloc_processing (RELENT,RELOC,SYMS,ABFD,SECT)
     58  1.1  christos 
     59  1.1  christos /* Customize coffcode.h; the default coff_ functions are set up to use
     60  1.1  christos    COFF2; coff_bad_format_hook uses BADMAG, so set that for COFF2.
     61  1.1  christos    The COFF1 and COFF0 vectors use custom _bad_format_hook procs
     62  1.1  christos    instead of setting BADMAG.  */
     63  1.1  christos #define BADMAG(x) COFF2_BADMAG(x)
     64  1.1  christos 
     65  1.1  christos #undef  coff_rtype_to_howto
     66  1.1  christos #define coff_rtype_to_howto	coff_tic4x_rtype_to_howto
     67  1.1  christos 
     68  1.1  christos #ifndef bfd_pe_print_pdata
     69  1.1  christos #define bfd_pe_print_pdata	NULL
     70  1.1  christos #endif
     71  1.1  christos 
     72  1.1  christos #include "coffcode.h"
     73  1.1  christos 
     74  1.1  christos static bfd_reloc_status_type
     75  1.1  christos tic4x_relocation (bfd *abfd ATTRIBUTE_UNUSED,
     76  1.1  christos 		  arelent *reloc_entry,
     77  1.1  christos 		  asymbol *symbol ATTRIBUTE_UNUSED,
     78  1.1  christos 		  void * data ATTRIBUTE_UNUSED,
     79  1.1  christos 		  asection *input_section,
     80  1.1  christos 		  bfd *output_bfd,
     81  1.1  christos 		  char **error_message ATTRIBUTE_UNUSED)
     82  1.1  christos {
     83  1.1  christos   if (output_bfd != (bfd *) NULL)
     84  1.1  christos     {
     85  1.1  christos       /* This is a partial relocation, and we want to apply the
     86  1.1  christos  	 relocation to the reloc entry rather than the raw data.
     87  1.1  christos  	 Modify the reloc inplace to reflect what we now know.  */
     88  1.1  christos       reloc_entry->address += input_section->output_offset;
     89  1.1  christos       return bfd_reloc_ok;
     90  1.1  christos     }
     91  1.1  christos   return bfd_reloc_continue;
     92  1.1  christos }
     93  1.1  christos 
     94  1.1  christos reloc_howto_type tic4x_howto_table[] =
     95  1.1  christos {
     96  1.1  christos     HOWTO(R_RELWORD,	 0,  2, 16, FALSE, 0, complain_overflow_signed,   tic4x_relocation, "RELWORD",   TRUE, 0x0000ffff, 0x0000ffff, FALSE),
     97  1.1  christos     HOWTO(R_REL24,	 0,  2, 24, FALSE, 0, complain_overflow_bitfield, tic4x_relocation, "REL24",     TRUE, 0x00ffffff, 0x00ffffff, FALSE),
     98  1.1  christos     HOWTO(R_RELLONG,	 0,  2, 32, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "RELLONG",   TRUE, 0xffffffff, 0xffffffff, FALSE),
     99  1.1  christos     HOWTO(R_PCRWORD,	 0,  2, 16, TRUE,  0, complain_overflow_signed,   tic4x_relocation, "PCRWORD",   TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    100  1.1  christos     HOWTO(R_PCR24,	 0,  2, 24, TRUE,  0, complain_overflow_signed,   tic4x_relocation, "PCR24",     TRUE, 0x00ffffff, 0x00ffffff, FALSE),
    101  1.1  christos     HOWTO(R_PARTLS16,	 0,  2, 16, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "PARTLS16",  TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    102  1.1  christos     HOWTO(R_PARTMS8,	16,  2, 16, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "PARTMS8",   TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    103  1.1  christos     HOWTO(R_RELWORD,	 0,  2, 16, FALSE, 0, complain_overflow_signed,   tic4x_relocation, "ARELWORD",  TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    104  1.1  christos     HOWTO(R_REL24,	 0,  2, 24, FALSE, 0, complain_overflow_signed,   tic4x_relocation, "AREL24",    TRUE, 0x00ffffff, 0x00ffffff, FALSE),
    105  1.1  christos     HOWTO(R_RELLONG,	 0,  2, 32, FALSE, 0, complain_overflow_signed,   tic4x_relocation, "ARELLONG",  TRUE, 0xffffffff, 0xffffffff, FALSE),
    106  1.1  christos     HOWTO(R_PCRWORD,	 0,  2, 16, TRUE,  0, complain_overflow_signed,   tic4x_relocation, "APCRWORD",  TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    107  1.1  christos     HOWTO(R_PCR24,	 0,  2, 24, TRUE,  0, complain_overflow_signed,   tic4x_relocation, "APCR24",    TRUE, 0x00ffffff, 0x00ffffff, FALSE),
    108  1.1  christos     HOWTO(R_PARTLS16,	 0,  2, 16, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "APARTLS16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    109  1.1  christos     HOWTO(R_PARTMS8,	16,  2, 16, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "APARTMS8",  TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    110  1.1  christos };
    111  1.1  christos #define HOWTO_SIZE (sizeof(tic4x_howto_table) / sizeof(tic4x_howto_table[0]))
    112  1.1  christos 
    113  1.1  christos #undef coff_bfd_reloc_type_lookup
    114  1.1  christos #define coff_bfd_reloc_type_lookup tic4x_coff_reloc_type_lookup
    115  1.1  christos #undef coff_bfd_reloc_name_lookup
    116  1.1  christos #define coff_bfd_reloc_name_lookup tic4x_coff_reloc_name_lookup
    117  1.1  christos 
    118  1.1  christos /* For the case statement use the code values used tc_gen_reloc (defined in
    119  1.1  christos    bfd/reloc.c) to map to the howto table entries.  */
    120  1.1  christos 
    121  1.1  christos static reloc_howto_type *
    122  1.1  christos tic4x_coff_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    123  1.1  christos 			      bfd_reloc_code_real_type code)
    124  1.1  christos {
    125  1.1  christos   unsigned int type;
    126  1.1  christos   unsigned int i;
    127  1.1  christos 
    128  1.1  christos   switch (code)
    129  1.1  christos     {
    130  1.1  christos     case BFD_RELOC_32:		type = R_RELLONG; break;
    131  1.1  christos     case BFD_RELOC_24:		type = R_REL24; break;
    132  1.1  christos     case BFD_RELOC_16:		type = R_RELWORD; break;
    133  1.1  christos     case BFD_RELOC_24_PCREL:	type = R_PCR24; break;
    134  1.1  christos     case BFD_RELOC_16_PCREL:	type = R_PCRWORD; break;
    135  1.1  christos     case BFD_RELOC_HI16:	type = R_PARTMS8; break;
    136  1.1  christos     case BFD_RELOC_LO16:	type = R_PARTLS16; break;
    137  1.1  christos     default:
    138  1.1  christos       return NULL;
    139  1.1  christos     }
    140  1.1  christos 
    141  1.1  christos   for (i = 0; i < HOWTO_SIZE; i++)
    142  1.1  christos     {
    143  1.1  christos       if (tic4x_howto_table[i].type == type)
    144  1.1  christos 	return tic4x_howto_table + i;
    145  1.1  christos     }
    146  1.1  christos   return NULL;
    147  1.1  christos }
    148  1.1  christos 
    149  1.1  christos static reloc_howto_type *
    150  1.1  christos tic4x_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    151  1.1  christos 			      const char *r_name)
    152  1.1  christos {
    153  1.1  christos   unsigned int i;
    154  1.1  christos 
    155  1.1  christos   for (i = 0;
    156  1.1  christos        i < sizeof (tic4x_howto_table) / sizeof (tic4x_howto_table[0]);
    157  1.1  christos        i++)
    158  1.1  christos     if (tic4x_howto_table[i].name != NULL
    159  1.1  christos 	&& strcasecmp (tic4x_howto_table[i].name, r_name) == 0)
    160  1.1  christos       return &tic4x_howto_table[i];
    161  1.1  christos 
    162  1.1  christos   return NULL;
    163  1.1  christos }
    164  1.1  christos 
    165  1.1  christos /* Code to turn a r_type into a howto ptr, uses the above howto table.
    166  1.1  christos    Called after some initial checking by the tic4x_rtype_to_howto fn
    167  1.1  christos    below.  */
    168  1.1  christos static void
    169  1.1  christos tic4x_lookup_howto (arelent *internal,
    170  1.1  christos 		    struct internal_reloc *dst)
    171  1.1  christos {
    172  1.1  christos   unsigned int i;
    173  1.1  christos   int bank = (dst->r_symndx == -1) ? HOWTO_BANK : 0;
    174  1.1  christos 
    175  1.1  christos   for (i = 0; i < HOWTO_SIZE; i++)
    176  1.1  christos     {
    177  1.1  christos       if (tic4x_howto_table[i].type == dst->r_type)
    178  1.1  christos 	{
    179  1.1  christos 	  internal->howto = tic4x_howto_table + i + bank;
    180  1.1  christos 	  return;
    181  1.1  christos 	}
    182  1.1  christos     }
    183  1.1  christos 
    184  1.1  christos   (*_bfd_error_handler) (_("Unrecognized reloc type 0x%x"),
    185  1.1  christos 			 (unsigned int) dst->r_type);
    186  1.1  christos   abort();
    187  1.1  christos }
    188  1.1  christos 
    189  1.1  christos static reloc_howto_type *
    190  1.1  christos coff_tic4x_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
    191  1.1  christos 			   asection *sec,
    192  1.1  christos 			   struct internal_reloc *rel,
    193  1.1  christos 			   struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
    194  1.1  christos 			   struct internal_syment *sym ATTRIBUTE_UNUSED,
    195  1.1  christos 			   bfd_vma *addendp)
    196  1.1  christos {
    197  1.1  christos   arelent genrel;
    198  1.1  christos 
    199  1.1  christos   if (rel->r_symndx == -1 && addendp != NULL)
    200  1.1  christos     /* This is a TI "internal relocation", which means that the relocation
    201  1.1  christos        amount is the amount by which the current section is being relocated
    202  1.1  christos        in the output section.  */
    203  1.1  christos     *addendp = (sec->output_section->vma + sec->output_offset) - sec->vma;
    204  1.1  christos 
    205  1.1  christos   tic4x_lookup_howto (&genrel, rel);
    206  1.1  christos 
    207  1.1  christos   return genrel.howto;
    208  1.1  christos }
    209  1.1  christos 
    210  1.1  christos 
    211  1.1  christos static void
    212  1.1  christos tic4x_reloc_processing (arelent *relent,
    213  1.1  christos 			struct internal_reloc *reloc,
    214  1.1  christos 			asymbol **symbols,
    215  1.1  christos 			bfd *abfd,
    216  1.1  christos 			asection *section)
    217  1.1  christos {
    218  1.1  christos   asymbol *ptr;
    219  1.1  christos 
    220  1.1  christos   relent->address = reloc->r_vaddr;
    221  1.1  christos 
    222  1.1  christos   if (reloc->r_symndx != -1)
    223  1.1  christos     {
    224  1.1  christos       if (reloc->r_symndx < 0 || reloc->r_symndx >= obj_conv_table_size (abfd))
    225  1.1  christos         {
    226  1.1  christos           (*_bfd_error_handler)
    227  1.1  christos             (_("%s: warning: illegal symbol index %ld in relocs"),
    228  1.1  christos              bfd_get_filename (abfd), reloc->r_symndx);
    229  1.1  christos           relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
    230  1.1  christos           ptr = NULL;
    231  1.1  christos         }
    232  1.1  christos       else
    233  1.1  christos         {
    234  1.1  christos           relent->sym_ptr_ptr = (symbols
    235  1.1  christos                                  + obj_convert (abfd)[reloc->r_symndx]);
    236  1.1  christos           ptr = *(relent->sym_ptr_ptr);
    237  1.1  christos         }
    238  1.1  christos     }
    239  1.1  christos   else
    240  1.1  christos     {
    241  1.1  christos       relent->sym_ptr_ptr = section->symbol_ptr_ptr;
    242  1.1  christos       ptr = *(relent->sym_ptr_ptr);
    243  1.1  christos     }
    244  1.1  christos 
    245  1.1  christos   /* The symbols definitions that we have read in have been relocated
    246  1.1  christos      as if their sections started at 0.  But the offsets refering to
    247  1.1  christos      the symbols in the raw data have not been modified, so we have to
    248  1.1  christos      have a negative addend to compensate.
    249  1.1  christos 
    250  1.1  christos      Note that symbols which used to be common must be left alone.  */
    251  1.1  christos 
    252  1.1  christos   /* Calculate any reloc addend by looking at the symbol.  */
    253  1.1  christos   CALC_ADDEND (abfd, ptr, *reloc, relent);
    254  1.1  christos 
    255  1.1  christos   relent->address -= section->vma;
    256  1.1  christos   /* !!     relent->section = (asection *) NULL;  */
    257  1.1  christos 
    258  1.1  christos   /* Fill in the relent->howto field from reloc->r_type.  */
    259  1.1  christos   tic4x_lookup_howto (relent, reloc);
    260  1.1  christos }
    261  1.1  christos 
    262  1.1  christos 
    263  1.1  christos /* TI COFF v0, DOS tools (little-endian headers).  */
    264  1.1  christos CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff0_vec, "coff0-tic4x", HAS_LOAD_PAGE, 0, '_', NULL, & ticoff0_swap_table);
    265  1.1  christos 
    266  1.1  christos /* TI COFF v0, SPARC tools (big-endian headers).  */
    267  1.1  christos CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff0_beh_vec, "coff0-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff0_vec, & ticoff0_swap_table);
    268  1.1  christos 
    269  1.1  christos /* TI COFF v1, DOS tools (little-endian headers).  */
    270  1.1  christos CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff1_vec, "coff1-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff0_beh_vec, & ticoff1_swap_table);
    271  1.1  christos 
    272  1.1  christos /* TI COFF v1, SPARC tools (big-endian headers).  */
    273  1.1  christos CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff1_beh_vec, "coff1-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff1_vec, & ticoff1_swap_table);
    274  1.1  christos 
    275  1.1  christos /* TI COFF v2, TI DOS tools output (little-endian headers).  */
    276  1.1  christos CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff2_vec, "coff2-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff1_beh_vec, COFF_SWAP_TABLE);
    277  1.1  christos 
    278  1.1  christos /* TI COFF v2, TI SPARC tools output (big-endian headers).  */
    279  1.1  christos CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff2_beh_vec, "coff2-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff2_vec, COFF_SWAP_TABLE);
    280