elf32-xgate.c revision 1.3 1 1.1 christos /* Freescale XGATE-specific support for 32-bit ELF
2 1.3 christos Copyright (C) 2010-2015 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 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
56 1.1 christos 32, /* 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.3 christos if (r_type >= (unsigned int) R_XGATE_max)
426 1.3 christos {
427 1.3 christos _bfd_error_handler (_("%A: invalid XGate reloc number: %d"), abfd, r_type);
428 1.3 christos r_type = 0;
429 1.3 christos }
430 1.1 christos cache_ptr->howto = &elf_xgate_howto_table[r_type];
431 1.1 christos }
432 1.1 christos
433 1.3 christos /* Destroy an XGATE ELF linker hash table. */
434 1.1 christos
435 1.3 christos static void
436 1.3 christos xgate_elf_bfd_link_hash_table_free (bfd *obfd)
437 1.1 christos {
438 1.1 christos struct xgate_elf_link_hash_table *ret =
439 1.3 christos (struct xgate_elf_link_hash_table *) obfd->link.hash;
440 1.1 christos
441 1.1 christos bfd_hash_table_free (ret->stub_hash_table);
442 1.1 christos free (ret->stub_hash_table);
443 1.3 christos _bfd_elf_link_hash_table_free (obfd);
444 1.1 christos }
445 1.1 christos
446 1.3 christos /* Create an XGATE ELF linker hash table. */
447 1.1 christos
448 1.1 christos static struct bfd_link_hash_table*
449 1.1 christos xgate_elf_bfd_link_hash_table_create (bfd *abfd)
450 1.1 christos {
451 1.1 christos struct xgate_elf_link_hash_table *ret;
452 1.1 christos bfd_size_type amt = sizeof(struct xgate_elf_link_hash_table);
453 1.1 christos
454 1.1 christos ret = (struct xgate_elf_link_hash_table *) bfd_zmalloc (amt);
455 1.1 christos if (ret == (struct xgate_elf_link_hash_table *) NULL)
456 1.1 christos return NULL;
457 1.1 christos
458 1.1 christos if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
459 1.1 christos _bfd_elf_link_hash_newfunc, sizeof(struct elf_link_hash_entry),
460 1.1 christos XGATE_ELF_DATA))
461 1.1 christos {
462 1.1 christos free (ret);
463 1.1 christos return NULL;
464 1.1 christos }
465 1.1 christos
466 1.1 christos /* Init the stub hash table too. */
467 1.1 christos amt = sizeof(struct bfd_hash_table);
468 1.1 christos ret->stub_hash_table = (struct bfd_hash_table*) bfd_zmalloc (amt);
469 1.1 christos if (ret->stub_hash_table == NULL)
470 1.1 christos {
471 1.3 christos _bfd_elf_link_hash_table_free (abfd);
472 1.1 christos return NULL;
473 1.1 christos }
474 1.1 christos
475 1.1 christos if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc,
476 1.1 christos sizeof(struct elf32_xgate_stub_hash_entry)))
477 1.1 christos {
478 1.1 christos free (ret->stub_hash_table);
479 1.3 christos _bfd_elf_link_hash_table_free (abfd);
480 1.1 christos return NULL;
481 1.1 christos }
482 1.3 christos ret->root.root.hash_table_free = xgate_elf_bfd_link_hash_table_free;
483 1.1 christos
484 1.1 christos return &ret->root.root;
485 1.1 christos }
486 1.1 christos
487 1.1 christos static bfd_boolean
488 1.1 christos xgate_elf_set_mach_from_flags (bfd *abfd ATTRIBUTE_UNUSED)
489 1.1 christos {
490 1.1 christos return TRUE;
491 1.1 christos }
492 1.1 christos
493 1.1 christos /* Specific sections:
494 1.1 christos - The .page0 is a data section that is mapped in [0x0000..0x00FF].
495 1.1 christos Page0 accesses are faster on the M68HC12.
496 1.1 christos - The .vectors is the section that represents the interrupt
497 1.1 christos vectors.
498 1.1 christos - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */
499 1.1 christos static const struct bfd_elf_special_section elf32_xgate_special_sections[] =
500 1.1 christos {
501 1.1 christos { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
502 1.1 christos { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
503 1.1 christos { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
504 1.1 christos { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
505 1.1 christos /*{ STRING_COMMA_LEN (".xgate"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
506 1.1 christos TODO finish this implementation */
507 1.1 christos { NULL, 0, 0, 0, 0 }
508 1.1 christos };
509 1.1 christos
510 1.1 christos struct xgate_scan_param
511 1.1 christos {
512 1.1 christos struct xgate_page_info* pinfo;
513 1.1 christos bfd_boolean use_memory_banks;
514 1.1 christos };
515 1.1 christos
516 1.1 christos /* Assorted hash table functions. */
517 1.1 christos
518 1.1 christos /* Initialize an entry in the stub hash table. */
519 1.1 christos
520 1.1 christos static struct bfd_hash_entry *
521 1.1 christos stub_hash_newfunc (struct bfd_hash_entry *entry,
522 1.1 christos struct bfd_hash_table *table ATTRIBUTE_UNUSED,
523 1.1 christos const char *string ATTRIBUTE_UNUSED)
524 1.1 christos {
525 1.1 christos return entry;
526 1.1 christos }
527 1.1 christos
528 1.1 christos /* Hook called by the linker routine which adds symbols from an object
529 1.1 christos file. */
530 1.1 christos
531 1.1 christos bfd_boolean
532 1.1 christos elf32_xgate_add_symbol_hook (bfd *abfd ATTRIBUTE_UNUSED,
533 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED,
534 1.1 christos Elf_Internal_Sym *sym,
535 1.1 christos const char **namep ATTRIBUTE_UNUSED,
536 1.1 christos flagword *flagsp ATTRIBUTE_UNUSED,
537 1.1 christos asection **secp ATTRIBUTE_UNUSED,
538 1.1 christos bfd_vma *valp ATTRIBUTE_UNUSED)
539 1.1 christos {
540 1.1 christos /* For some reason the st_target_internal value is not retained
541 1.1 christos after xgate_frob_symbol is called, hence this temp hack. */
542 1.1 christos sym->st_target_internal = 1;
543 1.1 christos return TRUE;
544 1.1 christos }
545 1.1 christos
546 1.1 christos /* External entry points for sizing and building linker stubs. */
547 1.1 christos
548 1.1 christos /* Set up various things so that we can make a list of input sections
549 1.1 christos for each output section included in the link. Returns -1 on error,
550 1.1 christos 0 when no stubs will be needed, and 1 on success. */
551 1.1 christos
552 1.1 christos int
553 1.1 christos elf32_xgate_setup_section_lists (bfd *output_bfd ATTRIBUTE_UNUSED,
554 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED)
555 1.1 christos {
556 1.1 christos return 1;
557 1.1 christos }
558 1.1 christos
559 1.1 christos /* Determine and set the size of the stub section for a final link.
560 1.1 christos The basic idea here is to examine all the relocations looking for
561 1.1 christos PC-relative calls to a target that is unreachable with any "9-bit PC-REL"
562 1.1 christos instruction. */
563 1.1 christos
564 1.1 christos bfd_boolean
565 1.1 christos elf32_xgate_size_stubs (bfd *output_bfd ATTRIBUTE_UNUSED,
566 1.1 christos bfd *stub_bfd ATTRIBUTE_UNUSED,
567 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED,
568 1.1 christos asection * (*add_stub_section) (const char*, asection*) ATTRIBUTE_UNUSED)
569 1.1 christos {
570 1.1 christos return FALSE;
571 1.1 christos }
572 1.1 christos
573 1.1 christos /* Build all the stubs associated with the current output file. The
574 1.1 christos stubs are kept in a hash table attached to the main linker hash
575 1.1 christos table. This function is called via xgateelf_finish in the
576 1.1 christos linker. */
577 1.1 christos
578 1.1 christos bfd_boolean
579 1.1 christos elf32_xgate_build_stubs (bfd *abfd ATTRIBUTE_UNUSED,
580 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED)
581 1.1 christos {
582 1.1 christos return TRUE;
583 1.1 christos }
584 1.1 christos
585 1.1 christos void
586 1.1 christos xgate_elf_get_bank_parameters (struct bfd_link_info *info ATTRIBUTE_UNUSED)
587 1.1 christos {
588 1.1 christos return;
589 1.1 christos }
590 1.1 christos
591 1.1 christos /* This function is used for relocs which are only used for relaxing,
592 1.1 christos which the linker should otherwise ignore. */
593 1.1 christos
594 1.1 christos bfd_reloc_status_type
595 1.1 christos xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
596 1.1 christos arelent *reloc_entry,
597 1.1 christos asymbol *symbol ATTRIBUTE_UNUSED,
598 1.1 christos void *data ATTRIBUTE_UNUSED,
599 1.1 christos asection *input_section,
600 1.1 christos bfd *output_bfd,
601 1.1 christos char **error_message ATTRIBUTE_UNUSED)
602 1.1 christos {
603 1.1 christos if (output_bfd != NULL)
604 1.1 christos reloc_entry->address += input_section->output_offset;
605 1.1 christos return bfd_reloc_ok;
606 1.1 christos }
607 1.1 christos
608 1.1 christos bfd_reloc_status_type
609 1.1 christos xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
610 1.1 christos arelent *reloc_entry ATTRIBUTE_UNUSED,
611 1.1 christos asymbol *symbol ATTRIBUTE_UNUSED,
612 1.1 christos void *data ATTRIBUTE_UNUSED,
613 1.1 christos asection *input_section ATTRIBUTE_UNUSED,
614 1.1 christos bfd *output_bfd ATTRIBUTE_UNUSED,
615 1.1 christos char **error_message ATTRIBUTE_UNUSED)
616 1.1 christos {
617 1.1 christos abort ();
618 1.1 christos }
619 1.1 christos
620 1.1 christos /* Look through the relocs for a section during the first phase.
621 1.1 christos Since we don't do .gots or .plts, we just need to consider the
622 1.1 christos virtual table relocs for gc. */
623 1.1 christos
624 1.1 christos bfd_boolean
625 1.1 christos elf32_xgate_check_relocs (bfd *abfd ATTRIBUTE_UNUSED,
626 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED,
627 1.1 christos asection *sec ATTRIBUTE_UNUSED,
628 1.1 christos const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
629 1.1 christos {
630 1.1 christos return TRUE;
631 1.1 christos }
632 1.1 christos
633 1.1 christos /* Relocate a XGATE/S12x ELF section. */
634 1.1 christos
635 1.1 christos bfd_boolean
636 1.1 christos elf32_xgate_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
637 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED,
638 1.1 christos bfd *input_bfd ATTRIBUTE_UNUSED,
639 1.1 christos asection *input_section ATTRIBUTE_UNUSED,
640 1.1 christos bfd_byte *contents ATTRIBUTE_UNUSED,
641 1.1 christos Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED,
642 1.1 christos Elf_Internal_Sym *local_syms ATTRIBUTE_UNUSED,
643 1.1 christos asection **local_sections ATTRIBUTE_UNUSED)
644 1.1 christos {
645 1.1 christos return TRUE;
646 1.1 christos }
647 1.1 christos
648 1.1 christos /* Set and control ELF flags in ELF header. */
649 1.1 christos
650 1.1 christos bfd_boolean
651 1.1 christos _bfd_xgate_elf_set_private_flags (bfd *abfd ATTRIBUTE_UNUSED,
652 1.1 christos flagword flags ATTRIBUTE_UNUSED)
653 1.1 christos {
654 1.1 christos return TRUE;
655 1.1 christos }
656 1.1 christos
657 1.1 christos /* Merge backend specific data from an object file to the output
658 1.1 christos object file when linking. */
659 1.1 christos
660 1.1 christos bfd_boolean
661 1.1 christos _bfd_xgate_elf_merge_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
662 1.1 christos bfd *obfd ATTRIBUTE_UNUSED)
663 1.1 christos {
664 1.1 christos return TRUE;
665 1.1 christos }
666 1.1 christos
667 1.1 christos bfd_boolean
668 1.1 christos _bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr)
669 1.1 christos {
670 1.1 christos FILE *file = (FILE *) ptr;
671 1.1 christos
672 1.1 christos BFD_ASSERT (abfd != NULL && ptr != NULL);
673 1.1 christos
674 1.1 christos /* Print normal ELF private data. */
675 1.1 christos _bfd_elf_print_private_bfd_data (abfd, ptr);
676 1.1 christos
677 1.1 christos /* xgettext:c-format */
678 1.1 christos fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
679 1.1 christos
680 1.1 christos if (elf_elfheader (abfd)->e_flags & E_XGATE_I32)
681 1.1 christos fprintf (file, _("[abi=32-bit int, "));
682 1.1 christos else
683 1.1 christos fprintf (file, _("[abi=16-bit int, "));
684 1.1 christos
685 1.1 christos if (elf_elfheader (abfd)->e_flags & E_XGATE_F64)
686 1.1 christos fprintf (file, _("64-bit double, "));
687 1.1 christos else
688 1.1 christos fprintf (file, _("32-bit double, "));
689 1.1 christos if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH)
690 1.1 christos fprintf (file, _("cpu=XGATE]"));
691 1.1 christos else
692 1.1 christos fprintf (file, _("error reading cpu type from elf private data"));
693 1.1 christos fputc ('\n', file);
694 1.1 christos
695 1.1 christos return TRUE;
696 1.1 christos }
697 1.1 christos
698 1.1 christos void
699 1.1 christos elf32_xgate_post_process_headers (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
700 1.1 christos {
701 1.1 christos
702 1.1 christos }
703 1.1 christos
704 1.1 christos #define ELF_ARCH bfd_arch_xgate
705 1.1 christos #define ELF_MACHINE_CODE EM_XGATE
706 1.1 christos #define ELF_TARGET_ID XGATE_ELF_DATA
707 1.1 christos
708 1.1 christos #define ELF_MAXPAGESIZE 0x1000
709 1.1 christos
710 1.3 christos #define TARGET_BIG_SYM xgate_elf32_vec
711 1.1 christos #define TARGET_BIG_NAME "elf32-xgate"
712 1.1 christos
713 1.1 christos #define elf_info_to_howto 0
714 1.1 christos #define elf_info_to_howto_rel xgate_info_to_howto_rel
715 1.1 christos #define elf_backend_check_relocs elf32_xgate_check_relocs
716 1.1 christos #define elf_backend_relocate_section elf32_xgate_relocate_section
717 1.1 christos #define elf_backend_object_p xgate_elf_set_mach_from_flags
718 1.1 christos #define elf_backend_final_write_processing 0
719 1.1 christos #define elf_backend_can_gc_sections 1
720 1.1 christos #define elf_backend_special_sections elf32_xgate_special_sections
721 1.1 christos #define elf_backend_post_process_headers elf32_xgate_post_process_headers
722 1.1 christos #define elf_backend_add_symbol_hook elf32_xgate_add_symbol_hook
723 1.1 christos
724 1.1 christos #define bfd_elf32_bfd_link_hash_table_create xgate_elf_bfd_link_hash_table_create
725 1.1 christos #define bfd_elf32_bfd_merge_private_bfd_data _bfd_xgate_elf_merge_private_bfd_data
726 1.1 christos #define bfd_elf32_bfd_set_private_flags _bfd_xgate_elf_set_private_flags
727 1.1 christos #define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data
728 1.1 christos
729 1.1 christos #define xgate_stub_hash_lookup(table, string, create, copy) \
730 1.1 christos ((struct elf32_xgate_stub_hash_entry *) \
731 1.1 christos bfd_hash_lookup ((table), (string), (create), (copy)))
732 1.1 christos
733 1.1 christos #include "elf32-target.h"
734