coff-tic4x.c revision 1.6 1 1.1 christos /* BFD back-end for TMS320C4X coff binaries.
2 1.6 christos Copyright (C) 1996-2018 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.1 christos static bfd_boolean
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.1 christos return TRUE;
50 1.1 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.1 christos HOWTO(R_RELWORD, 0, 2, 16, FALSE, 0, complain_overflow_signed, tic4x_relocation, "RELWORD", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
96 1.1 christos HOWTO(R_REL24, 0, 2, 24, FALSE, 0, complain_overflow_bitfield, tic4x_relocation, "REL24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
97 1.1 christos HOWTO(R_RELLONG, 0, 2, 32, FALSE, 0, complain_overflow_dont, tic4x_relocation, "RELLONG", TRUE, 0xffffffff, 0xffffffff, FALSE),
98 1.1 christos HOWTO(R_PCRWORD, 0, 2, 16, TRUE, 0, complain_overflow_signed, tic4x_relocation, "PCRWORD", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
99 1.1 christos HOWTO(R_PCR24, 0, 2, 24, TRUE, 0, complain_overflow_signed, tic4x_relocation, "PCR24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
100 1.1 christos HOWTO(R_PARTLS16, 0, 2, 16, FALSE, 0, complain_overflow_dont, tic4x_relocation, "PARTLS16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
101 1.1 christos HOWTO(R_PARTMS8, 16, 2, 16, FALSE, 0, complain_overflow_dont, tic4x_relocation, "PARTMS8", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
102 1.1 christos HOWTO(R_RELWORD, 0, 2, 16, FALSE, 0, complain_overflow_signed, tic4x_relocation, "ARELWORD", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
103 1.1 christos HOWTO(R_REL24, 0, 2, 24, FALSE, 0, complain_overflow_signed, tic4x_relocation, "AREL24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
104 1.1 christos HOWTO(R_RELLONG, 0, 2, 32, FALSE, 0, complain_overflow_signed, tic4x_relocation, "ARELLONG", TRUE, 0xffffffff, 0xffffffff, FALSE),
105 1.1 christos HOWTO(R_PCRWORD, 0, 2, 16, TRUE, 0, complain_overflow_signed, tic4x_relocation, "APCRWORD", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
106 1.1 christos HOWTO(R_PCR24, 0, 2, 24, TRUE, 0, complain_overflow_signed, tic4x_relocation, "APCR24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
107 1.1 christos HOWTO(R_PARTLS16, 0, 2, 16, FALSE, 0, complain_overflow_dont, tic4x_relocation, "APARTLS16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
108 1.1 christos HOWTO(R_PARTMS8, 16, 2, 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.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.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.6 christos relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
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.1 christos relent->sym_ptr_ptr = section->symbol_ptr_ptr;
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