elf32-xstormy16.c revision 1.1.1.2.2.1 1 1.1 christos /* Xstormy16-specific support for 32-bit ELF.
2 1.1.1.2 christos Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2012
3 1.1 christos Free Software Foundation, Inc.
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 "libbfd.h"
25 1.1 christos #include "elf-bfd.h"
26 1.1 christos #include "elf/xstormy16.h"
27 1.1 christos #include "libiberty.h"
28 1.1 christos
29 1.1 christos /* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */
30 1.1 christos
31 1.1 christos static bfd_reloc_status_type
32 1.1 christos xstormy16_elf_24_reloc (bfd *abfd,
33 1.1 christos arelent *reloc_entry,
34 1.1 christos asymbol *symbol,
35 1.1 christos void * data,
36 1.1 christos asection *input_section,
37 1.1 christos bfd *output_bfd,
38 1.1 christos char **error_message ATTRIBUTE_UNUSED)
39 1.1 christos {
40 1.1 christos bfd_vma relocation, x;
41 1.1 christos
42 1.1 christos if (output_bfd != NULL)
43 1.1 christos {
44 1.1 christos reloc_entry->address += input_section->output_offset;
45 1.1 christos return bfd_reloc_ok;
46 1.1 christos }
47 1.1 christos
48 1.1 christos if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
49 1.1 christos return bfd_reloc_outofrange;
50 1.1 christos
51 1.1 christos if (bfd_is_com_section (symbol->section))
52 1.1 christos relocation = 0;
53 1.1 christos else
54 1.1 christos relocation = symbol->value;
55 1.1 christos
56 1.1 christos relocation += symbol->section->output_section->vma;
57 1.1 christos relocation += symbol->section->output_offset;
58 1.1 christos relocation += reloc_entry->addend;
59 1.1 christos
60 1.1 christos x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
61 1.1 christos x &= 0x0000ff00;
62 1.1 christos x |= relocation & 0xff;
63 1.1 christos x |= (relocation << 8) & 0xffff0000;
64 1.1 christos bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
65 1.1 christos
66 1.1 christos if (relocation & ~ (bfd_vma) 0xffffff)
67 1.1 christos return bfd_reloc_overflow;
68 1.1 christos
69 1.1 christos return bfd_reloc_ok;
70 1.1 christos }
71 1.1 christos
72 1.1 christos static reloc_howto_type xstormy16_elf_howto_table [] =
73 1.1 christos {
74 1.1 christos /* This reloc does nothing. */
75 1.1 christos HOWTO (R_XSTORMY16_NONE, /* type */
76 1.1 christos 0, /* rightshift */
77 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
78 1.1 christos 32, /* bitsize */
79 1.1 christos FALSE, /* pc_relative */
80 1.1 christos 0, /* bitpos */
81 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
82 1.1 christos bfd_elf_generic_reloc, /* special_function */
83 1.1 christos "R_XSTORMY16_NONE", /* name */
84 1.1 christos FALSE, /* partial_inplace */
85 1.1 christos 0, /* src_mask */
86 1.1 christos 0, /* dst_mask */
87 1.1 christos FALSE), /* pcrel_offset */
88 1.1 christos
89 1.1 christos /* A 32 bit absolute relocation. */
90 1.1 christos HOWTO (R_XSTORMY16_32, /* type */
91 1.1 christos 0, /* rightshift */
92 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
93 1.1 christos 32, /* bitsize */
94 1.1 christos FALSE, /* pc_relative */
95 1.1 christos 0, /* bitpos */
96 1.1 christos complain_overflow_dont, /* complain_on_overflow */
97 1.1 christos bfd_elf_generic_reloc, /* special_function */
98 1.1 christos "R_XSTORMY16_32", /* name */
99 1.1 christos FALSE, /* partial_inplace */
100 1.1 christos 0, /* src_mask */
101 1.1 christos 0xffffffff, /* dst_mask */
102 1.1 christos FALSE), /* pcrel_offset */
103 1.1 christos
104 1.1 christos /* A 16 bit absolute relocation. */
105 1.1 christos HOWTO (R_XSTORMY16_16, /* type */
106 1.1 christos 0, /* rightshift */
107 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
108 1.1 christos 16, /* bitsize */
109 1.1 christos FALSE, /* pc_relative */
110 1.1 christos 0, /* bitpos */
111 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
112 1.1 christos bfd_elf_generic_reloc, /* special_function */
113 1.1 christos "R_XSTORMY16_16", /* name */
114 1.1 christos FALSE, /* partial_inplace */
115 1.1 christos 0, /* src_mask */
116 1.1 christos 0xffff, /* dst_mask */
117 1.1 christos FALSE), /* pcrel_offset */
118 1.1 christos
119 1.1 christos /* An 8 bit absolute relocation. */
120 1.1 christos HOWTO (R_XSTORMY16_8, /* type */
121 1.1 christos 0, /* rightshift */
122 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
123 1.1 christos 8, /* bitsize */
124 1.1 christos FALSE, /* pc_relative */
125 1.1 christos 0, /* bitpos */
126 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
127 1.1 christos bfd_elf_generic_reloc, /* special_function */
128 1.1 christos "R_XSTORMY16_8", /* name */
129 1.1 christos FALSE, /* partial_inplace */
130 1.1 christos 0, /* src_mask */
131 1.1 christos 0xff, /* dst_mask */
132 1.1 christos FALSE), /* pcrel_offset */
133 1.1 christos
134 1.1 christos /* A 32 bit pc-relative relocation. */
135 1.1 christos HOWTO (R_XSTORMY16_PC32, /* type */
136 1.1 christos 0, /* rightshift */
137 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
138 1.1 christos 32, /* bitsize */
139 1.1 christos TRUE, /* pc_relative */
140 1.1 christos 0, /* bitpos */
141 1.1 christos complain_overflow_dont, /* complain_on_overflow */
142 1.1 christos bfd_elf_generic_reloc, /* special_function */
143 1.1 christos "R_XSTORMY16_PC32", /* name */
144 1.1 christos FALSE, /* partial_inplace */
145 1.1 christos 0, /* src_mask */
146 1.1 christos 0xffffffff, /* dst_mask */
147 1.1 christos TRUE), /* pcrel_offset */
148 1.1 christos
149 1.1 christos /* A 16 bit pc-relative relocation. */
150 1.1 christos HOWTO (R_XSTORMY16_PC16, /* type */
151 1.1 christos 0, /* rightshift */
152 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
153 1.1 christos 16, /* bitsize */
154 1.1 christos TRUE, /* pc_relative */
155 1.1 christos 0, /* bitpos */
156 1.1 christos complain_overflow_signed, /* complain_on_overflow */
157 1.1 christos bfd_elf_generic_reloc, /* special_function */
158 1.1 christos "R_XSTORMY16_PC16", /* name */
159 1.1 christos FALSE, /* partial_inplace */
160 1.1 christos 0, /* src_mask */
161 1.1 christos 0xffffffff, /* dst_mask */
162 1.1 christos TRUE), /* pcrel_offset */
163 1.1 christos
164 1.1 christos /* An 8 bit pc-relative relocation. */
165 1.1 christos HOWTO (R_XSTORMY16_PC8, /* type */
166 1.1 christos 0, /* rightshift */
167 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
168 1.1 christos 8, /* bitsize */
169 1.1 christos TRUE, /* pc_relative */
170 1.1 christos 0, /* bitpos */
171 1.1 christos complain_overflow_signed, /* complain_on_overflow */
172 1.1 christos bfd_elf_generic_reloc, /* special_function */
173 1.1 christos "R_XSTORMY16_PC8", /* name */
174 1.1 christos FALSE, /* partial_inplace */
175 1.1 christos 0, /* src_mask */
176 1.1 christos 0xffffffff, /* dst_mask */
177 1.1 christos TRUE), /* pcrel_offset */
178 1.1 christos
179 1.1 christos /* A 12-bit pc-relative relocation suitable for the branch instructions. */
180 1.1 christos HOWTO (R_XSTORMY16_REL_12, /* type */
181 1.1 christos 1, /* rightshift */
182 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
183 1.1 christos 11, /* bitsize */
184 1.1 christos TRUE, /* pc_relative */
185 1.1 christos 1, /* bitpos */
186 1.1 christos complain_overflow_signed, /* complain_on_overflow */
187 1.1 christos bfd_elf_generic_reloc, /* special_function */
188 1.1 christos "R_XSTORMY16_REL_12", /* name */
189 1.1 christos FALSE, /* partial_inplace */
190 1.1 christos 0, /* src_mask */
191 1.1 christos 0x0ffe, /* dst_mask */
192 1.1 christos TRUE), /* pcrel_offset */
193 1.1 christos
194 1.1 christos /* A 24-bit absolute relocation suitable for the jump instructions. */
195 1.1 christos HOWTO (R_XSTORMY16_24, /* type */
196 1.1 christos 0, /* rightshift */
197 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
198 1.1 christos 24, /* bitsize */
199 1.1 christos FALSE, /* pc_relative */
200 1.1 christos 0, /* bitpos */
201 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
202 1.1 christos xstormy16_elf_24_reloc, /* special_function */
203 1.1 christos "R_XSTORMY16_24", /* name */
204 1.1 christos TRUE, /* partial_inplace */
205 1.1 christos 0, /* src_mask */
206 1.1 christos 0xffff00ff, /* dst_mask */
207 1.1 christos TRUE), /* pcrel_offset */
208 1.1 christos
209 1.1 christos /* A 16 bit absolute relocation to a function pointer. */
210 1.1 christos HOWTO (R_XSTORMY16_FPTR16, /* type */
211 1.1 christos 0, /* rightshift */
212 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
213 1.1 christos 16, /* bitsize */
214 1.1 christos FALSE, /* pc_relative */
215 1.1 christos 0, /* bitpos */
216 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
217 1.1 christos bfd_elf_generic_reloc, /* special_function */
218 1.1 christos "R_XSTORMY16_FPTR16", /* name */
219 1.1 christos FALSE, /* partial_inplace */
220 1.1 christos 0, /* src_mask */
221 1.1 christos 0xffffffff, /* dst_mask */
222 1.1 christos FALSE), /* pcrel_offset */
223 1.1 christos
224 1.1 christos /* Low order 16 bit value of a high memory address. */
225 1.1 christos HOWTO (R_XSTORMY16_LO16, /* type */
226 1.1 christos 0, /* rightshift */
227 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
228 1.1 christos 16, /* bitsize */
229 1.1 christos FALSE, /* pc_relative */
230 1.1 christos 0, /* bitpos */
231 1.1 christos complain_overflow_dont, /* complain_on_overflow */
232 1.1 christos bfd_elf_generic_reloc, /* special_function */
233 1.1 christos "R_XSTORMY16_LO16", /* name */
234 1.1 christos FALSE, /* partial_inplace */
235 1.1 christos 0, /* src_mask */
236 1.1 christos 0xffff, /* dst_mask */
237 1.1 christos FALSE), /* pcrel_offset */
238 1.1 christos
239 1.1 christos /* High order 16 bit value of a high memory address. */
240 1.1 christos HOWTO (R_XSTORMY16_HI16, /* type */
241 1.1 christos 16, /* rightshift */
242 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
243 1.1 christos 16, /* bitsize */
244 1.1 christos FALSE, /* pc_relative */
245 1.1 christos 0, /* bitpos */
246 1.1 christos complain_overflow_dont, /* complain_on_overflow */
247 1.1 christos bfd_elf_generic_reloc, /* special_function */
248 1.1 christos "R_XSTORMY16_HI16", /* name */
249 1.1 christos FALSE, /* partial_inplace */
250 1.1 christos 0, /* src_mask */
251 1.1 christos 0xffff, /* dst_mask */
252 1.1 christos FALSE), /* pcrel_offset */
253 1.1 christos
254 1.1 christos /* A 12 bit absolute relocation. */
255 1.1 christos HOWTO (R_XSTORMY16_12, /* type */
256 1.1 christos 0, /* rightshift */
257 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
258 1.1 christos 12, /* bitsize */
259 1.1 christos FALSE, /* pc_relative */
260 1.1 christos 0, /* bitpos */
261 1.1 christos complain_overflow_signed, /* complain_on_overflow */
262 1.1 christos bfd_elf_generic_reloc, /* special_function */
263 1.1 christos "R_XSTORMY16_12", /* name */
264 1.1 christos FALSE, /* partial_inplace */
265 1.1 christos 0x0000, /* src_mask */
266 1.1 christos 0x0fff, /* dst_mask */
267 1.1 christos FALSE), /* pcrel_offset */
268 1.1 christos };
269 1.1 christos
270 1.1 christos static reloc_howto_type xstormy16_elf_howto_table2 [] =
271 1.1 christos {
272 1.1 christos /* GNU extension to record C++ vtable hierarchy */
273 1.1 christos HOWTO (R_XSTORMY16_GNU_VTINHERIT, /* type */
274 1.1 christos 0, /* rightshift */
275 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
276 1.1 christos 0, /* bitsize */
277 1.1 christos FALSE, /* pc_relative */
278 1.1 christos 0, /* bitpos */
279 1.1 christos complain_overflow_dont, /* complain_on_overflow */
280 1.1 christos NULL, /* special_function */
281 1.1 christos "R_XSTORMY16_GNU_VTINHERIT", /* name */
282 1.1 christos FALSE, /* partial_inplace */
283 1.1 christos 0, /* src_mask */
284 1.1 christos 0, /* dst_mask */
285 1.1 christos FALSE), /* pcrel_offset */
286 1.1 christos
287 1.1 christos /* GNU extension to record C++ vtable member usage */
288 1.1 christos HOWTO (R_XSTORMY16_GNU_VTENTRY, /* type */
289 1.1 christos 0, /* rightshift */
290 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
291 1.1 christos 0, /* bitsize */
292 1.1 christos FALSE, /* pc_relative */
293 1.1 christos 0, /* bitpos */
294 1.1 christos complain_overflow_dont, /* complain_on_overflow */
295 1.1 christos _bfd_elf_rel_vtable_reloc_fn, /* special_function */
296 1.1 christos "R_XSTORMY16_GNU_VTENTRY", /* name */
297 1.1 christos FALSE, /* partial_inplace */
298 1.1 christos 0, /* src_mask */
299 1.1 christos 0, /* dst_mask */
300 1.1 christos FALSE), /* pcrel_offset */
301 1.1 christos
302 1.1 christos };
303 1.1 christos
304 1.1 christos /* Map BFD reloc types to XSTORMY16 ELF reloc types. */
306 1.1 christos
307 1.1 christos typedef struct xstormy16_reloc_map
308 1.1 christos {
309 1.1 christos bfd_reloc_code_real_type bfd_reloc_val;
310 1.1 christos unsigned int xstormy16_reloc_val;
311 1.1 christos reloc_howto_type * table;
312 1.1 christos } reloc_map;
313 1.1 christos
314 1.1 christos static const reloc_map xstormy16_reloc_map [] =
315 1.1 christos {
316 1.1 christos { BFD_RELOC_NONE, R_XSTORMY16_NONE, xstormy16_elf_howto_table },
317 1.1 christos { BFD_RELOC_32, R_XSTORMY16_32, xstormy16_elf_howto_table },
318 1.1 christos { BFD_RELOC_16, R_XSTORMY16_16, xstormy16_elf_howto_table },
319 1.1 christos { BFD_RELOC_8, R_XSTORMY16_8, xstormy16_elf_howto_table },
320 1.1 christos { BFD_RELOC_32_PCREL, R_XSTORMY16_PC32, xstormy16_elf_howto_table },
321 1.1 christos { BFD_RELOC_16_PCREL, R_XSTORMY16_PC16, xstormy16_elf_howto_table },
322 1.1 christos { BFD_RELOC_8_PCREL, R_XSTORMY16_PC8, xstormy16_elf_howto_table },
323 1.1 christos { BFD_RELOC_XSTORMY16_REL_12, R_XSTORMY16_REL_12, xstormy16_elf_howto_table },
324 1.1 christos { BFD_RELOC_XSTORMY16_24, R_XSTORMY16_24, xstormy16_elf_howto_table },
325 1.1 christos { BFD_RELOC_XSTORMY16_FPTR16, R_XSTORMY16_FPTR16, xstormy16_elf_howto_table },
326 1.1 christos { BFD_RELOC_LO16, R_XSTORMY16_LO16, xstormy16_elf_howto_table },
327 1.1 christos { BFD_RELOC_HI16, R_XSTORMY16_HI16, xstormy16_elf_howto_table },
328 1.1 christos { BFD_RELOC_XSTORMY16_12, R_XSTORMY16_12, xstormy16_elf_howto_table },
329 1.1 christos { BFD_RELOC_VTABLE_INHERIT, R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 },
330 1.1 christos { BFD_RELOC_VTABLE_ENTRY, R_XSTORMY16_GNU_VTENTRY, xstormy16_elf_howto_table2 },
331 1.1 christos };
332 1.1 christos
333 1.1 christos static reloc_howto_type *
334 1.1 christos xstormy16_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
335 1.1 christos bfd_reloc_code_real_type code)
336 1.1 christos {
337 1.1 christos unsigned int i;
338 1.1 christos
339 1.1 christos for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;)
340 1.1 christos {
341 1.1 christos const reloc_map * entry;
342 1.1 christos
343 1.1 christos entry = xstormy16_reloc_map + i;
344 1.1 christos
345 1.1 christos if (entry->bfd_reloc_val == code)
346 1.1 christos return entry->table + (entry->xstormy16_reloc_val
347 1.1 christos - entry->table[0].type);
348 1.1 christos }
349 1.1 christos
350 1.1 christos return NULL;
351 1.1 christos }
352 1.1 christos
353 1.1 christos static reloc_howto_type *
354 1.1 christos xstormy16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
355 1.1 christos const char *r_name)
356 1.1 christos {
357 1.1 christos unsigned int i;
358 1.1 christos
359 1.1 christos for (i = 0;
360 1.1 christos i < (sizeof (xstormy16_elf_howto_table)
361 1.1 christos / sizeof (xstormy16_elf_howto_table[0]));
362 1.1 christos i++)
363 1.1 christos if (xstormy16_elf_howto_table[i].name != NULL
364 1.1 christos && strcasecmp (xstormy16_elf_howto_table[i].name, r_name) == 0)
365 1.1 christos return &xstormy16_elf_howto_table[i];
366 1.1 christos
367 1.1 christos for (i = 0;
368 1.1 christos i < (sizeof (xstormy16_elf_howto_table2)
369 1.1 christos / sizeof (xstormy16_elf_howto_table2[0]));
370 1.1 christos i++)
371 1.1 christos if (xstormy16_elf_howto_table2[i].name != NULL
372 1.1 christos && strcasecmp (xstormy16_elf_howto_table2[i].name, r_name) == 0)
373 1.1 christos return &xstormy16_elf_howto_table2[i];
374 1.1 christos
375 1.1 christos return NULL;
376 1.1 christos }
377 1.1 christos
378 1.1 christos /* Set the howto pointer for an XSTORMY16 ELF reloc. */
379 1.1 christos
380 1.1 christos static void
381 1.1 christos xstormy16_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
382 1.1 christos arelent * cache_ptr,
383 1.1 christos Elf_Internal_Rela * dst)
384 1.1 christos {
385 1.1 christos unsigned int r_type = ELF32_R_TYPE (dst->r_info);
386 1.1 christos
387 1.1 christos if (r_type <= (unsigned int) R_XSTORMY16_12)
388 1.1 christos cache_ptr->howto = &xstormy16_elf_howto_table [r_type];
389 1.1 christos else if (r_type - R_XSTORMY16_GNU_VTINHERIT
390 1.1 christos <= (unsigned int) R_XSTORMY16_GNU_VTENTRY)
391 1.1 christos cache_ptr->howto
392 1.1 christos = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT];
393 1.1 christos else
394 1.1 christos abort ();
395 1.1 christos }
396 1.1 christos
397 1.1 christos /* We support 16-bit pointers to code above 64k by generating a thunk
399 1.1 christos below 64k containing a JMPF instruction to the final address. We
400 1.1 christos cannot, unfortunately, minimize the number of thunks unless the
401 1.1 christos -relax switch is given, as otherwise we have no idea where the
402 1.1 christos sections will fall in the address space. */
403 1.1 christos
404 1.1 christos static bfd_boolean
405 1.1 christos xstormy16_elf_check_relocs (bfd *abfd,
406 1.1 christos struct bfd_link_info *info,
407 1.1 christos asection *sec,
408 1.1 christos const Elf_Internal_Rela *relocs)
409 1.1 christos {
410 1.1 christos const Elf_Internal_Rela *rel, *relend;
411 1.1 christos struct elf_link_hash_entry **sym_hashes;
412 1.1 christos Elf_Internal_Shdr *symtab_hdr;
413 1.1 christos bfd_vma *local_plt_offsets;
414 1.1 christos asection *splt;
415 1.1 christos bfd *dynobj;
416 1.1 christos
417 1.1 christos if (info->relocatable)
418 1.1 christos return TRUE;
419 1.1 christos
420 1.1 christos symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
421 1.1 christos sym_hashes = elf_sym_hashes (abfd);
422 1.1 christos local_plt_offsets = elf_local_got_offsets (abfd);
423 1.1 christos splt = NULL;
424 1.1 christos dynobj = elf_hash_table(info)->dynobj;
425 1.1 christos
426 1.1 christos relend = relocs + sec->reloc_count;
427 1.1 christos for (rel = relocs; rel < relend; ++rel)
428 1.1 christos {
429 1.1 christos unsigned long r_symndx;
430 1.1 christos struct elf_link_hash_entry *h;
431 1.1 christos bfd_vma *offset;
432 1.1 christos
433 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
434 1.1 christos if (r_symndx < symtab_hdr->sh_info)
435 1.1 christos h = NULL;
436 1.1 christos else
437 1.1 christos {
438 1.1 christos h = sym_hashes[r_symndx - symtab_hdr->sh_info];
439 1.1 christos while (h->root.type == bfd_link_hash_indirect
440 1.1.1.2.2.1 tls || h->root.type == bfd_link_hash_warning)
441 1.1.1.2.2.1 tls h = (struct elf_link_hash_entry *) h->root.u.i.link;
442 1.1.1.2.2.1 tls
443 1.1.1.2.2.1 tls /* PR15323, ref flags aren't set for references in the same
444 1.1 christos object. */
445 1.1 christos h->root.non_ir_ref = 1;
446 1.1 christos }
447 1.1 christos
448 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
449 1.1 christos {
450 1.1 christos /* This relocation describes a 16-bit pointer to a function.
451 1.1 christos We may need to allocate a thunk in low memory; reserve memory
452 1.1 christos for it now. */
453 1.1 christos case R_XSTORMY16_FPTR16:
454 1.1 christos if (rel->r_addend != 0)
455 1.1 christos {
456 1.1 christos (*info->callbacks->warning)
457 1.1 christos (info, _("non-zero addend in @fptr reloc"), 0,
458 1.1 christos abfd, 0, 0);
459 1.1 christos }
460 1.1 christos
461 1.1 christos if (dynobj == NULL)
462 1.1 christos elf_hash_table (info)->dynobj = dynobj = abfd;
463 1.1.1.2 christos if (splt == NULL)
464 1.1 christos {
465 1.1 christos splt = bfd_get_linker_section (dynobj, ".plt");
466 1.1.1.2 christos if (splt == NULL)
467 1.1.1.2 christos {
468 1.1.1.2 christos flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
469 1.1 christos | SEC_IN_MEMORY | SEC_LINKER_CREATED
470 1.1.1.2 christos | SEC_READONLY | SEC_CODE);
471 1.1.1.2 christos
472 1.1 christos splt = bfd_make_section_anyway_with_flags (dynobj, ".plt",
473 1.1 christos flags);
474 1.1 christos if (splt == NULL
475 1.1 christos || ! bfd_set_section_alignment (dynobj, splt, 1))
476 1.1 christos return FALSE;
477 1.1 christos }
478 1.1 christos }
479 1.1 christos
480 1.1 christos if (h != NULL)
481 1.1 christos offset = &h->plt.offset;
482 1.1 christos else
483 1.1 christos {
484 1.1 christos if (local_plt_offsets == NULL)
485 1.1 christos {
486 1.1 christos size_t size;
487 1.1 christos unsigned int i;
488 1.1 christos
489 1.1 christos size = symtab_hdr->sh_info * sizeof (bfd_vma);
490 1.1 christos local_plt_offsets = bfd_alloc (abfd, size);
491 1.1 christos if (local_plt_offsets == NULL)
492 1.1 christos return FALSE;
493 1.1 christos elf_local_got_offsets (abfd) = local_plt_offsets;
494 1.1 christos
495 1.1 christos for (i = 0; i < symtab_hdr->sh_info; i++)
496 1.1 christos local_plt_offsets[i] = (bfd_vma) -1;
497 1.1 christos }
498 1.1 christos offset = &local_plt_offsets[r_symndx];
499 1.1 christos }
500 1.1 christos
501 1.1 christos if (*offset == (bfd_vma) -1)
502 1.1 christos {
503 1.1 christos *offset = splt->size;
504 1.1 christos splt->size += 4;
505 1.1 christos }
506 1.1 christos break;
507 1.1 christos
508 1.1 christos /* This relocation describes the C++ object vtable hierarchy.
509 1.1 christos Reconstruct it for later use during GC. */
510 1.1 christos case R_XSTORMY16_GNU_VTINHERIT:
511 1.1 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
512 1.1 christos return FALSE;
513 1.1 christos break;
514 1.1 christos
515 1.1 christos /* This relocation describes which C++ vtable entries are actually
516 1.1 christos used. Record for later use during GC. */
517 1.1 christos case R_XSTORMY16_GNU_VTENTRY:
518 1.1 christos BFD_ASSERT (h != NULL);
519 1.1 christos if (h != NULL
520 1.1 christos && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
521 1.1 christos return FALSE;
522 1.1 christos break;
523 1.1 christos }
524 1.1 christos }
525 1.1 christos
526 1.1 christos return TRUE;
527 1.1 christos }
528 1.1 christos
529 1.1 christos /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
530 1.1 christos is within the low 64k, remove any entry for it in the plt. */
531 1.1 christos
532 1.1 christos struct relax_plt_data
533 1.1 christos {
534 1.1 christos asection *splt;
535 1.1 christos bfd_boolean *again;
536 1.1 christos };
537 1.1 christos
538 1.1 christos static bfd_boolean
539 1.1 christos xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata)
540 1.1 christos {
541 1.1 christos struct relax_plt_data *data = (struct relax_plt_data *) xdata;
542 1.1 christos
543 1.1 christos if (h->plt.offset != (bfd_vma) -1)
544 1.1 christos {
545 1.1 christos bfd_vma address;
546 1.1 christos
547 1.1 christos if (h->root.type == bfd_link_hash_undefined
548 1.1 christos || h->root.type == bfd_link_hash_undefweak)
549 1.1 christos address = 0;
550 1.1 christos else
551 1.1 christos address = (h->root.u.def.section->output_section->vma
552 1.1 christos + h->root.u.def.section->output_offset
553 1.1 christos + h->root.u.def.value);
554 1.1 christos
555 1.1 christos if (address <= 0xffff)
556 1.1 christos {
557 1.1 christos h->plt.offset = -1;
558 1.1 christos data->splt->size -= 4;
559 1.1 christos *data->again = TRUE;
560 1.1 christos }
561 1.1 christos }
562 1.1 christos
563 1.1 christos return TRUE;
564 1.1 christos }
565 1.1 christos
566 1.1 christos /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
567 1.1 christos previously had a plt entry, give it a new entry offset. */
568 1.1 christos
569 1.1 christos static bfd_boolean
570 1.1 christos xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata)
571 1.1 christos {
572 1.1 christos bfd_vma *entry = (bfd_vma *) xdata;
573 1.1 christos
574 1.1 christos if (h->plt.offset != (bfd_vma) -1)
575 1.1 christos {
576 1.1 christos h->plt.offset = *entry;
577 1.1 christos *entry += 4;
578 1.1 christos }
579 1.1 christos
580 1.1 christos return TRUE;
581 1.1 christos }
582 1.1 christos
583 1.1 christos static bfd_boolean
584 1.1 christos xstormy16_elf_relax_section (bfd *dynobj,
585 1.1 christos asection *splt,
586 1.1 christos struct bfd_link_info *info,
587 1.1 christos bfd_boolean *again)
588 1.1 christos {
589 1.1 christos struct relax_plt_data relax_plt_data;
590 1.1 christos bfd *ibfd;
591 1.1 christos
592 1.1 christos /* Assume nothing changes. */
593 1.1 christos *again = FALSE;
594 1.1 christos
595 1.1 christos if (info->relocatable)
596 1.1 christos return TRUE;
597 1.1 christos
598 1.1 christos /* We only relax the .plt section at the moment. */
599 1.1 christos if (dynobj != elf_hash_table (info)->dynobj
600 1.1 christos || strcmp (splt->name, ".plt") != 0)
601 1.1 christos return TRUE;
602 1.1 christos
603 1.1 christos /* Quick check for an empty plt. */
604 1.1 christos if (splt->size == 0)
605 1.1 christos return TRUE;
606 1.1 christos
607 1.1 christos /* Map across all global symbols; see which ones happen to
608 1.1 christos fall in the low 64k. */
609 1.1 christos relax_plt_data.splt = splt;
610 1.1 christos relax_plt_data.again = again;
611 1.1 christos elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check,
612 1.1 christos &relax_plt_data);
613 1.1 christos
614 1.1 christos /* Likewise for local symbols, though that's somewhat less convenient
615 1.1 christos as we have to walk the list of input bfds and swap in symbol data. */
616 1.1 christos for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
617 1.1 christos {
618 1.1 christos bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
619 1.1 christos Elf_Internal_Shdr *symtab_hdr;
620 1.1 christos Elf_Internal_Sym *isymbuf = NULL;
621 1.1 christos unsigned int idx;
622 1.1 christos
623 1.1 christos if (! local_plt_offsets)
624 1.1 christos continue;
625 1.1 christos
626 1.1 christos symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
627 1.1 christos if (symtab_hdr->sh_info != 0)
628 1.1 christos {
629 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
630 1.1 christos if (isymbuf == NULL)
631 1.1 christos isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
632 1.1 christos symtab_hdr->sh_info, 0,
633 1.1 christos NULL, NULL, NULL);
634 1.1 christos if (isymbuf == NULL)
635 1.1 christos return FALSE;
636 1.1 christos }
637 1.1 christos
638 1.1 christos for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
639 1.1 christos {
640 1.1 christos Elf_Internal_Sym *isym;
641 1.1 christos asection *tsec;
642 1.1 christos bfd_vma address;
643 1.1 christos
644 1.1 christos if (local_plt_offsets[idx] == (bfd_vma) -1)
645 1.1 christos continue;
646 1.1 christos
647 1.1 christos isym = &isymbuf[idx];
648 1.1 christos if (isym->st_shndx == SHN_UNDEF)
649 1.1 christos continue;
650 1.1 christos else if (isym->st_shndx == SHN_ABS)
651 1.1 christos tsec = bfd_abs_section_ptr;
652 1.1 christos else if (isym->st_shndx == SHN_COMMON)
653 1.1 christos tsec = bfd_com_section_ptr;
654 1.1 christos else
655 1.1 christos tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
656 1.1 christos
657 1.1 christos address = (tsec->output_section->vma
658 1.1 christos + tsec->output_offset
659 1.1 christos + isym->st_value);
660 1.1 christos if (address <= 0xffff)
661 1.1 christos {
662 1.1 christos local_plt_offsets[idx] = -1;
663 1.1 christos splt->size -= 4;
664 1.1 christos *again = TRUE;
665 1.1 christos }
666 1.1 christos }
667 1.1 christos
668 1.1 christos if (isymbuf != NULL
669 1.1 christos && symtab_hdr->contents != (unsigned char *) isymbuf)
670 1.1 christos {
671 1.1 christos if (! info->keep_memory)
672 1.1 christos free (isymbuf);
673 1.1 christos else
674 1.1 christos {
675 1.1 christos /* Cache the symbols for elf_link_input_bfd. */
676 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf;
677 1.1 christos }
678 1.1 christos }
679 1.1 christos }
680 1.1 christos
681 1.1 christos /* If we changed anything, walk the symbols again to reallocate
682 1.1 christos .plt entry addresses. */
683 1.1 christos if (*again && splt->size > 0)
684 1.1 christos {
685 1.1 christos bfd_vma entry = 0;
686 1.1 christos
687 1.1 christos elf_link_hash_traverse (elf_hash_table (info),
688 1.1 christos xstormy16_relax_plt_realloc, &entry);
689 1.1 christos
690 1.1 christos for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
691 1.1 christos {
692 1.1 christos bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
693 1.1 christos unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
694 1.1 christos unsigned int idx;
695 1.1 christos
696 1.1 christos if (! local_plt_offsets)
697 1.1 christos continue;
698 1.1 christos
699 1.1 christos for (idx = 0; idx < nlocals; ++idx)
700 1.1 christos if (local_plt_offsets[idx] != (bfd_vma) -1)
701 1.1 christos {
702 1.1 christos local_plt_offsets[idx] = entry;
703 1.1 christos entry += 4;
704 1.1 christos }
705 1.1 christos }
706 1.1 christos }
707 1.1 christos
708 1.1 christos return TRUE;
709 1.1 christos }
710 1.1 christos
711 1.1 christos static bfd_boolean
712 1.1 christos xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
713 1.1 christos struct bfd_link_info *info)
714 1.1 christos {
715 1.1 christos bfd *dynobj;
716 1.1 christos asection *splt;
717 1.1 christos
718 1.1 christos if (info->relocatable)
719 1.1 christos return TRUE;
720 1.1 christos
721 1.1 christos dynobj = elf_hash_table (info)->dynobj;
722 1.1 christos if (dynobj == NULL)
723 1.1.1.2 christos return TRUE;
724 1.1 christos
725 1.1 christos splt = bfd_get_linker_section (dynobj, ".plt");
726 1.1 christos BFD_ASSERT (splt != NULL);
727 1.1 christos
728 1.1 christos splt->contents = bfd_zalloc (dynobj, splt->size);
729 1.1 christos if (splt->contents == NULL)
730 1.1 christos return FALSE;
731 1.1 christos
732 1.1 christos return TRUE;
733 1.1 christos }
734 1.1 christos
735 1.1 christos /* Relocate an XSTORMY16 ELF section.
737 1.1 christos
738 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker
739 1.1 christos to handle the relocations for a section.
740 1.1 christos
741 1.1 christos The relocs are always passed as Rela structures; if the section
742 1.1 christos actually uses Rel structures, the r_addend field will always be
743 1.1 christos zero.
744 1.1 christos
745 1.1 christos This function is responsible for adjusting the section contents as
746 1.1 christos necessary, and (if using Rela relocs and generating a relocatable
747 1.1 christos output file) adjusting the reloc addend as necessary.
748 1.1 christos
749 1.1 christos This function does not have to worry about setting the reloc
750 1.1 christos address or the reloc symbol index.
751 1.1 christos
752 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols.
753 1.1 christos
754 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file
755 1.1 christos corresponding to the st_shndx field of each local symbol.
756 1.1 christos
757 1.1 christos The global hash table entry for the global symbols can be found
758 1.1 christos via elf_sym_hashes (input_bfd).
759 1.1 christos
760 1.1 christos When generating relocatable output, this function must handle
761 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is
762 1.1 christos going to be the section symbol corresponding to the output
763 1.1 christos section, which means that the addend must be adjusted
764 1.1 christos accordingly. */
765 1.1 christos
766 1.1 christos static bfd_boolean
767 1.1 christos xstormy16_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED,
768 1.1 christos struct bfd_link_info * info,
769 1.1 christos bfd * input_bfd,
770 1.1 christos asection * input_section,
771 1.1 christos bfd_byte * contents,
772 1.1 christos Elf_Internal_Rela * relocs,
773 1.1 christos Elf_Internal_Sym * local_syms,
774 1.1 christos asection ** local_sections)
775 1.1 christos {
776 1.1 christos Elf_Internal_Shdr * symtab_hdr;
777 1.1 christos struct elf_link_hash_entry ** sym_hashes;
778 1.1 christos Elf_Internal_Rela * rel;
779 1.1 christos Elf_Internal_Rela * relend;
780 1.1 christos bfd *dynobj;
781 1.1 christos asection *splt;
782 1.1 christos
783 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
784 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
785 1.1 christos relend = relocs + input_section->reloc_count;
786 1.1 christos
787 1.1.1.2 christos dynobj = elf_hash_table (info)->dynobj;
788 1.1 christos splt = NULL;
789 1.1 christos if (dynobj != NULL)
790 1.1 christos splt = bfd_get_linker_section (dynobj, ".plt");
791 1.1 christos
792 1.1 christos for (rel = relocs; rel < relend; rel ++)
793 1.1 christos {
794 1.1 christos reloc_howto_type * howto;
795 1.1 christos unsigned long r_symndx;
796 1.1 christos Elf_Internal_Sym * sym;
797 1.1 christos asection * sec;
798 1.1 christos struct elf_link_hash_entry * h;
799 1.1 christos bfd_vma relocation;
800 1.1 christos bfd_reloc_status_type r;
801 1.1 christos const char * name = NULL;
802 1.1 christos int r_type;
803 1.1 christos
804 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
805 1.1 christos
806 1.1 christos if ( r_type == R_XSTORMY16_GNU_VTINHERIT
807 1.1 christos || r_type == R_XSTORMY16_GNU_VTENTRY)
808 1.1 christos continue;
809 1.1 christos
810 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
811 1.1 christos howto = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
812 1.1 christos h = NULL;
813 1.1 christos sym = NULL;
814 1.1 christos sec = NULL;
815 1.1 christos
816 1.1 christos if (r_symndx < symtab_hdr->sh_info)
817 1.1 christos {
818 1.1 christos sym = local_syms + r_symndx;
819 1.1 christos sec = local_sections [r_symndx];
820 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
821 1.1.1.2.2.1 tls }
822 1.1 christos else
823 1.1 christos {
824 1.1 christos bfd_boolean unresolved_reloc, warned, ignored;
825 1.1 christos
826 1.1.1.2.2.1 tls RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
827 1.1 christos r_symndx, symtab_hdr, sym_hashes,
828 1.1 christos h, sec, relocation,
829 1.1.1.2 christos unresolved_reloc, warned, ignored);
830 1.1 christos }
831 1.1.1.2 christos
832 1.1 christos if (sec != NULL && discarded_section (sec))
833 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
834 1.1 christos rel, 1, relend, howto, 0, contents);
835 1.1 christos
836 1.1 christos if (info->relocatable)
837 1.1 christos continue;
838 1.1 christos
839 1.1 christos if (h != NULL)
840 1.1 christos name = h->root.root.string;
841 1.1 christos else
842 1.1 christos {
843 1.1 christos name = (bfd_elf_string_from_elf_section
844 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name));
845 1.1 christos if (name == NULL || *name == '\0')
846 1.1 christos name = bfd_section_name (input_bfd, sec);
847 1.1 christos }
848 1.1 christos
849 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
850 1.1 christos {
851 1.1 christos case R_XSTORMY16_24:
852 1.1 christos {
853 1.1 christos bfd_vma reloc = relocation + rel->r_addend;
854 1.1 christos unsigned int x;
855 1.1 christos
856 1.1 christos x = bfd_get_32 (input_bfd, contents + rel->r_offset);
857 1.1 christos x &= 0x0000ff00;
858 1.1 christos x |= reloc & 0xff;
859 1.1 christos x |= (reloc << 8) & 0xffff0000;
860 1.1 christos bfd_put_32 (input_bfd, x, contents + rel->r_offset);
861 1.1 christos
862 1.1 christos if (reloc & ~0xffffff)
863 1.1 christos r = bfd_reloc_overflow;
864 1.1 christos else
865 1.1 christos r = bfd_reloc_ok;
866 1.1 christos break;
867 1.1 christos }
868 1.1 christos
869 1.1 christos case R_XSTORMY16_FPTR16:
870 1.1 christos {
871 1.1 christos bfd_vma *plt_offset;
872 1.1 christos
873 1.1 christos if (h != NULL)
874 1.1 christos plt_offset = &h->plt.offset;
875 1.1 christos else
876 1.1 christos plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
877 1.1 christos
878 1.1 christos if (relocation <= 0xffff)
879 1.1 christos {
880 1.1 christos /* If the symbol is in range for a 16-bit address, we should
881 1.1 christos have deallocated the plt entry in relax_section. */
882 1.1 christos BFD_ASSERT (*plt_offset == (bfd_vma) -1);
883 1.1 christos }
884 1.1 christos else
885 1.1 christos {
886 1.1 christos /* If the symbol is out of range for a 16-bit address,
887 1.1 christos we must have allocated a plt entry. */
888 1.1 christos BFD_ASSERT (*plt_offset != (bfd_vma) -1);
889 1.1 christos
890 1.1 christos /* If this is the first time we've processed this symbol,
891 1.1 christos fill in the plt entry with the correct symbol address. */
892 1.1 christos if ((*plt_offset & 1) == 0)
893 1.1 christos {
894 1.1 christos unsigned int x;
895 1.1 christos
896 1.1 christos x = 0x00000200; /* jmpf */
897 1.1 christos x |= relocation & 0xff;
898 1.1 christos x |= (relocation << 8) & 0xffff0000;
899 1.1 christos bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
900 1.1 christos *plt_offset |= 1;
901 1.1 christos }
902 1.1 christos
903 1.1 christos relocation = (splt->output_section->vma
904 1.1 christos + splt->output_offset
905 1.1 christos + (*plt_offset & -2));
906 1.1 christos }
907 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
908 1.1 christos contents, rel->r_offset,
909 1.1 christos relocation, 0);
910 1.1 christos break;
911 1.1 christos }
912 1.1 christos
913 1.1 christos default:
914 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
915 1.1 christos contents, rel->r_offset,
916 1.1 christos relocation, rel->r_addend);
917 1.1 christos break;
918 1.1 christos }
919 1.1 christos
920 1.1 christos if (r != bfd_reloc_ok)
921 1.1 christos {
922 1.1 christos const char * msg = NULL;
923 1.1 christos
924 1.1 christos switch (r)
925 1.1 christos {
926 1.1 christos case bfd_reloc_overflow:
927 1.1 christos r = info->callbacks->reloc_overflow
928 1.1 christos (info, (h ? &h->root : NULL), name, howto->name,
929 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
930 1.1 christos break;
931 1.1 christos
932 1.1 christos case bfd_reloc_undefined:
933 1.1 christos r = info->callbacks->undefined_symbol
934 1.1 christos (info, name, input_bfd, input_section, rel->r_offset,
935 1.1 christos TRUE);
936 1.1 christos break;
937 1.1 christos
938 1.1 christos case bfd_reloc_outofrange:
939 1.1 christos msg = _("internal error: out of range error");
940 1.1 christos break;
941 1.1 christos
942 1.1 christos case bfd_reloc_notsupported:
943 1.1 christos msg = _("internal error: unsupported relocation error");
944 1.1 christos break;
945 1.1 christos
946 1.1 christos case bfd_reloc_dangerous:
947 1.1 christos msg = _("internal error: dangerous relocation");
948 1.1 christos break;
949 1.1 christos
950 1.1 christos default:
951 1.1 christos msg = _("internal error: unknown error");
952 1.1 christos break;
953 1.1 christos }
954 1.1 christos
955 1.1 christos if (msg)
956 1.1 christos r = info->callbacks->warning
957 1.1 christos (info, msg, name, input_bfd, input_section, rel->r_offset);
958 1.1 christos
959 1.1 christos if (! r)
960 1.1 christos return FALSE;
961 1.1 christos }
962 1.1 christos }
963 1.1 christos
964 1.1 christos return TRUE;
965 1.1 christos }
966 1.1 christos
967 1.1 christos /* This must exist if dynobj is ever set. */
968 1.1 christos
969 1.1 christos static bfd_boolean
970 1.1 christos xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED,
971 1.1 christos struct bfd_link_info *info)
972 1.1 christos {
973 1.1 christos bfd *dynobj;
974 1.1 christos asection *splt;
975 1.1 christos
976 1.1 christos /* As an extra sanity check, verify that all plt entries have
977 1.1.1.2 christos been filled in. */
978 1.1 christos
979 1.1 christos if ((dynobj = elf_hash_table (info)->dynobj) != NULL
980 1.1 christos && (splt = bfd_get_linker_section (dynobj, ".plt")) != NULL)
981 1.1 christos {
982 1.1 christos bfd_byte *contents = splt->contents;
983 1.1 christos unsigned int i, size = splt->size;
984 1.1 christos
985 1.1 christos for (i = 0; i < size; i += 4)
986 1.1 christos {
987 1.1 christos unsigned int x = bfd_get_32 (dynobj, contents + i);
988 1.1 christos
989 1.1 christos BFD_ASSERT (x != 0);
990 1.1 christos }
991 1.1 christos }
992 1.1 christos
993 1.1 christos return TRUE;
994 1.1 christos }
995 1.1 christos
996 1.1 christos /* Return the section that should be marked against GC for a given
998 1.1 christos relocation. */
999 1.1 christos
1000 1.1 christos static asection *
1001 1.1 christos xstormy16_elf_gc_mark_hook (asection *sec,
1002 1.1 christos struct bfd_link_info *info,
1003 1.1 christos Elf_Internal_Rela *rel,
1004 1.1 christos struct elf_link_hash_entry *h,
1005 1.1 christos Elf_Internal_Sym *sym)
1006 1.1 christos {
1007 1.1 christos if (h != NULL)
1008 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
1009 1.1 christos {
1010 1.1 christos case R_XSTORMY16_GNU_VTINHERIT:
1011 1.1 christos case R_XSTORMY16_GNU_VTENTRY:
1012 1.1 christos return NULL;
1013 1.1 christos }
1014 1.1 christos
1015 1.1 christos return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
1016 1.1 christos }
1017 1.1 christos
1018 1.1 christos #define ELF_ARCH bfd_arch_xstormy16
1020 1.1 christos #define ELF_MACHINE_CODE EM_XSTORMY16
1021 1.1 christos #define ELF_MAXPAGESIZE 0x100
1022 1.1 christos
1023 1.1 christos #define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1024 1.1 christos #define TARGET_LITTLE_NAME "elf32-xstormy16"
1025 1.1 christos
1026 1.1 christos #define elf_info_to_howto_rel NULL
1027 1.1 christos #define elf_info_to_howto xstormy16_info_to_howto_rela
1028 1.1 christos #define elf_backend_relocate_section xstormy16_elf_relocate_section
1029 1.1 christos #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
1030 1.1 christos #define elf_backend_check_relocs xstormy16_elf_check_relocs
1031 1.1 christos #define elf_backend_always_size_sections \
1032 1.1 christos xstormy16_elf_always_size_sections
1033 1.1 christos #define elf_backend_omit_section_dynsym \
1034 1.1 christos ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
1035 1.1 christos #define elf_backend_finish_dynamic_sections \
1036 1.1 christos xstormy16_elf_finish_dynamic_sections
1037 1.1 christos
1038 1.1 christos #define elf_backend_can_gc_sections 1
1039 1.1 christos #define elf_backend_rela_normal 1
1040 1.1 christos
1041 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1042 #define bfd_elf32_bfd_reloc_name_lookup \
1043 xstormy16_reloc_name_lookup
1044 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1045
1046 #include "elf32-target.h"
1047