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 = §ion->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