elf32-xgate.c revision 1.1.1.5 1 1.1 christos /* Freescale XGATE-specific support for 32-bit ELF
2 1.1.1.5 christos Copyright (C) 2010-2017 Free Software Foundation, Inc.
3 1.1 christos Contributed by Sean Keys(skeys (at) ipdatasys.com)
4 1.1 christos
5 1.1 christos This file is part of BFD, the Binary File Descriptor library.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; if not, write to the Free Software
19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "sysdep.h"
23 1.1 christos #include "bfd.h"
24 1.1 christos #include "bfdlink.h"
25 1.1 christos #include "libbfd.h"
26 1.1 christos #include "elf-bfd.h"
27 1.1 christos #include "elf32-xgate.h"
28 1.1 christos #include "elf/xgate.h"
29 1.1 christos #include "opcode/xgate.h"
30 1.1 christos #include "libiberty.h"
31 1.1 christos
32 1.1 christos /* Relocation functions. */
33 1.1 christos static reloc_howto_type *
34 1.1 christos bfd_elf32_bfd_reloc_type_lookup (bfd *, bfd_reloc_code_real_type);
35 1.1 christos static reloc_howto_type *
36 1.1 christos bfd_elf32_bfd_reloc_name_lookup (bfd *, const char *);
37 1.1 christos static void
38 1.1 christos xgate_info_to_howto_rel (bfd *, arelent *, Elf_Internal_Rela *);
39 1.1 christos static bfd_boolean
40 1.1 christos xgate_elf_set_mach_from_flags (bfd *);
41 1.1 christos static struct bfd_hash_entry *
42 1.1 christos stub_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *,
43 1.1 christos const char *);
44 1.1 christos static struct bfd_link_hash_table*
45 1.1 christos xgate_elf_bfd_link_hash_table_create (bfd *);
46 1.1 christos
47 1.1 christos /* Use REL instead of RELA to save space */
48 1.1 christos #define USE_REL 1
49 1.1 christos
50 1.1 christos static reloc_howto_type elf_xgate_howto_table[] =
51 1.1 christos {
52 1.1 christos /* This reloc does nothing. */
53 1.1 christos HOWTO (R_XGATE_NONE, /* type */
54 1.1 christos 0, /* rightshift */
55 1.1.1.3 christos 3, /* size (0 = byte, 1 = short, 2 = long) */
56 1.1.1.3 christos 0, /* bitsize */
57 1.1 christos FALSE, /* pc_relative */
58 1.1 christos 0, /* bitpos */
59 1.1 christos complain_overflow_dont,/* complain_on_overflow */
60 1.1 christos bfd_elf_generic_reloc, /* special_function */
61 1.1 christos "R_XGATE_NONE", /* name */
62 1.1 christos FALSE, /* partial_inplace */
63 1.1 christos 0, /* src_mask */
64 1.1 christos 0, /* dst_mask */
65 1.1 christos FALSE), /* pcrel_offset */
66 1.1 christos
67 1.1 christos /* A 8 bit absolute relocation. */
68 1.1 christos HOWTO (R_XGATE_8, /* type */
69 1.1 christos 0, /* rightshift */
70 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
71 1.1 christos 8, /* bitsize */
72 1.1 christos FALSE, /* pc_relative */
73 1.1 christos 0, /* bitpos */
74 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
75 1.1 christos bfd_elf_generic_reloc, /* special_function */
76 1.1 christos "R_XGATE_8", /* name */
77 1.1 christos FALSE, /* partial_inplace */
78 1.1 christos 0x00ff, /* src_mask */
79 1.1 christos 0x00ff, /* dst_mask */
80 1.1 christos FALSE), /* pcrel_offset */
81 1.1 christos
82 1.1 christos /* A 8 bit PC-rel relocation. */
83 1.1 christos HOWTO (R_XGATE_PCREL_8, /* type */
84 1.1 christos 0, /* rightshift */
85 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
86 1.1 christos 8, /* bitsize */
87 1.1 christos TRUE, /* pc_relative */
88 1.1 christos 0, /* bitpos */
89 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
90 1.1 christos bfd_elf_generic_reloc, /* special_function */
91 1.1 christos "R_XGATE_PCREL_8", /* name */
92 1.1 christos FALSE, /* partial_inplace */
93 1.1 christos 0x00ff, /* src_mask */
94 1.1 christos 0x00ff, /* dst_mask */
95 1.1 christos TRUE), /* pcrel_offset */
96 1.1 christos
97 1.1 christos /* A 16 bit absolute relocation. */
98 1.1 christos HOWTO (R_XGATE_16, /* type */
99 1.1 christos 0, /* rightshift */
100 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
101 1.1 christos 16, /* bitsize */
102 1.1 christos FALSE, /* pc_relative */
103 1.1 christos 0, /* bitpos */
104 1.1 christos complain_overflow_dont /*bitfield */, /* complain_on_overflow */
105 1.1 christos bfd_elf_generic_reloc, /* special_function */
106 1.1 christos "R_XGATE_16", /* name */
107 1.1 christos FALSE, /* partial_inplace */
108 1.1 christos 0xffff, /* src_mask */
109 1.1 christos 0xffff, /* dst_mask */
110 1.1 christos FALSE), /* pcrel_offset */
111 1.1 christos
112 1.1 christos /* A 32 bit absolute relocation. This one is never used for the
113 1.1 christos code relocation. It's used by gas for -gstabs generation. */
114 1.1 christos HOWTO (R_XGATE_32, /* type */
115 1.1 christos 0, /* rightshift */
116 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
117 1.1 christos 32, /* bitsize */
118 1.1 christos FALSE, /* pc_relative */
119 1.1 christos 0, /* bitpos */
120 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
121 1.1 christos bfd_elf_generic_reloc, /* special_function */
122 1.1 christos "R_XGATE_32", /* name */
123 1.1 christos FALSE, /* partial_inplace */
124 1.1 christos 0xffffffff, /* src_mask */
125 1.1 christos 0xffffffff, /* dst_mask */
126 1.1 christos FALSE), /* pcrel_offset */
127 1.1 christos
128 1.1 christos /* A 16 bit PC-rel relocation. */
129 1.1 christos HOWTO (R_XGATE_PCREL_16, /* type */
130 1.1 christos 0, /* rightshift */
131 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
132 1.1 christos 16, /* bitsize */
133 1.1 christos TRUE, /* pc_relative */
134 1.1 christos 0, /* bitpos */
135 1.1 christos complain_overflow_dont, /* complain_on_overflow */
136 1.1 christos bfd_elf_generic_reloc, /* special_function */
137 1.1 christos "R_XGATE_PCREL_16", /* name */
138 1.1 christos FALSE, /* partial_inplace */
139 1.1 christos 0xffff, /* src_mask */
140 1.1 christos 0xffff, /* dst_mask */
141 1.1 christos TRUE), /* pcrel_offset */
142 1.1 christos
143 1.1 christos /* GNU extension to record C++ vtable hierarchy. */
144 1.1 christos HOWTO (R_XGATE_GNU_VTINHERIT, /* type */
145 1.1 christos 0, /* rightshift */
146 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
147 1.1 christos 0, /* bitsize */
148 1.1 christos FALSE, /* pc_relative */
149 1.1 christos 0, /* bitpos */
150 1.1 christos complain_overflow_dont, /* complain_on_overflow */
151 1.1 christos NULL, /* special_function */
152 1.1 christos "R_XGATE_GNU_VTINHERIT", /* name */
153 1.1 christos FALSE, /* partial_inplace */
154 1.1 christos 0, /* src_mask */
155 1.1 christos 0, /* dst_mask */
156 1.1 christos FALSE), /* pcrel_offset */
157 1.1 christos
158 1.1 christos /* GNU extension to record C++ vtable member usage. */
159 1.1 christos HOWTO (R_XGATE_GNU_VTENTRY, /* type */
160 1.1 christos 0, /* rightshift */
161 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
162 1.1 christos 0, /* bitsize */
163 1.1 christos FALSE, /* pc_relative */
164 1.1 christos 0, /* bitpos */
165 1.1 christos complain_overflow_dont, /* complain_on_overflow */
166 1.1 christos _bfd_elf_rel_vtable_reloc_fn, /* special_function */
167 1.1 christos "R_XGATE_GNU_VTENTRY", /* name */
168 1.1 christos FALSE, /* partial_inplace */
169 1.1 christos 0, /* src_mask */
170 1.1 christos 0, /* dst_mask */
171 1.1 christos FALSE), /* pcrel_offset */
172 1.1 christos
173 1.1 christos /* A 24 bit relocation. */
174 1.1 christos HOWTO (R_XGATE_24, /* type */
175 1.1 christos 0, /* rightshift */
176 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
177 1.1 christos 16, /* bitsize */
178 1.1 christos FALSE, /* pc_relative */
179 1.1 christos 0, /* bitpos */
180 1.1 christos complain_overflow_dont, /* complain_on_overflow */
181 1.1 christos bfd_elf_generic_reloc, /* special_function */
182 1.1 christos "R_XGATE_IMM8_LO", /* name */
183 1.1 christos FALSE, /* partial_inplace */
184 1.1 christos 0x00ff, /* src_mask */
185 1.1 christos 0x00ff, /* dst_mask */
186 1.1 christos FALSE), /* pcrel_offset */
187 1.1 christos
188 1.1 christos /* A 16-bit low relocation. */
189 1.1 christos HOWTO (R_XGATE_LO16, /* type */
190 1.1 christos 8, /* rightshift */
191 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
192 1.1 christos 16, /* bitsize */
193 1.1 christos FALSE, /* pc_relative */
194 1.1 christos 0, /* bitpos */
195 1.1 christos complain_overflow_dont, /* complain_on_overflow */
196 1.1 christos bfd_elf_generic_reloc, /* special_function */
197 1.1 christos "R_XGATE_IMM8_HI", /* name */
198 1.1 christos FALSE, /* partial_inplace */
199 1.1 christos 0x00ff, /* src_mask */
200 1.1 christos 0x00ff, /* dst_mask */
201 1.1 christos FALSE), /* pcrel_offset */
202 1.1 christos
203 1.1 christos /* A page relocation. */
204 1.1 christos HOWTO (R_XGATE_GPAGE, /* type */
205 1.1 christos 0, /* rightshift */
206 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
207 1.1 christos 8, /* bitsize */
208 1.1 christos FALSE, /* pc_relative */
209 1.1 christos 0, /* bitpos */
210 1.1 christos complain_overflow_dont, /* complain_on_overflow */
211 1.1 christos xgate_elf_special_reloc,/* special_function */
212 1.1 christos "R_XGATE_GPAGE", /* name */
213 1.1 christos FALSE, /* partial_inplace */
214 1.1 christos 0x00ff, /* src_mask */
215 1.1 christos 0x00ff, /* dst_mask */
216 1.1 christos FALSE), /* pcrel_offset */
217 1.1 christos
218 1.1 christos /* A 9 bit absolute relocation. */
219 1.1 christos HOWTO (R_XGATE_PCREL_9, /* type */
220 1.1 christos 0, /* rightshift */
221 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
222 1.1 christos 9, /* bitsize */
223 1.1 christos TRUE, /* pc_relative */
224 1.1 christos 0, /* bitpos */
225 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
226 1.1 christos bfd_elf_generic_reloc, /* special_function */
227 1.1 christos "R_XGATE_PCREL_9", /* name */
228 1.1 christos FALSE, /* partial_inplace */
229 1.1 christos 0xffff, /* src_mask */
230 1.1 christos 0xffff, /* dst_mask */
231 1.1 christos TRUE), /* pcrel_offset */
232 1.1 christos
233 1.1 christos /* A 8 bit absolute relocation (upper address). */
234 1.1 christos HOWTO (R_XGATE_PCREL_10, /* type */
235 1.1 christos 8, /* rightshift */
236 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
237 1.1 christos 10, /* bitsize */
238 1.1 christos TRUE, /* pc_relative */
239 1.1 christos 0, /* bitpos */
240 1.1 christos complain_overflow_dont, /* complain_on_overflow */
241 1.1 christos bfd_elf_generic_reloc, /* special_function */
242 1.1 christos "R_XGATE_PCREL_10", /* name */
243 1.1 christos FALSE, /* partial_inplace */
244 1.1 christos 0x00ff, /* src_mask */
245 1.1 christos 0x00ff, /* dst_mask */
246 1.1 christos TRUE), /* pcrel_offset */
247 1.1 christos
248 1.1 christos /* A 8 bit absolute relocation. */
249 1.1 christos HOWTO (R_XGATE_IMM8_LO, /* type */
250 1.1 christos 0, /* rightshift */
251 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
252 1.1 christos 16, /* bitsize */
253 1.1 christos FALSE, /* pc_relative */
254 1.1 christos 0, /* bitpos */
255 1.1 christos complain_overflow_dont, /* complain_on_overflow */
256 1.1 christos bfd_elf_generic_reloc, /* special_function */
257 1.1 christos "R_XGATE_IMM8_LO", /* name */
258 1.1 christos FALSE, /* partial_inplace */
259 1.1 christos 0xffff, /* src_mask */
260 1.1 christos 0xffff, /* dst_mask */
261 1.1 christos FALSE), /* pcrel_offset */
262 1.1 christos
263 1.1 christos /* A 16 bit absolute relocation (upper address). */
264 1.1 christos HOWTO (R_XGATE_IMM8_HI, /* type */
265 1.1 christos 8, /* rightshift */
266 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
267 1.1 christos 16, /* bitsize */
268 1.1 christos FALSE, /* pc_relative */
269 1.1 christos 0, /* bitpos */
270 1.1 christos complain_overflow_dont, /* complain_on_overflow */
271 1.1 christos bfd_elf_generic_reloc, /* special_function */
272 1.1 christos "R_XGATE_IMM8_HI", /* name */
273 1.1 christos FALSE, /* partial_inplace */
274 1.1 christos 0x00ff, /* src_mask */
275 1.1 christos 0x00ff, /* dst_mask */
276 1.1 christos FALSE), /* pcrel_offset */
277 1.1 christos
278 1.1 christos /* A 3 bit absolute relocation. */
279 1.1 christos HOWTO (R_XGATE_IMM3, /* type */
280 1.1 christos 8, /* rightshift */
281 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
282 1.1 christos 16, /* bitsize */
283 1.1 christos FALSE, /* pc_relative */
284 1.1 christos 0, /* bitpos */
285 1.1 christos complain_overflow_dont, /* complain_on_overflow */
286 1.1 christos bfd_elf_generic_reloc, /* special_function */
287 1.1 christos "R_XGATE_IMM3", /* name */
288 1.1 christos FALSE, /* partial_inplace */
289 1.1 christos 0x00ff, /* src_mask */
290 1.1 christos 0x00ff, /* dst_mask */
291 1.1 christos FALSE), /* pcrel_offset */
292 1.1 christos
293 1.1 christos /* A 4 bit absolute relocation. */
294 1.1 christos HOWTO (R_XGATE_IMM4, /* type */
295 1.1 christos 8, /* rightshift */
296 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
297 1.1 christos 16, /* bitsize */
298 1.1 christos FALSE, /* pc_relative */
299 1.1 christos 0, /* bitpos */
300 1.1 christos complain_overflow_dont, /* complain_on_overflow */
301 1.1 christos bfd_elf_generic_reloc, /* special_function */
302 1.1 christos "R_XGATE_IMM4", /* name */
303 1.1 christos FALSE, /* partial_inplace */
304 1.1 christos 0x00ff, /* src_mask */
305 1.1 christos 0x00ff, /* dst_mask */
306 1.1 christos FALSE), /* pcrel_offset */
307 1.1 christos
308 1.1 christos /* A 5 bit absolute relocation. */
309 1.1 christos HOWTO (R_XGATE_IMM5, /* type */
310 1.1 christos 8, /* rightshift */
311 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
312 1.1 christos 16, /* bitsize */
313 1.1 christos FALSE, /* pc_relative */
314 1.1 christos 0, /* bitpos */
315 1.1 christos complain_overflow_dont, /* complain_on_overflow */
316 1.1 christos bfd_elf_generic_reloc, /* special_function */
317 1.1 christos "R_XGATE_IMM5", /* name */
318 1.1 christos FALSE, /* partial_inplace */
319 1.1 christos 0x00ff, /* src_mask */
320 1.1 christos 0x00ff, /* dst_mask */
321 1.1 christos FALSE), /* pcrel_offset */
322 1.1 christos
323 1.1 christos /* Mark beginning of a jump instruction (any form). */
324 1.1 christos HOWTO (R_XGATE_RL_JUMP, /* type */
325 1.1 christos 0, /* rightshift */
326 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
327 1.1 christos 0, /* bitsize */
328 1.1 christos FALSE, /* pc_relative */
329 1.1 christos 0, /* bitpos */
330 1.1 christos complain_overflow_dont, /* complain_on_overflow */
331 1.1 christos xgate_elf_ignore_reloc, /* special_function */
332 1.1 christos "R_XGATE_RL_JUMP", /* name */
333 1.1 christos TRUE, /* partial_inplace */
334 1.1 christos 0, /* src_mask */
335 1.1 christos 0, /* dst_mask */
336 1.1 christos TRUE), /* pcrel_offset */
337 1.1 christos
338 1.1 christos /* Mark beginning of Gcc relaxation group instruction. */
339 1.1 christos HOWTO (R_XGATE_RL_GROUP, /* type */
340 1.1 christos 0, /* rightshift */
341 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
342 1.1 christos 0, /* bitsize */
343 1.1 christos FALSE, /* pc_relative */
344 1.1 christos 0, /* bitpos */
345 1.1 christos complain_overflow_dont, /* complain_on_overflow */
346 1.1 christos xgate_elf_ignore_reloc, /* special_function */
347 1.1 christos "R_XGATE_RL_GROUP", /* name */
348 1.1 christos TRUE, /* partial_inplace */
349 1.1 christos 0, /* src_mask */
350 1.1 christos 0, /* dst_mask */
351 1.1 christos TRUE), /* pcrel_offset */
352 1.1 christos };
353 1.1 christos
354 1.1 christos /* Map BFD reloc types to XGATE ELF reloc types. */
355 1.1 christos
356 1.1 christos struct xgate_reloc_map
357 1.1 christos {
358 1.1 christos bfd_reloc_code_real_type bfd_reloc_val;
359 1.1 christos unsigned char elf_reloc_val;
360 1.1 christos };
361 1.1 christos
362 1.1 christos static const struct xgate_reloc_map xgate_reloc_map[] =
363 1.1 christos {
364 1.1 christos {BFD_RELOC_NONE, R_XGATE_NONE},
365 1.1 christos {BFD_RELOC_8, R_XGATE_8},
366 1.1 christos {BFD_RELOC_8_PCREL, R_XGATE_PCREL_8},
367 1.1 christos {BFD_RELOC_16_PCREL, R_XGATE_PCREL_16},
368 1.1 christos {BFD_RELOC_16, R_XGATE_16},
369 1.1 christos {BFD_RELOC_32, R_XGATE_32},
370 1.1 christos
371 1.1 christos {BFD_RELOC_VTABLE_INHERIT, R_XGATE_GNU_VTINHERIT},
372 1.1 christos {BFD_RELOC_VTABLE_ENTRY, R_XGATE_GNU_VTENTRY},
373 1.1 christos
374 1.1 christos {BFD_RELOC_XGATE_LO16, R_XGATE_LO16},
375 1.1 christos {BFD_RELOC_XGATE_GPAGE, R_XGATE_GPAGE},
376 1.1 christos {BFD_RELOC_XGATE_24, R_XGATE_24},
377 1.1 christos {BFD_RELOC_XGATE_PCREL_9, R_XGATE_PCREL_9},
378 1.1 christos {BFD_RELOC_XGATE_PCREL_10, R_XGATE_PCREL_10},
379 1.1 christos {BFD_RELOC_XGATE_IMM8_LO, R_XGATE_IMM8_LO},
380 1.1 christos {BFD_RELOC_XGATE_IMM8_HI, R_XGATE_IMM8_HI},
381 1.1 christos {BFD_RELOC_XGATE_IMM3, R_XGATE_IMM3},
382 1.1 christos {BFD_RELOC_XGATE_IMM4, R_XGATE_IMM4},
383 1.1 christos {BFD_RELOC_XGATE_IMM5, R_XGATE_IMM5},
384 1.1 christos
385 1.1 christos {BFD_RELOC_XGATE_RL_JUMP, R_XGATE_RL_JUMP},
386 1.1 christos {BFD_RELOC_XGATE_RL_GROUP, R_XGATE_RL_GROUP},
387 1.1 christos };
388 1.1 christos
389 1.1 christos static reloc_howto_type *
390 1.1 christos bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
391 1.1 christos bfd_reloc_code_real_type code)
392 1.1 christos {
393 1.1 christos unsigned int i;
394 1.1 christos
395 1.1 christos for (i = 0; i < ARRAY_SIZE (xgate_reloc_map); i++)
396 1.1 christos if (xgate_reloc_map[i].bfd_reloc_val == code)
397 1.1 christos return &elf_xgate_howto_table[xgate_reloc_map[i].elf_reloc_val];
398 1.1 christos
399 1.1 christos return NULL;
400 1.1 christos }
401 1.1 christos
402 1.1 christos static reloc_howto_type *
403 1.1 christos bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
404 1.1 christos {
405 1.1 christos unsigned int i;
406 1.1 christos
407 1.1 christos for (i = 0; i < ARRAY_SIZE (elf_xgate_howto_table); i++)
408 1.1 christos if (elf_xgate_howto_table[i].name != NULL
409 1.1 christos && strcasecmp (elf_xgate_howto_table[i].name, r_name) == 0)
410 1.1 christos return &elf_xgate_howto_table[i];
411 1.1 christos
412 1.1 christos return NULL;
413 1.1 christos }
414 1.1 christos
415 1.1 christos /* Set the howto pointer for an XGATE ELF reloc. */
416 1.1 christos
417 1.1 christos static void
418 1.1 christos xgate_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
419 1.1 christos arelent *cache_ptr,
420 1.1 christos Elf_Internal_Rela *dst)
421 1.1 christos {
422 1.1 christos unsigned int r_type;
423 1.1 christos
424 1.1 christos r_type = ELF32_R_TYPE (dst->r_info);
425 1.1.1.2 christos if (r_type >= (unsigned int) R_XGATE_max)
426 1.1.1.2 christos {
427 1.1.1.5 christos /* xgettext:c-format */
428 1.1.1.3 christos _bfd_error_handler (_("%B: invalid XGate reloc number: %d"), abfd, r_type);
429 1.1.1.2 christos r_type = 0;
430 1.1.1.2 christos }
431 1.1 christos cache_ptr->howto = &elf_xgate_howto_table[r_type];
432 1.1 christos }
433 1.1 christos
434 1.1.1.2 christos /* Destroy an XGATE ELF linker hash table. */
435 1.1 christos
436 1.1.1.2 christos static void
437 1.1.1.2 christos xgate_elf_bfd_link_hash_table_free (bfd *obfd)
438 1.1 christos {
439 1.1 christos struct xgate_elf_link_hash_table *ret =
440 1.1.1.2 christos (struct xgate_elf_link_hash_table *) obfd->link.hash;
441 1.1 christos
442 1.1 christos bfd_hash_table_free (ret->stub_hash_table);
443 1.1 christos free (ret->stub_hash_table);
444 1.1.1.2 christos _bfd_elf_link_hash_table_free (obfd);
445 1.1 christos }
446 1.1 christos
447 1.1.1.2 christos /* Create an XGATE ELF linker hash table. */
448 1.1 christos
449 1.1 christos static struct bfd_link_hash_table*
450 1.1 christos xgate_elf_bfd_link_hash_table_create (bfd *abfd)
451 1.1 christos {
452 1.1 christos struct xgate_elf_link_hash_table *ret;
453 1.1 christos bfd_size_type amt = sizeof(struct xgate_elf_link_hash_table);
454 1.1 christos
455 1.1 christos ret = (struct xgate_elf_link_hash_table *) bfd_zmalloc (amt);
456 1.1 christos if (ret == (struct xgate_elf_link_hash_table *) NULL)
457 1.1 christos return NULL;
458 1.1 christos
459 1.1 christos if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
460 1.1 christos _bfd_elf_link_hash_newfunc, sizeof(struct elf_link_hash_entry),
461 1.1 christos XGATE_ELF_DATA))
462 1.1 christos {
463 1.1 christos free (ret);
464 1.1 christos return NULL;
465 1.1 christos }
466 1.1 christos
467 1.1 christos /* Init the stub hash table too. */
468 1.1 christos amt = sizeof(struct bfd_hash_table);
469 1.1 christos ret->stub_hash_table = (struct bfd_hash_table*) bfd_zmalloc (amt);
470 1.1 christos if (ret->stub_hash_table == NULL)
471 1.1 christos {
472 1.1.1.2 christos _bfd_elf_link_hash_table_free (abfd);
473 1.1 christos return NULL;
474 1.1 christos }
475 1.1 christos
476 1.1 christos if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc,
477 1.1 christos sizeof(struct elf32_xgate_stub_hash_entry)))
478 1.1 christos {
479 1.1 christos free (ret->stub_hash_table);
480 1.1.1.2 christos _bfd_elf_link_hash_table_free (abfd);
481 1.1 christos return NULL;
482 1.1 christos }
483 1.1.1.2 christos ret->root.root.hash_table_free = xgate_elf_bfd_link_hash_table_free;
484 1.1 christos
485 1.1 christos return &ret->root.root;
486 1.1 christos }
487 1.1 christos
488 1.1 christos static bfd_boolean
489 1.1 christos xgate_elf_set_mach_from_flags (bfd *abfd ATTRIBUTE_UNUSED)
490 1.1 christos {
491 1.1 christos return TRUE;
492 1.1 christos }
493 1.1 christos
494 1.1 christos /* Specific sections:
495 1.1 christos - The .page0 is a data section that is mapped in [0x0000..0x00FF].
496 1.1 christos Page0 accesses are faster on the M68HC12.
497 1.1 christos - The .vectors is the section that represents the interrupt
498 1.1 christos vectors.
499 1.1 christos - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */
500 1.1 christos static const struct bfd_elf_special_section elf32_xgate_special_sections[] =
501 1.1 christos {
502 1.1 christos { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
503 1.1 christos { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
504 1.1 christos { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
505 1.1 christos { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
506 1.1 christos /*{ STRING_COMMA_LEN (".xgate"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
507 1.1 christos TODO finish this implementation */
508 1.1 christos { NULL, 0, 0, 0, 0 }
509 1.1 christos };
510 1.1 christos
511 1.1 christos struct xgate_scan_param
512 1.1 christos {
513 1.1 christos struct xgate_page_info* pinfo;
514 1.1 christos bfd_boolean use_memory_banks;
515 1.1 christos };
516 1.1 christos
517 1.1 christos /* Assorted hash table functions. */
518 1.1 christos
519 1.1 christos /* Initialize an entry in the stub hash table. */
520 1.1 christos
521 1.1 christos static struct bfd_hash_entry *
522 1.1 christos stub_hash_newfunc (struct bfd_hash_entry *entry,
523 1.1 christos struct bfd_hash_table *table ATTRIBUTE_UNUSED,
524 1.1 christos const char *string ATTRIBUTE_UNUSED)
525 1.1 christos {
526 1.1 christos return entry;
527 1.1 christos }
528 1.1 christos
529 1.1 christos /* Hook called by the linker routine which adds symbols from an object
530 1.1 christos file. */
531 1.1 christos
532 1.1 christos bfd_boolean
533 1.1 christos elf32_xgate_add_symbol_hook (bfd *abfd ATTRIBUTE_UNUSED,
534 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED,
535 1.1 christos Elf_Internal_Sym *sym,
536 1.1 christos const char **namep ATTRIBUTE_UNUSED,
537 1.1 christos flagword *flagsp ATTRIBUTE_UNUSED,
538 1.1 christos asection **secp ATTRIBUTE_UNUSED,
539 1.1 christos bfd_vma *valp ATTRIBUTE_UNUSED)
540 1.1 christos {
541 1.1 christos /* For some reason the st_target_internal value is not retained
542 1.1 christos after xgate_frob_symbol is called, hence this temp hack. */
543 1.1 christos sym->st_target_internal = 1;
544 1.1 christos return TRUE;
545 1.1 christos }
546 1.1 christos
547 1.1 christos /* External entry points for sizing and building linker stubs. */
548 1.1 christos
549 1.1 christos /* Set up various things so that we can make a list of input sections
550 1.1 christos for each output section included in the link. Returns -1 on error,
551 1.1 christos 0 when no stubs will be needed, and 1 on success. */
552 1.1 christos
553 1.1 christos int
554 1.1 christos elf32_xgate_setup_section_lists (bfd *output_bfd ATTRIBUTE_UNUSED,
555 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED)
556 1.1 christos {
557 1.1 christos return 1;
558 1.1 christos }
559 1.1 christos
560 1.1 christos /* Determine and set the size of the stub section for a final link.
561 1.1 christos The basic idea here is to examine all the relocations looking for
562 1.1 christos PC-relative calls to a target that is unreachable with any "9-bit PC-REL"
563 1.1 christos instruction. */
564 1.1 christos
565 1.1 christos bfd_boolean
566 1.1 christos elf32_xgate_size_stubs (bfd *output_bfd ATTRIBUTE_UNUSED,
567 1.1 christos bfd *stub_bfd ATTRIBUTE_UNUSED,
568 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED,
569 1.1 christos asection * (*add_stub_section) (const char*, asection*) ATTRIBUTE_UNUSED)
570 1.1 christos {
571 1.1 christos return FALSE;
572 1.1 christos }
573 1.1 christos
574 1.1 christos /* Build all the stubs associated with the current output file. The
575 1.1 christos stubs are kept in a hash table attached to the main linker hash
576 1.1 christos table. This function is called via xgateelf_finish in the
577 1.1 christos linker. */
578 1.1 christos
579 1.1 christos bfd_boolean
580 1.1 christos elf32_xgate_build_stubs (bfd *abfd ATTRIBUTE_UNUSED,
581 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED)
582 1.1 christos {
583 1.1 christos return TRUE;
584 1.1 christos }
585 1.1 christos
586 1.1 christos void
587 1.1 christos xgate_elf_get_bank_parameters (struct bfd_link_info *info ATTRIBUTE_UNUSED)
588 1.1 christos {
589 1.1 christos return;
590 1.1 christos }
591 1.1 christos
592 1.1 christos /* This function is used for relocs which are only used for relaxing,
593 1.1 christos which the linker should otherwise ignore. */
594 1.1 christos
595 1.1 christos bfd_reloc_status_type
596 1.1 christos xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
597 1.1 christos arelent *reloc_entry,
598 1.1 christos asymbol *symbol ATTRIBUTE_UNUSED,
599 1.1 christos void *data ATTRIBUTE_UNUSED,
600 1.1 christos asection *input_section,
601 1.1 christos bfd *output_bfd,
602 1.1 christos char **error_message ATTRIBUTE_UNUSED)
603 1.1 christos {
604 1.1 christos if (output_bfd != NULL)
605 1.1 christos reloc_entry->address += input_section->output_offset;
606 1.1 christos return bfd_reloc_ok;
607 1.1 christos }
608 1.1 christos
609 1.1 christos bfd_reloc_status_type
610 1.1 christos xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
611 1.1 christos arelent *reloc_entry ATTRIBUTE_UNUSED,
612 1.1 christos asymbol *symbol ATTRIBUTE_UNUSED,
613 1.1 christos void *data ATTRIBUTE_UNUSED,
614 1.1 christos asection *input_section ATTRIBUTE_UNUSED,
615 1.1 christos bfd *output_bfd ATTRIBUTE_UNUSED,
616 1.1 christos char **error_message ATTRIBUTE_UNUSED)
617 1.1 christos {
618 1.1 christos abort ();
619 1.1 christos }
620 1.1 christos
621 1.1 christos /* Look through the relocs for a section during the first phase.
622 1.1 christos Since we don't do .gots or .plts, we just need to consider the
623 1.1 christos virtual table relocs for gc. */
624 1.1 christos
625 1.1 christos bfd_boolean
626 1.1 christos elf32_xgate_check_relocs (bfd *abfd ATTRIBUTE_UNUSED,
627 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED,
628 1.1 christos asection *sec ATTRIBUTE_UNUSED,
629 1.1 christos const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
630 1.1 christos {
631 1.1 christos return TRUE;
632 1.1 christos }
633 1.1 christos
634 1.1 christos /* Relocate a XGATE/S12x ELF section. */
635 1.1 christos
636 1.1 christos bfd_boolean
637 1.1 christos elf32_xgate_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
638 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED,
639 1.1 christos bfd *input_bfd ATTRIBUTE_UNUSED,
640 1.1 christos asection *input_section ATTRIBUTE_UNUSED,
641 1.1 christos bfd_byte *contents ATTRIBUTE_UNUSED,
642 1.1 christos Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED,
643 1.1 christos Elf_Internal_Sym *local_syms ATTRIBUTE_UNUSED,
644 1.1 christos asection **local_sections ATTRIBUTE_UNUSED)
645 1.1 christos {
646 1.1 christos return TRUE;
647 1.1 christos }
648 1.1 christos
649 1.1 christos /* Set and control ELF flags in ELF header. */
650 1.1 christos
651 1.1 christos bfd_boolean
652 1.1 christos _bfd_xgate_elf_set_private_flags (bfd *abfd ATTRIBUTE_UNUSED,
653 1.1 christos flagword flags ATTRIBUTE_UNUSED)
654 1.1 christos {
655 1.1 christos return TRUE;
656 1.1 christos }
657 1.1 christos
658 1.1 christos bfd_boolean
659 1.1 christos _bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr)
660 1.1 christos {
661 1.1 christos FILE *file = (FILE *) ptr;
662 1.1 christos
663 1.1 christos BFD_ASSERT (abfd != NULL && ptr != NULL);
664 1.1 christos
665 1.1 christos /* Print normal ELF private data. */
666 1.1 christos _bfd_elf_print_private_bfd_data (abfd, ptr);
667 1.1 christos
668 1.1 christos /* xgettext:c-format */
669 1.1 christos fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
670 1.1 christos
671 1.1 christos if (elf_elfheader (abfd)->e_flags & E_XGATE_I32)
672 1.1 christos fprintf (file, _("[abi=32-bit int, "));
673 1.1 christos else
674 1.1 christos fprintf (file, _("[abi=16-bit int, "));
675 1.1 christos
676 1.1 christos if (elf_elfheader (abfd)->e_flags & E_XGATE_F64)
677 1.1 christos fprintf (file, _("64-bit double, "));
678 1.1 christos else
679 1.1 christos fprintf (file, _("32-bit double, "));
680 1.1 christos if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH)
681 1.1 christos fprintf (file, _("cpu=XGATE]"));
682 1.1 christos else
683 1.1 christos fprintf (file, _("error reading cpu type from elf private data"));
684 1.1 christos fputc ('\n', file);
685 1.1 christos
686 1.1 christos return TRUE;
687 1.1 christos }
688 1.1 christos
689 1.1 christos void
690 1.1 christos elf32_xgate_post_process_headers (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
691 1.1 christos {
692 1.1 christos
693 1.1 christos }
694 1.1 christos
695 1.1 christos #define ELF_ARCH bfd_arch_xgate
696 1.1 christos #define ELF_MACHINE_CODE EM_XGATE
697 1.1 christos #define ELF_TARGET_ID XGATE_ELF_DATA
698 1.1 christos
699 1.1 christos #define ELF_MAXPAGESIZE 0x1000
700 1.1 christos
701 1.1.1.2 christos #define TARGET_BIG_SYM xgate_elf32_vec
702 1.1 christos #define TARGET_BIG_NAME "elf32-xgate"
703 1.1 christos
704 1.1 christos #define elf_info_to_howto 0
705 1.1 christos #define elf_info_to_howto_rel xgate_info_to_howto_rel
706 1.1 christos #define elf_backend_check_relocs elf32_xgate_check_relocs
707 1.1 christos #define elf_backend_relocate_section elf32_xgate_relocate_section
708 1.1 christos #define elf_backend_object_p xgate_elf_set_mach_from_flags
709 1.1 christos #define elf_backend_final_write_processing 0
710 1.1 christos #define elf_backend_can_gc_sections 1
711 1.1 christos #define elf_backend_special_sections elf32_xgate_special_sections
712 1.1 christos #define elf_backend_post_process_headers elf32_xgate_post_process_headers
713 1.1 christos #define elf_backend_add_symbol_hook elf32_xgate_add_symbol_hook
714 1.1 christos
715 1.1 christos #define bfd_elf32_bfd_link_hash_table_create xgate_elf_bfd_link_hash_table_create
716 1.1 christos #define bfd_elf32_bfd_set_private_flags _bfd_xgate_elf_set_private_flags
717 1.1 christos #define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data
718 1.1 christos
719 1.1 christos #define xgate_stub_hash_lookup(table, string, create, copy) \
720 1.1 christos ((struct elf32_xgate_stub_hash_entry *) \
721 1.1 christos bfd_hash_lookup ((table), (string), (create), (copy)))
722 1.1 christos
723 1.1 christos #include "elf32-target.h"
724