0edd8341ff61ebac52b46828248af43300287209
[deliverable/binutils-gdb.git] / bfd / coff-tic4x.c
1 /* BFD back-end for TMS320C4X coff binaries.
2 Copyright 1996, 1997, 1998, 1999, 2000, 2002, 2003
3 Free Software Foundation, Inc.
4
5 Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
6
7 This file is part of BFD, the Binary File Descriptor library.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA. */
23
24 #include "bfd.h"
25 #include "sysdep.h"
26 #include "libbfd.h"
27 #include "bfdlink.h"
28 #include "coff/tic4x.h"
29 #include "coff/internal.h"
30 #include "libcoff.h"
31
32 #undef F_LSYMS
33 #define F_LSYMS F_LSYMS_TICOFF
34
35 static bfd_boolean ticoff0_bad_format_hook
36 PARAMS ((bfd *, PTR ));
37 static bfd_boolean ticoff1_bad_format_hook
38 PARAMS ((bfd *, PTR ));
39 static bfd_boolean ticoff_bfd_is_local_label_name
40 PARAMS ((bfd *, const char *));
41 static bfd_reloc_status_type tic4x_relocation
42 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char ** ));
43 static reloc_howto_type *tic4x_coff_reloc_type_lookup
44 PARAMS ((bfd *, bfd_reloc_code_real_type ));
45 static void tic4x_lookup_howto
46 PARAMS ((arelent *, struct internal_reloc * ));
47 static reloc_howto_type *coff_tic4x_rtype_to_howto
48 PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma * ));
49 static void tic4x_reloc_processing
50 PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection * ));
51
52
53 static bfd_boolean
54 ticoff0_bad_format_hook (abfd, filehdr)
55 bfd *abfd ATTRIBUTE_UNUSED;
56 PTR filehdr;
57 {
58 struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
59
60 if (COFF0_BADMAG (*internal_f))
61 return FALSE;
62
63 return TRUE;
64 }
65
66 static bfd_boolean
67 ticoff1_bad_format_hook (abfd, filehdr)
68 bfd *abfd ATTRIBUTE_UNUSED;
69 PTR filehdr;
70 {
71 struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
72
73 if (COFF1_BADMAG (*internal_f))
74 return FALSE;
75
76 return TRUE;
77 }
78
79 /* Replace the stock _bfd_coff_is_local_label_name to recognize TI COFF local
80 labels. */
81 static bfd_boolean
82 ticoff_bfd_is_local_label_name (abfd, name)
83 bfd *abfd ATTRIBUTE_UNUSED;
84 const char *name;
85 {
86 if (TICOFF_LOCAL_LABEL_P(name))
87 return TRUE;
88 return FALSE;
89 }
90
91 #define coff_bfd_is_local_label_name ticoff_bfd_is_local_label_name
92
93 #define RELOC_PROCESSING(RELENT,RELOC,SYMS,ABFD,SECT)\
94 tic4x_reloc_processing (RELENT,RELOC,SYMS,ABFD,SECT)
95
96 /* Customize coffcode.h; the default coff_ functions are set up to use
97 COFF2; coff_bad_format_hook uses BADMAG, so set that for COFF2.
98 The COFF1 and COFF0 vectors use custom _bad_format_hook procs
99 instead of setting BADMAG. */
100 #define BADMAG(x) COFF2_BADMAG(x)
101 #include "coffcode.h"
102
103 static bfd_reloc_status_type
104 tic4x_relocation (abfd, reloc_entry, symbol, data, input_section,
105 output_bfd, error_message)
106 bfd *abfd ATTRIBUTE_UNUSED;
107 arelent *reloc_entry;
108 asymbol *symbol ATTRIBUTE_UNUSED;
109 PTR data ATTRIBUTE_UNUSED;
110 asection *input_section;
111 bfd *output_bfd;
112 char **error_message ATTRIBUTE_UNUSED;
113 {
114 if (output_bfd != (bfd *) NULL)
115 {
116 /* This is a partial relocation, and we want to apply the
117 relocation to the reloc entry rather than the raw data.
118 Modify the reloc inplace to reflect what we now know. */
119 reloc_entry->address += input_section->output_offset;
120 return bfd_reloc_ok;
121 }
122 return bfd_reloc_continue;
123 }
124
125 reloc_howto_type tic4x_howto_table[] =
126 {
127 HOWTO(R_RELWORD, 0, 2, 16, FALSE, 0, complain_overflow_signed, tic4x_relocation, "RELWORD", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
128 HOWTO(R_REL24, 0, 2, 24, FALSE, 0, complain_overflow_bitfield, tic4x_relocation, "REL24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
129 HOWTO(R_RELLONG, 0, 2, 32, FALSE, 0, complain_overflow_dont, tic4x_relocation, "RELLONG", TRUE, 0xffffffff, 0xffffffff, FALSE),
130 HOWTO(R_PCRWORD, 0, 2, 16, TRUE, 0, complain_overflow_signed, tic4x_relocation, "PCRWORD", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
131 HOWTO(R_PCR24, 0, 2, 24, TRUE, 0, complain_overflow_signed, tic4x_relocation, "PCR24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
132 HOWTO(R_PARTLS16, 0, 2, 16, FALSE, 0, complain_overflow_dont, tic4x_relocation, "PARTLS16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
133 HOWTO(R_PARTMS8, 16, 2, 16, FALSE, 0, complain_overflow_dont, tic4x_relocation, "PARTMS8", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
134 HOWTO(R_RELWORD, 0, 2, 16, FALSE, 0, complain_overflow_signed, tic4x_relocation, "ARELWORD", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
135 HOWTO(R_REL24, 0, 2, 24, FALSE, 0, complain_overflow_signed, tic4x_relocation, "AREL24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
136 HOWTO(R_RELLONG, 0, 2, 32, FALSE, 0, complain_overflow_signed, tic4x_relocation, "ARELLONG", TRUE, 0xffffffff, 0xffffffff, FALSE),
137 HOWTO(R_PCRWORD, 0, 2, 16, TRUE, 0, complain_overflow_signed, tic4x_relocation, "APCRWORD", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
138 HOWTO(R_PCR24, 0, 2, 24, TRUE, 0, complain_overflow_signed, tic4x_relocation, "APCR24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
139 HOWTO(R_PARTLS16, 0, 2, 16, FALSE, 0, complain_overflow_dont, tic4x_relocation, "APARTLS16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
140 HOWTO(R_PARTMS8, 16, 2, 16, FALSE, 0, complain_overflow_dont, tic4x_relocation, "APARTMS8", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
141 };
142 #define HOWTO_SIZE (sizeof(tic4x_howto_table) / sizeof(tic4x_howto_table[0]))
143
144 #undef coff_bfd_reloc_type_lookup
145 #define coff_bfd_reloc_type_lookup tic4x_coff_reloc_type_lookup
146
147 /* For the case statement use the code values used tc_gen_reloc (defined in
148 bfd/reloc.c) to map to the howto table entries. */
149
150 static reloc_howto_type *
151 tic4x_coff_reloc_type_lookup (abfd, code)
152 bfd *abfd ATTRIBUTE_UNUSED;
153 bfd_reloc_code_real_type code;
154 {
155 unsigned int type;
156 unsigned int i;
157
158 switch (code)
159 {
160 case BFD_RELOC_32: type = R_RELLONG; break;
161 case BFD_RELOC_24: type = R_REL24; break;
162 case BFD_RELOC_16: type = R_RELWORD; break;
163 case BFD_RELOC_24_PCREL: type = R_PCR24; break;
164 case BFD_RELOC_16_PCREL: type = R_PCRWORD; break;
165 case BFD_RELOC_HI16: type = R_PARTMS8; break;
166 case BFD_RELOC_LO16: type = R_PARTLS16; break;
167 default:
168 return NULL;
169 }
170
171 for (i = 0; i < HOWTO_SIZE; i++)
172 {
173 if (tic4x_howto_table[i].type == type)
174 return tic4x_howto_table + i;
175 }
176 return NULL;
177 }
178
179
180 /* Code to turn a r_type into a howto ptr, uses the above howto table.
181 Called after some initial checking by the tic4x_rtype_to_howto fn
182 below. */
183 static void
184 tic4x_lookup_howto (internal, dst)
185 arelent *internal;
186 struct internal_reloc *dst;
187 {
188 unsigned int i;
189 int bank = (dst->r_symndx == -1) ? HOWTO_BANK : 0;
190
191 for (i = 0; i < HOWTO_SIZE; i++)
192 {
193 if (tic4x_howto_table[i].type == dst->r_type)
194 {
195 internal->howto = tic4x_howto_table + i + bank;
196 return;
197 }
198 }
199
200 (*_bfd_error_handler) (_("Unrecognized reloc type 0x%x"),
201 (unsigned int) dst->r_type);
202 abort();
203 }
204
205 #undef coff_rtype_to_howto
206 #define coff_rtype_to_howto coff_tic4x_rtype_to_howto
207
208 static reloc_howto_type *
209 coff_tic4x_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
210 bfd *abfd ATTRIBUTE_UNUSED;
211 asection *sec;
212 struct internal_reloc *rel;
213 struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
214 struct internal_syment *sym ATTRIBUTE_UNUSED;
215 bfd_vma *addendp;
216 {
217 arelent genrel;
218
219 if (rel->r_symndx == -1 && addendp != NULL)
220 /* This is a TI "internal relocation", which means that the relocation
221 amount is the amount by which the current section is being relocated
222 in the output section. */
223 *addendp = (sec->output_section->vma + sec->output_offset) - sec->vma;
224
225 tic4x_lookup_howto (&genrel, rel);
226
227 return genrel.howto;
228 }
229
230
231 static void
232 tic4x_reloc_processing (relent, reloc, symbols, abfd, section)
233 arelent *relent;
234 struct internal_reloc *reloc;
235 asymbol **symbols;
236 bfd *abfd;
237 asection *section;
238 {
239 asymbol *ptr;
240
241 relent->address = reloc->r_vaddr;
242
243 if (reloc->r_symndx != -1)
244 {
245 if (reloc->r_symndx < 0 || reloc->r_symndx >= obj_conv_table_size (abfd))
246 {
247 (*_bfd_error_handler)
248 (_("%s: warning: illegal symbol index %ld in relocs"),
249 bfd_get_filename (abfd), reloc->r_symndx);
250 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
251 ptr = NULL;
252 }
253 else
254 {
255 relent->sym_ptr_ptr = (symbols
256 + obj_convert (abfd)[reloc->r_symndx]);
257 ptr = *(relent->sym_ptr_ptr);
258 }
259 }
260 else
261 {
262 relent->sym_ptr_ptr = section->symbol_ptr_ptr;
263 ptr = *(relent->sym_ptr_ptr);
264 }
265
266 /* The symbols definitions that we have read in have been relocated
267 as if their sections started at 0. But the offsets refering to
268 the symbols in the raw data have not been modified, so we have to
269 have a negative addend to compensate.
270
271 Note that symbols which used to be common must be left alone. */
272
273 /* Calculate any reloc addend by looking at the symbol. */
274 CALC_ADDEND (abfd, ptr, *reloc, relent);
275
276 relent->address -= section->vma;
277 /* !! relent->section = (asection *) NULL; */
278
279 /* Fill in the relent->howto field from reloc->r_type. */
280 tic4x_lookup_howto (relent, reloc);
281 }
282
283
284 static const bfd_coff_backend_data ticoff0_swap_table =
285 {
286 coff_SWAP_aux_in, coff_SWAP_sym_in, coff_SWAP_lineno_in,
287 coff_SWAP_aux_out, coff_SWAP_sym_out,
288 coff_SWAP_lineno_out, coff_SWAP_reloc_out,
289 coff_SWAP_filehdr_out, coff_SWAP_aouthdr_out,
290 coff_SWAP_scnhdr_out,
291 FILHSZ_V0, AOUTSZ, SCNHSZ_V01, SYMESZ, AUXESZ, RELSZ_V0, LINESZ, FILNMLEN,
292 #ifdef COFF_LONG_FILENAMES
293 TRUE,
294 #else
295 FALSE,
296 #endif
297 #ifdef COFF_LONG_SECTION_NAMES
298 TRUE,
299 #else
300 FALSE,
301 #endif
302 COFF_DEFAULT_SECTION_ALIGNMENT_POWER,
303 #ifdef COFF_FORCE_SYMBOLS_IN_STRINGS
304 TRUE,
305 #else
306 FALSE,
307 #endif
308 #ifdef COFF_DEBUG_STRING_WIDE_PREFIX
309 4,
310 #else
311 2,
312 #endif
313 coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in,
314 coff_SWAP_reloc_in, ticoff0_bad_format_hook, coff_set_arch_mach_hook,
315 coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
316 coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
317 coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
318 coff_classify_symbol, coff_compute_section_file_positions,
319 coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
320 coff_adjust_symndx, coff_link_add_one_symbol,
321 coff_link_output_has_begun, coff_final_link_postscript
322 };
323
324 /* COFF1 differs in section header size. */
325 static const bfd_coff_backend_data ticoff1_swap_table =
326 {
327 coff_SWAP_aux_in, coff_SWAP_sym_in, coff_SWAP_lineno_in,
328 coff_SWAP_aux_out, coff_SWAP_sym_out,
329 coff_SWAP_lineno_out, coff_SWAP_reloc_out,
330 coff_SWAP_filehdr_out, coff_SWAP_aouthdr_out,
331 coff_SWAP_scnhdr_out,
332 FILHSZ, AOUTSZ, SCNHSZ_V01, SYMESZ, AUXESZ, RELSZ, LINESZ, FILNMLEN,
333 #ifdef COFF_LONG_FILENAMES
334 TRUE,
335 #else
336 FALSE,
337 #endif
338 #ifdef COFF_LONG_SECTION_NAMES
339 TRUE,
340 #else
341 FALSE,
342 #endif
343 COFF_DEFAULT_SECTION_ALIGNMENT_POWER,
344 #ifdef COFF_FORCE_SYMBOLS_IN_STRINGS
345 TRUE,
346 #else
347 FALSE,
348 #endif
349 #ifdef COFF_DEBUG_STRING_WIDE_PREFIX
350 4,
351 #else
352 2,
353 #endif
354 coff_SWAP_filehdr_in, coff_SWAP_aouthdr_in, coff_SWAP_scnhdr_in,
355 coff_SWAP_reloc_in, ticoff1_bad_format_hook, coff_set_arch_mach_hook,
356 coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
357 coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
358 coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
359 coff_classify_symbol, coff_compute_section_file_positions,
360 coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
361 coff_adjust_symndx, coff_link_add_one_symbol,
362 coff_link_output_has_begun, coff_final_link_postscript
363 };
364
365
366
367 /* TI COFF v0, DOS tools (little-endian headers). */
368 CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff0_vec, "coff0-tic4x", HAS_LOAD_PAGE, 0, '_', NULL, (PTR)&ticoff0_swap_table);
369
370 /* TI COFF v0, SPARC tools (big-endian headers). */
371 CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff0_beh_vec, "coff0-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff0_vec, (PTR)&ticoff0_swap_table);
372
373 /* TI COFF v1, DOS tools (little-endian headers). */
374 CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff1_vec, "coff1-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff0_beh_vec, (PTR)&ticoff1_swap_table);
375
376 /* TI COFF v1, SPARC tools (big-endian headers). */
377 CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff1_beh_vec, "coff1-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff1_vec, (PTR)&ticoff1_swap_table);
378
379 /* TI COFF v2, TI DOS tools output (little-endian headers). */
380 CREATE_LITTLE_COFF_TARGET_VEC(tic4x_coff2_vec, "coff2-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff1_beh_vec, COFF_SWAP_TABLE);
381
382 /* TI COFF v2, TI SPARC tools output (big-endian headers). */
383 CREATE_BIGHDR_COFF_TARGET_VEC(tic4x_coff2_beh_vec, "coff2-beh-tic4x", HAS_LOAD_PAGE, 0, '_', &tic4x_coff2_vec, COFF_SWAP_TABLE);
This page took 0.048764 seconds and 4 git commands to generate.