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