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