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