Back to index

cell-binutils  2.17cvs20070401
coff-tic4x.c
Go to the documentation of this file.
00001 /* BFD back-end for TMS320C4X coff binaries.
00002    Copyright 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2005, 2007
00003    Free Software Foundation, Inc.
00004 
00005    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
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
00022    02110-1301, USA.  */
00023 
00024 #include "bfd.h"
00025 #include "sysdep.h"
00026 #include "libbfd.h"
00027 #include "bfdlink.h"
00028 #include "coff/tic4x.h"
00029 #include "coff/internal.h"
00030 #include "libcoff.h"
00031 
00032 #undef  F_LSYMS
00033 #define       F_LSYMS              F_LSYMS_TICOFF
00034 
00035 static bfd_boolean ticoff_bfd_is_local_label_name
00036     PARAMS ((bfd *, const char *));
00037 static bfd_reloc_status_type tic4x_relocation
00038     PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char ** ));
00039 static reloc_howto_type *tic4x_coff_reloc_type_lookup
00040     PARAMS ((bfd *, bfd_reloc_code_real_type ));
00041 static void tic4x_lookup_howto
00042     PARAMS ((arelent *, struct internal_reloc * ));
00043 static reloc_howto_type *coff_tic4x_rtype_to_howto
00044     PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma * ));
00045 static void tic4x_reloc_processing
00046     PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection * ));
00047 
00048 
00049 /* Replace the stock _bfd_coff_is_local_label_name to recognize TI COFF local
00050    labels.  */
00051 static bfd_boolean
00052 ticoff_bfd_is_local_label_name (abfd, name)
00053   bfd *abfd ATTRIBUTE_UNUSED;
00054   const char *name;
00055 {
00056   if (TICOFF_LOCAL_LABEL_P(name))
00057     return TRUE;
00058   return FALSE;
00059 }
00060 
00061 #define coff_bfd_is_local_label_name ticoff_bfd_is_local_label_name
00062 
00063 #define RELOC_PROCESSING(RELENT,RELOC,SYMS,ABFD,SECT)\
00064  tic4x_reloc_processing (RELENT,RELOC,SYMS,ABFD,SECT)
00065 
00066 /* Customize coffcode.h; the default coff_ functions are set up to use
00067    COFF2; coff_bad_format_hook uses BADMAG, so set that for COFF2.
00068    The COFF1 and COFF0 vectors use custom _bad_format_hook procs
00069    instead of setting BADMAG.  */
00070 #define BADMAG(x) COFF2_BADMAG(x)
00071 
00072 #undef coff_rtype_to_howto
00073 #define coff_rtype_to_howto coff_tic4x_rtype_to_howto
00074 
00075 #include "coffcode.h"
00076 
00077 static bfd_reloc_status_type
00078 tic4x_relocation (abfd, reloc_entry, symbol, data, input_section,
00079                 output_bfd, error_message)
00080   bfd *abfd ATTRIBUTE_UNUSED;
00081   arelent *reloc_entry;
00082   asymbol *symbol ATTRIBUTE_UNUSED;
00083   PTR data ATTRIBUTE_UNUSED;
00084   asection *input_section;
00085   bfd *output_bfd;
00086   char **error_message ATTRIBUTE_UNUSED;
00087 {
00088   if (output_bfd != (bfd *) NULL)
00089     {
00090       /* This is a partial relocation, and we want to apply the
00091         relocation to the reloc entry rather than the raw data.
00092         Modify the reloc inplace to reflect what we now know.  */
00093       reloc_entry->address += input_section->output_offset;
00094       return bfd_reloc_ok;
00095     }
00096   return bfd_reloc_continue;
00097 }
00098 
00099 reloc_howto_type tic4x_howto_table[] =
00100 {
00101     HOWTO(R_RELWORD,  0,  2, 16, FALSE, 0, complain_overflow_signed,   tic4x_relocation, "RELWORD",   TRUE, 0x0000ffff, 0x0000ffff, FALSE),
00102     HOWTO(R_REL24,    0,  2, 24, FALSE, 0, complain_overflow_bitfield, tic4x_relocation, "REL24",     TRUE, 0x00ffffff, 0x00ffffff, FALSE),
00103     HOWTO(R_RELLONG,  0,  2, 32, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "RELLONG",   TRUE, 0xffffffff, 0xffffffff, FALSE),
00104     HOWTO(R_PCRWORD,  0,  2, 16, TRUE,  0, complain_overflow_signed,   tic4x_relocation, "PCRWORD",   TRUE, 0x0000ffff, 0x0000ffff, FALSE),
00105     HOWTO(R_PCR24,    0,  2, 24, TRUE,  0, complain_overflow_signed,   tic4x_relocation, "PCR24",     TRUE, 0x00ffffff, 0x00ffffff, FALSE),
00106     HOWTO(R_PARTLS16,        0,  2, 16, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "PARTLS16",  TRUE, 0x0000ffff, 0x0000ffff, FALSE),
00107     HOWTO(R_PARTMS8, 16,  2, 16, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "PARTMS8",   TRUE, 0x0000ffff, 0x0000ffff, FALSE),
00108     HOWTO(R_RELWORD,  0,  2, 16, FALSE, 0, complain_overflow_signed,   tic4x_relocation, "ARELWORD",  TRUE, 0x0000ffff, 0x0000ffff, FALSE),
00109     HOWTO(R_REL24,    0,  2, 24, FALSE, 0, complain_overflow_signed,   tic4x_relocation, "AREL24",    TRUE, 0x00ffffff, 0x00ffffff, FALSE),
00110     HOWTO(R_RELLONG,  0,  2, 32, FALSE, 0, complain_overflow_signed,   tic4x_relocation, "ARELLONG",  TRUE, 0xffffffff, 0xffffffff, FALSE),
00111     HOWTO(R_PCRWORD,  0,  2, 16, TRUE,  0, complain_overflow_signed,   tic4x_relocation, "APCRWORD",  TRUE, 0x0000ffff, 0x0000ffff, FALSE),
00112     HOWTO(R_PCR24,    0,  2, 24, TRUE,  0, complain_overflow_signed,   tic4x_relocation, "APCR24",    TRUE, 0x00ffffff, 0x00ffffff, FALSE),
00113     HOWTO(R_PARTLS16,        0,  2, 16, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "APARTLS16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
00114     HOWTO(R_PARTMS8, 16,  2, 16, FALSE, 0, complain_overflow_dont,     tic4x_relocation, "APARTMS8",  TRUE, 0x0000ffff, 0x0000ffff, FALSE),
00115 };
00116 #define HOWTO_SIZE (sizeof(tic4x_howto_table) / sizeof(tic4x_howto_table[0]))
00117 
00118 #undef coff_bfd_reloc_type_lookup
00119 #define coff_bfd_reloc_type_lookup tic4x_coff_reloc_type_lookup
00120 #undef coff_bfd_reloc_name_lookup
00121 #define coff_bfd_reloc_name_lookup tic4x_coff_reloc_name_lookup
00122 
00123 /* For the case statement use the code values used tc_gen_reloc (defined in
00124    bfd/reloc.c) to map to the howto table entries.  */
00125 
00126 static reloc_howto_type *
00127 tic4x_coff_reloc_type_lookup (abfd, code)
00128     bfd *abfd ATTRIBUTE_UNUSED;
00129     bfd_reloc_code_real_type code;
00130 {
00131   unsigned int type;
00132   unsigned int i;
00133 
00134   switch (code)
00135     {
00136     case BFD_RELOC_32:             type = R_RELLONG; break;
00137     case BFD_RELOC_24:             type = R_REL24; break;
00138     case BFD_RELOC_16:             type = R_RELWORD; break;
00139     case BFD_RELOC_24_PCREL:       type = R_PCR24; break;
00140     case BFD_RELOC_16_PCREL:       type = R_PCRWORD; break;
00141     case BFD_RELOC_HI16:    type = R_PARTMS8; break;
00142     case BFD_RELOC_LO16:    type = R_PARTLS16; break;
00143     default:
00144       return NULL;
00145     }
00146 
00147   for (i = 0; i < HOWTO_SIZE; i++)
00148     {
00149       if (tic4x_howto_table[i].type == type)
00150        return tic4x_howto_table + i;
00151     }
00152   return NULL;
00153 }
00154 
00155 static reloc_howto_type *
00156 tic4x_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00157                            const char *r_name)
00158 {
00159   unsigned int i;
00160 
00161   for (i = 0;
00162        i < sizeof (tic4x_howto_table) / sizeof (tic4x_howto_table[0]);
00163        i++)
00164     if (tic4x_howto_table[i].name != NULL
00165        && strcasecmp (tic4x_howto_table[i].name, r_name) == 0)
00166       return &tic4x_howto_table[i];
00167 
00168   return NULL;
00169 }
00170 
00171 /* Code to turn a r_type into a howto ptr, uses the above howto table.
00172    Called after some initial checking by the tic4x_rtype_to_howto fn
00173    below.  */
00174 static void
00175 tic4x_lookup_howto (internal, dst)
00176      arelent *internal;
00177      struct internal_reloc *dst;
00178 {
00179   unsigned int i;
00180   int bank = (dst->r_symndx == -1) ? HOWTO_BANK : 0;
00181 
00182   for (i = 0; i < HOWTO_SIZE; i++)
00183     {
00184       if (tic4x_howto_table[i].type == dst->r_type)
00185        {
00186          internal->howto = tic4x_howto_table + i + bank;
00187          return;
00188        }
00189     }
00190 
00191   (*_bfd_error_handler) (_("Unrecognized reloc type 0x%x"),
00192                       (unsigned int) dst->r_type);
00193   abort();
00194 }
00195 
00196 static reloc_howto_type *
00197 coff_tic4x_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00198      bfd *abfd ATTRIBUTE_UNUSED;
00199      asection *sec;
00200      struct internal_reloc *rel;
00201      struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
00202      struct internal_syment *sym ATTRIBUTE_UNUSED;
00203      bfd_vma *addendp;
00204 {
00205   arelent genrel;
00206 
00207   if (rel->r_symndx == -1 && addendp != NULL)
00208     /* This is a TI "internal relocation", which means that the relocation
00209        amount is the amount by which the current section is being relocated
00210        in the output section.  */
00211     *addendp = (sec->output_section->vma + sec->output_offset) - sec->vma;
00212 
00213   tic4x_lookup_howto (&genrel, rel);
00214 
00215   return genrel.howto;
00216 }
00217 
00218 
00219 static void
00220 tic4x_reloc_processing (relent, reloc, symbols, abfd, section)
00221      arelent *relent;
00222      struct internal_reloc *reloc;
00223      asymbol **symbols;
00224      bfd *abfd;
00225      asection *section;
00226 {
00227   asymbol *ptr;
00228 
00229   relent->address = reloc->r_vaddr;
00230 
00231   if (reloc->r_symndx != -1)
00232     {
00233       if (reloc->r_symndx < 0 || reloc->r_symndx >= obj_conv_table_size (abfd))
00234         {
00235           (*_bfd_error_handler)
00236             (_("%s: warning: illegal symbol index %ld in relocs"),
00237              bfd_get_filename (abfd), reloc->r_symndx);
00238           relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
00239           ptr = NULL;
00240         }
00241       else
00242         {
00243           relent->sym_ptr_ptr = (symbols
00244                                  + obj_convert (abfd)[reloc->r_symndx]);
00245           ptr = *(relent->sym_ptr_ptr);
00246         }
00247     }
00248   else
00249     {
00250       relent->sym_ptr_ptr = section->symbol_ptr_ptr;
00251       ptr = *(relent->sym_ptr_ptr);
00252     }
00253 
00254   /* The symbols definitions that we have read in have been relocated
00255      as if their sections started at 0.  But the offsets refering to
00256      the symbols in the raw data have not been modified, so we have to
00257      have a negative addend to compensate.
00258 
00259      Note that symbols which used to be common must be left alone.  */
00260 
00261   /* Calculate any reloc addend by looking at the symbol.  */
00262   CALC_ADDEND (abfd, ptr, *reloc, relent);
00263 
00264   relent->address -= section->vma;
00265   /* !!     relent->section = (asection *) NULL;  */
00266 
00267   /* Fill in the relent->howto field from reloc->r_type.  */
00268   tic4x_lookup_howto (relent, reloc);
00269 }
00270 
00271 
00272 /* TI COFF v0, DOS tools (little-endian headers).  */
00273 CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff0_vec, "coff0-tic4x", HAS_LOAD_PAGE, 0, '_', NULL, (PTR)&ticoff0_swap_table);
00274 
00275 /* TI COFF v0, SPARC tools (big-endian headers).  */
00276 CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff0_beh_vec, "coff0-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff0_vec, (PTR)&ticoff0_swap_table);
00277 
00278 /* TI COFF v1, DOS tools (little-endian headers).  */
00279 CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff1_vec, "coff1-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff0_beh_vec, (PTR)&ticoff1_swap_table);
00280 
00281 /* TI COFF v1, SPARC tools (big-endian headers).  */
00282 CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff1_beh_vec, "coff1-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff1_vec, (PTR)&ticoff1_swap_table);
00283 
00284 /* TI COFF v2, TI DOS tools output (little-endian headers).  */
00285 CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff2_vec, "coff2-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff1_beh_vec, COFF_SWAP_TABLE);
00286 
00287 /* TI COFF v2, TI SPARC tools output (big-endian headers).  */
00288 CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff2_beh_vec, "coff2-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff2_vec, COFF_SWAP_TABLE);