elf32-fr30.c revision 1.5 1 1.1 christos /* FR30-specific support for 32-bit ELF.
2 1.3 christos Copyright (C) 1998-2015 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of BFD, the Binary File Descriptor library.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3 of the License, or
9 1.1 christos (at your option) any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software
18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 christos MA 02110-1301, USA. */
20 1.1 christos
21 1.1 christos #include "sysdep.h"
22 1.1 christos #include "bfd.h"
23 1.1 christos #include "libbfd.h"
24 1.1 christos #include "elf-bfd.h"
25 1.1 christos #include "elf/fr30.h"
26 1.1 christos
27 1.1 christos /* Forward declarations. */
28 1.1 christos static bfd_reloc_status_type
29 1.1 christos fr30_elf_i20_reloc (bfd *, arelent *, asymbol *, void * data,
30 1.1 christos asection *, bfd *, char **error_message);
31 1.1 christos static bfd_reloc_status_type
32 1.1 christos fr30_elf_i32_reloc (bfd *, arelent *, asymbol *, void *,
33 1.1 christos asection *, bfd *, char **);
34 1.1 christos
35 1.1 christos static reloc_howto_type fr30_elf_howto_table [] =
36 1.1 christos {
37 1.1 christos /* This reloc does nothing. */
38 1.1 christos HOWTO (R_FR30_NONE, /* type */
39 1.1 christos 0, /* rightshift */
40 1.5 christos 3, /* size (0 = byte, 1 = short, 2 = long) */
41 1.5 christos 0, /* bitsize */
42 1.1 christos FALSE, /* pc_relative */
43 1.1 christos 0, /* bitpos */
44 1.5 christos complain_overflow_dont, /* complain_on_overflow */
45 1.1 christos bfd_elf_generic_reloc, /* special_function */
46 1.1 christos "R_FR30_NONE", /* name */
47 1.1 christos FALSE, /* partial_inplace */
48 1.1 christos 0, /* src_mask */
49 1.1 christos 0, /* dst_mask */
50 1.1 christos FALSE), /* pcrel_offset */
51 1.1 christos
52 1.1 christos /* An 8 bit absolute relocation. */
53 1.1 christos HOWTO (R_FR30_8, /* type */
54 1.1 christos 0, /* rightshift */
55 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
56 1.1 christos 8, /* bitsize */
57 1.1 christos FALSE, /* pc_relative */
58 1.1 christos 4, /* bitpos */
59 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
60 1.1 christos bfd_elf_generic_reloc, /* special_function */
61 1.1 christos "R_FR30_8", /* name */
62 1.1 christos FALSE, /* partial_inplace */
63 1.1 christos 0x0000, /* src_mask */
64 1.1 christos 0x0ff0, /* dst_mask */
65 1.1 christos FALSE), /* pcrel_offset */
66 1.1 christos
67 1.1 christos /* A 20 bit absolute relocation. */
68 1.1 christos HOWTO (R_FR30_20, /* type */
69 1.1 christos 0, /* rightshift */
70 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
71 1.1 christos 20, /* 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 fr30_elf_i20_reloc, /* special_function */
76 1.1 christos "R_FR30_20", /* name */
77 1.1 christos FALSE, /* partial_inplace */
78 1.1 christos 0x00000000, /* src_mask */
79 1.1 christos 0x00f0ffff, /* dst_mask */
80 1.1 christos FALSE), /* pcrel_offset */
81 1.1 christos
82 1.1 christos /* A 32 bit absolute relocation. */
83 1.1 christos HOWTO (R_FR30_32, /* type */
84 1.1 christos 0, /* rightshift */
85 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
86 1.1 christos 32, /* bitsize */
87 1.1 christos FALSE, /* 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_FR30_32", /* name */
92 1.1 christos FALSE, /* partial_inplace */
93 1.1 christos 0x00000000, /* src_mask */
94 1.1 christos 0xffffffff, /* dst_mask */
95 1.1 christos FALSE), /* pcrel_offset */
96 1.1 christos
97 1.1 christos /* A 32 bit into 48 bits absolute relocation. */
98 1.1 christos HOWTO (R_FR30_48, /* type */
99 1.1 christos 0, /* rightshift */
100 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
101 1.1 christos 32, /* bitsize */
102 1.1 christos FALSE, /* pc_relative */
103 1.1 christos 0, /* bitpos */
104 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
105 1.1 christos fr30_elf_i32_reloc, /* special_function */
106 1.1 christos "R_FR30_48", /* name */
107 1.1 christos FALSE, /* partial_inplace */
108 1.1 christos 0x00000000, /* src_mask */
109 1.1 christos 0xffffffff, /* dst_mask */
110 1.1 christos FALSE), /* pcrel_offset */
111 1.1 christos
112 1.1 christos /* A 6 bit absolute relocation. */
113 1.1 christos HOWTO (R_FR30_6_IN_4, /* type */
114 1.1 christos 2, /* rightshift */
115 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
116 1.1 christos 6, /* bitsize */
117 1.1 christos FALSE, /* pc_relative */
118 1.1 christos 4, /* bitpos */
119 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
120 1.1 christos bfd_elf_generic_reloc, /* special_function */
121 1.1 christos "R_FR30_6_IN_4", /* name */
122 1.1 christos FALSE, /* partial_inplace */
123 1.1 christos 0x0000, /* src_mask */
124 1.1 christos 0x00f0, /* dst_mask */
125 1.1 christos FALSE), /* pcrel_offset */
126 1.1 christos
127 1.1 christos /* An 8 bit absolute relocation. */
128 1.1 christos HOWTO (R_FR30_8_IN_8, /* type */
129 1.1 christos 0, /* rightshift */
130 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
131 1.1 christos 8, /* bitsize */
132 1.1 christos FALSE, /* pc_relative */
133 1.1 christos 4, /* bitpos */
134 1.1 christos complain_overflow_signed, /* complain_on_overflow */
135 1.1 christos bfd_elf_generic_reloc,/* special_function */
136 1.1 christos "R_FR30_8_IN_8", /* name */
137 1.1 christos FALSE, /* partial_inplace */
138 1.1 christos 0x0000, /* src_mask */
139 1.1 christos 0x0ff0, /* dst_mask */
140 1.1 christos FALSE), /* pcrel_offset */
141 1.1 christos
142 1.1 christos /* A 9 bit absolute relocation. */
143 1.1 christos HOWTO (R_FR30_9_IN_8, /* type */
144 1.1 christos 1, /* rightshift */
145 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
146 1.1 christos 9, /* bitsize */
147 1.1 christos FALSE, /* pc_relative */
148 1.1 christos 4, /* bitpos */
149 1.1 christos complain_overflow_signed, /* complain_on_overflow */
150 1.1 christos bfd_elf_generic_reloc,/* special_function */
151 1.1 christos "R_FR30_9_IN_8", /* name */
152 1.1 christos FALSE, /* partial_inplace */
153 1.1 christos 0x0000, /* src_mask */
154 1.1 christos 0x0ff0, /* dst_mask */
155 1.1 christos FALSE), /* pcrel_offset */
156 1.1 christos
157 1.1 christos /* A 10 bit absolute relocation. */
158 1.1 christos HOWTO (R_FR30_10_IN_8, /* type */
159 1.1 christos 2, /* rightshift */
160 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
161 1.1 christos 10, /* bitsize */
162 1.1 christos FALSE, /* pc_relative */
163 1.1 christos 4, /* bitpos */
164 1.1 christos complain_overflow_signed, /* complain_on_overflow */
165 1.1 christos bfd_elf_generic_reloc,/* special_function */
166 1.1 christos "R_FR30_10_IN_8", /* name */
167 1.1 christos FALSE, /* partial_inplace */
168 1.1 christos 0x0000, /* src_mask */
169 1.1 christos 0x0ff0, /* dst_mask */
170 1.1 christos FALSE), /* pcrel_offset */
171 1.1 christos
172 1.1 christos /* A PC relative 9 bit relocation, right shifted by 1. */
173 1.1 christos HOWTO (R_FR30_9_PCREL, /* type */
174 1.1 christos 1, /* rightshift */
175 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
176 1.1 christos 9, /* bitsize */
177 1.1 christos TRUE, /* pc_relative */
178 1.1 christos 0, /* bitpos */
179 1.1 christos complain_overflow_signed, /* complain_on_overflow */
180 1.1 christos bfd_elf_generic_reloc, /* special_function */
181 1.1 christos "R_FR30_9_PCREL", /* name */
182 1.1 christos FALSE, /* partial_inplace */
183 1.1 christos 0x0000, /* src_mask */
184 1.1 christos 0x00ff, /* dst_mask */
185 1.1 christos FALSE), /* pcrel_offset */
186 1.1 christos
187 1.1 christos /* A PC relative 12 bit relocation, right shifted by 1. */
188 1.1 christos HOWTO (R_FR30_12_PCREL, /* type */
189 1.1 christos 1, /* rightshift */
190 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
191 1.1 christos 12, /* bitsize */
192 1.1 christos TRUE, /* pc_relative */
193 1.1 christos 0, /* bitpos */
194 1.1 christos complain_overflow_signed, /* complain_on_overflow */
195 1.1 christos bfd_elf_generic_reloc, /* special_function */
196 1.1 christos "R_FR30_12_PCREL", /* name */
197 1.1 christos FALSE, /* partial_inplace */
198 1.1 christos 0x0000, /* src_mask */
199 1.1 christos 0x07ff, /* dst_mask */
200 1.1 christos FALSE), /* pcrel_offset */
201 1.1 christos /* GNU extension to record C++ vtable hierarchy */
202 1.1 christos HOWTO (R_FR30_GNU_VTINHERIT, /* type */
203 1.1 christos 0, /* rightshift */
204 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
205 1.1 christos 0, /* bitsize */
206 1.1 christos FALSE, /* pc_relative */
207 1.1 christos 0, /* bitpos */
208 1.1 christos complain_overflow_dont, /* complain_on_overflow */
209 1.1 christos NULL, /* special_function */
210 1.1 christos "R_FR30_GNU_VTINHERIT", /* name */
211 1.1 christos FALSE, /* partial_inplace */
212 1.1 christos 0, /* src_mask */
213 1.1 christos 0, /* dst_mask */
214 1.1 christos FALSE), /* pcrel_offset */
215 1.1 christos
216 1.1 christos /* GNU extension to record C++ vtable member usage */
217 1.1 christos HOWTO (R_FR30_GNU_VTENTRY, /* type */
218 1.1 christos 0, /* rightshift */
219 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
220 1.1 christos 0, /* bitsize */
221 1.1 christos FALSE, /* pc_relative */
222 1.1 christos 0, /* bitpos */
223 1.1 christos complain_overflow_dont, /* complain_on_overflow */
224 1.1 christos _bfd_elf_rel_vtable_reloc_fn, /* special_function */
225 1.1 christos "R_FR30_GNU_VTENTRY", /* name */
226 1.1 christos FALSE, /* partial_inplace */
227 1.1 christos 0, /* src_mask */
228 1.1 christos 0, /* dst_mask */
229 1.1 christos FALSE), /* pcrel_offset */
230 1.1 christos };
231 1.1 christos
232 1.1 christos /* Utility to actually perform an R_FR30_20 reloc. */
234 1.1 christos
235 1.1 christos static bfd_reloc_status_type
236 1.1 christos fr30_elf_i20_reloc (bfd *abfd,
237 1.1 christos arelent *reloc_entry,
238 1.1 christos asymbol *symbol,
239 1.1 christos void * data,
240 1.1 christos asection *input_section,
241 1.1 christos bfd *output_bfd,
242 1.1 christos char **error_message ATTRIBUTE_UNUSED)
243 1.1 christos {
244 1.1 christos bfd_vma relocation;
245 1.1 christos unsigned long x;
246 1.1 christos
247 1.1 christos /* This part is from bfd_elf_generic_reloc. */
248 1.1 christos if (output_bfd != (bfd *) NULL
249 1.1 christos && (symbol->flags & BSF_SECTION_SYM) == 0
250 1.1 christos && (! reloc_entry->howto->partial_inplace
251 1.1 christos || reloc_entry->addend == 0))
252 1.1 christos {
253 1.1 christos reloc_entry->address += input_section->output_offset;
254 1.1 christos return bfd_reloc_ok;
255 1.1 christos }
256 1.1 christos
257 1.1 christos if (output_bfd != NULL)
258 1.1 christos /* FIXME: See bfd_perform_relocation. Is this right? */
259 1.1 christos return bfd_reloc_ok;
260 1.1 christos
261 1.1 christos relocation =
262 1.1 christos symbol->value
263 1.1 christos + symbol->section->output_section->vma
264 1.1 christos + symbol->section->output_offset
265 1.1 christos + reloc_entry->addend;
266 1.1 christos
267 1.1 christos if (relocation > (((bfd_vma) 1 << 20) - 1))
268 1.1 christos return bfd_reloc_overflow;
269 1.1 christos
270 1.1 christos x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
271 1.1 christos x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
272 1.1 christos bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
273 1.1 christos
274 1.1 christos return bfd_reloc_ok;
275 1.1 christos }
276 1.1 christos
277 1.1 christos /* Utility to actually perform a R_FR30_48 reloc. */
279 1.1 christos
280 1.1 christos static bfd_reloc_status_type
281 1.1 christos fr30_elf_i32_reloc (bfd *abfd,
282 1.1 christos arelent *reloc_entry,
283 1.1 christos asymbol *symbol,
284 1.1 christos void * data,
285 1.1 christos asection *input_section,
286 1.1 christos bfd *output_bfd,
287 1.1 christos char **error_message ATTRIBUTE_UNUSED)
288 1.1 christos {
289 1.1 christos bfd_vma relocation;
290 1.1 christos
291 1.1 christos /* This part is from bfd_elf_generic_reloc. */
292 1.1 christos if (output_bfd != (bfd *) NULL
293 1.1 christos && (symbol->flags & BSF_SECTION_SYM) == 0
294 1.1 christos && (! reloc_entry->howto->partial_inplace
295 1.1 christos || reloc_entry->addend == 0))
296 1.1 christos {
297 1.1 christos reloc_entry->address += input_section->output_offset;
298 1.1 christos return bfd_reloc_ok;
299 1.1 christos }
300 1.1 christos
301 1.1 christos if (output_bfd != NULL)
302 1.1 christos /* FIXME: See bfd_perform_relocation. Is this right? */
303 1.1 christos return bfd_reloc_ok;
304 1.1 christos
305 1.1 christos relocation =
306 1.1 christos symbol->value
307 1.1 christos + symbol->section->output_section->vma
308 1.1 christos + symbol->section->output_offset
309 1.1 christos + reloc_entry->addend;
310 1.1 christos
311 1.1 christos bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
312 1.1 christos
313 1.1 christos return bfd_reloc_ok;
314 1.1 christos }
315 1.1 christos
316 1.1 christos /* Map BFD reloc types to FR30 ELF reloc types. */
318 1.1 christos
319 1.1 christos struct fr30_reloc_map
320 1.1 christos {
321 1.1 christos bfd_reloc_code_real_type bfd_reloc_val;
322 1.1 christos unsigned int fr30_reloc_val;
323 1.1 christos };
324 1.1 christos
325 1.1 christos static const struct fr30_reloc_map fr30_reloc_map [] =
326 1.1 christos {
327 1.1 christos { BFD_RELOC_NONE, R_FR30_NONE },
328 1.1 christos { BFD_RELOC_8, R_FR30_8 },
329 1.1 christos { BFD_RELOC_FR30_20, R_FR30_20 },
330 1.1 christos { BFD_RELOC_32, R_FR30_32 },
331 1.1 christos { BFD_RELOC_FR30_48, R_FR30_48 },
332 1.1 christos { BFD_RELOC_FR30_6_IN_4, R_FR30_6_IN_4 },
333 1.1 christos { BFD_RELOC_FR30_8_IN_8, R_FR30_8_IN_8 },
334 1.1 christos { BFD_RELOC_FR30_9_IN_8, R_FR30_9_IN_8 },
335 1.1 christos { BFD_RELOC_FR30_10_IN_8, R_FR30_10_IN_8 },
336 1.1 christos { BFD_RELOC_FR30_9_PCREL, R_FR30_9_PCREL },
337 1.1 christos { BFD_RELOC_FR30_12_PCREL, R_FR30_12_PCREL },
338 1.1 christos { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
339 1.1 christos { BFD_RELOC_VTABLE_ENTRY, R_FR30_GNU_VTENTRY },
340 1.1 christos };
341 1.1 christos
342 1.1 christos static reloc_howto_type *
343 1.1 christos fr30_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
344 1.1 christos bfd_reloc_code_real_type code)
345 1.1 christos {
346 1.5 christos unsigned int i;
347 1.1 christos
348 1.1 christos for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
349 1.1 christos i--;)
350 1.1 christos if (fr30_reloc_map [i].bfd_reloc_val == code)
351 1.1 christos return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
352 1.1 christos
353 1.1 christos return NULL;
354 1.1 christos }
355 1.1 christos
356 1.1 christos static reloc_howto_type *
357 1.1 christos fr30_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
358 1.1 christos {
359 1.1 christos unsigned int i;
360 1.1 christos
361 1.1 christos for (i = 0;
362 1.1 christos i < sizeof (fr30_elf_howto_table) / sizeof (fr30_elf_howto_table[0]);
363 1.1 christos i++)
364 1.1 christos if (fr30_elf_howto_table[i].name != NULL
365 1.1 christos && strcasecmp (fr30_elf_howto_table[i].name, r_name) == 0)
366 1.1 christos return &fr30_elf_howto_table[i];
367 1.1 christos
368 1.1 christos return NULL;
369 1.1 christos }
370 1.1 christos
371 1.1 christos /* Set the howto pointer for an FR30 ELF reloc. */
372 1.1 christos
373 1.1 christos static void
374 1.1 christos fr30_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
375 1.1 christos arelent *cache_ptr,
376 1.1 christos Elf_Internal_Rela *dst)
377 1.1 christos {
378 1.3 christos unsigned int r_type;
379 1.3 christos
380 1.5 christos r_type = ELF32_R_TYPE (dst->r_info);
381 1.3 christos if (r_type >= (unsigned int) R_FR30_max)
382 1.3 christos {
383 1.1 christos _bfd_error_handler (_("%B: invalid FR30 reloc number: %d"), abfd, r_type);
384 1.1 christos r_type = 0;
385 1.1 christos }
386 1.1 christos cache_ptr->howto = & fr30_elf_howto_table [r_type];
387 1.1 christos }
388 1.1 christos
389 1.1 christos /* Perform a single relocation. By default we use the standard BFD
391 1.1 christos routines, but a few relocs, we have to do them ourselves. */
392 1.1 christos
393 1.1 christos static bfd_reloc_status_type
394 1.1 christos fr30_final_link_relocate (reloc_howto_type *howto,
395 1.1 christos bfd *input_bfd,
396 1.1 christos asection *input_section,
397 1.1 christos bfd_byte *contents,
398 1.1 christos Elf_Internal_Rela *rel,
399 1.1 christos bfd_vma relocation)
400 1.1 christos {
401 1.1 christos bfd_reloc_status_type r = bfd_reloc_ok;
402 1.1 christos bfd_vma x;
403 1.1 christos bfd_signed_vma srel;
404 1.1 christos
405 1.1 christos switch (howto->type)
406 1.1 christos {
407 1.1 christos case R_FR30_20:
408 1.1 christos contents += rel->r_offset;
409 1.1 christos relocation += rel->r_addend;
410 1.1 christos
411 1.1 christos if (relocation > ((1 << 20) - 1))
412 1.1 christos return bfd_reloc_overflow;
413 1.1 christos
414 1.1 christos x = bfd_get_32 (input_bfd, contents);
415 1.1 christos x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
416 1.1 christos bfd_put_32 (input_bfd, x, contents);
417 1.1 christos break;
418 1.1 christos
419 1.1 christos case R_FR30_48:
420 1.1 christos contents += rel->r_offset + 2;
421 1.1 christos relocation += rel->r_addend;
422 1.1 christos bfd_put_32 (input_bfd, relocation, contents);
423 1.1 christos break;
424 1.1 christos
425 1.1 christos case R_FR30_9_PCREL:
426 1.1 christos contents += rel->r_offset + 1;
427 1.1 christos srel = (bfd_signed_vma) relocation;
428 1.1 christos srel += rel->r_addend;
429 1.1 christos srel -= rel->r_offset;
430 1.1 christos srel -= 2; /* Branch instructions add 2 to the PC... */
431 1.1 christos srel -= (input_section->output_section->vma +
432 1.1 christos input_section->output_offset);
433 1.1 christos
434 1.1 christos if (srel & 1)
435 1.1 christos return bfd_reloc_outofrange;
436 1.1 christos if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
437 1.1 christos return bfd_reloc_overflow;
438 1.1 christos
439 1.1 christos bfd_put_8 (input_bfd, srel >> 1, contents);
440 1.1 christos break;
441 1.1 christos
442 1.1 christos case R_FR30_12_PCREL:
443 1.1 christos contents += rel->r_offset;
444 1.1 christos srel = (bfd_signed_vma) relocation;
445 1.1 christos srel += rel->r_addend;
446 1.1 christos srel -= rel->r_offset;
447 1.1 christos srel -= 2; /* Branch instructions add 2 to the PC... */
448 1.1 christos srel -= (input_section->output_section->vma +
449 1.1 christos input_section->output_offset);
450 1.1 christos
451 1.1 christos if (srel & 1)
452 1.1 christos return bfd_reloc_outofrange;
453 1.1 christos if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
454 1.1 christos return bfd_reloc_overflow;
455 1.1 christos
456 1.1 christos x = bfd_get_16 (input_bfd, contents);
457 1.1 christos x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
458 1.1 christos bfd_put_16 (input_bfd, x, contents);
459 1.1 christos break;
460 1.1 christos
461 1.1 christos default:
462 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
463 1.1 christos contents, rel->r_offset,
464 1.1 christos relocation, rel->r_addend);
465 1.1 christos }
466 1.1 christos
467 1.1 christos return r;
468 1.1 christos }
469 1.1 christos
470 1.1 christos /* Relocate an FR30 ELF section.
472 1.1 christos
473 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker
474 1.1 christos to handle the relocations for a section.
475 1.1 christos
476 1.1 christos The relocs are always passed as Rela structures; if the section
477 1.1 christos actually uses Rel structures, the r_addend field will always be
478 1.1 christos zero.
479 1.1 christos
480 1.1 christos This function is responsible for adjusting the section contents as
481 1.1 christos necessary, and (if using Rela relocs and generating a relocatable
482 1.1 christos output file) adjusting the reloc addend as necessary.
483 1.1 christos
484 1.1 christos This function does not have to worry about setting the reloc
485 1.1 christos address or the reloc symbol index.
486 1.1 christos
487 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols.
488 1.1 christos
489 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file
490 1.1 christos corresponding to the st_shndx field of each local symbol.
491 1.1 christos
492 1.1 christos The global hash table entry for the global symbols can be found
493 1.1 christos via elf_sym_hashes (input_bfd).
494 1.1 christos
495 1.1 christos When generating relocatable output, this function must handle
496 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is
497 1.1 christos going to be the section symbol corresponding to the output
498 1.1 christos section, which means that the addend must be adjusted
499 1.1 christos accordingly. */
500 1.1 christos
501 1.1 christos static bfd_boolean
502 1.1 christos fr30_elf_relocate_section (bfd *output_bfd,
503 1.1 christos struct bfd_link_info *info,
504 1.1 christos bfd *input_bfd,
505 1.1 christos asection *input_section,
506 1.1 christos bfd_byte *contents,
507 1.1 christos Elf_Internal_Rela *relocs,
508 1.1 christos Elf_Internal_Sym *local_syms,
509 1.1 christos asection **local_sections)
510 1.1 christos {
511 1.1 christos Elf_Internal_Shdr *symtab_hdr;
512 1.1 christos struct elf_link_hash_entry **sym_hashes;
513 1.1 christos Elf_Internal_Rela *rel;
514 1.1 christos Elf_Internal_Rela *relend;
515 1.1 christos
516 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
517 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
518 1.1 christos relend = relocs + input_section->reloc_count;
519 1.1 christos
520 1.1 christos for (rel = relocs; rel < relend; rel ++)
521 1.1 christos {
522 1.1 christos reloc_howto_type *howto;
523 1.1 christos unsigned long r_symndx;
524 1.1 christos Elf_Internal_Sym *sym;
525 1.1 christos asection *sec;
526 1.1 christos struct elf_link_hash_entry *h;
527 1.1 christos bfd_vma relocation;
528 1.1 christos bfd_reloc_status_type r;
529 1.1 christos const char *name;
530 1.1 christos int r_type;
531 1.1 christos
532 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
533 1.1 christos
534 1.1 christos if ( r_type == R_FR30_GNU_VTINHERIT
535 1.1 christos || r_type == R_FR30_GNU_VTENTRY)
536 1.1 christos continue;
537 1.1 christos
538 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
539 1.1 christos
540 1.1 christos howto = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
541 1.1 christos h = NULL;
542 1.1 christos sym = NULL;
543 1.1 christos sec = NULL;
544 1.1 christos
545 1.1 christos if (r_symndx < symtab_hdr->sh_info)
546 1.1 christos {
547 1.1 christos sym = local_syms + r_symndx;
548 1.1 christos sec = local_sections [r_symndx];
549 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
550 1.1 christos
551 1.1 christos name = bfd_elf_string_from_elf_section
552 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name);
553 1.1 christos name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
554 1.1 christos }
555 1.1 christos else
556 1.1 christos {
557 1.1 christos bfd_boolean unresolved_reloc, warned, ignored;
558 1.1 christos
559 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
560 1.1 christos r_symndx, symtab_hdr, sym_hashes,
561 1.1 christos h, sec, relocation,
562 1.1 christos unresolved_reloc, warned, ignored);
563 1.1 christos
564 1.1 christos name = h->root.root.string;
565 1.1 christos }
566 1.1 christos
567 1.1 christos if (sec != NULL && discarded_section (sec))
568 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
569 1.1 christos rel, 1, relend, howto, 0, contents);
570 1.1 christos
571 1.1 christos if (info->relocatable)
572 1.1 christos continue;
573 1.1 christos
574 1.1 christos r = fr30_final_link_relocate (howto, input_bfd, input_section,
575 1.1 christos contents, rel, relocation);
576 1.1 christos
577 1.1 christos if (r != bfd_reloc_ok)
578 1.1 christos {
579 1.1 christos const char * msg = (const char *) NULL;
580 1.1 christos
581 1.1 christos switch (r)
582 1.1 christos {
583 1.1 christos case bfd_reloc_overflow:
584 1.1 christos r = info->callbacks->reloc_overflow
585 1.1 christos (info, (h ? &h->root : NULL), name, howto->name,
586 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
587 1.1 christos break;
588 1.1 christos
589 1.1 christos case bfd_reloc_undefined:
590 1.1 christos r = info->callbacks->undefined_symbol
591 1.1 christos (info, name, input_bfd, input_section, rel->r_offset,
592 1.1 christos TRUE);
593 1.1 christos break;
594 1.1 christos
595 1.1 christos case bfd_reloc_outofrange:
596 1.1 christos msg = _("internal error: out of range error");
597 1.1 christos break;
598 1.1 christos
599 1.1 christos case bfd_reloc_notsupported:
600 1.1 christos msg = _("internal error: unsupported relocation error");
601 1.1 christos break;
602 1.1 christos
603 1.1 christos case bfd_reloc_dangerous:
604 1.1 christos msg = _("internal error: dangerous relocation");
605 1.1 christos break;
606 1.1 christos
607 1.1 christos default:
608 1.1 christos msg = _("internal error: unknown error");
609 1.1 christos break;
610 1.1 christos }
611 1.1 christos
612 1.1 christos if (msg)
613 1.1 christos r = info->callbacks->warning
614 1.1 christos (info, msg, name, input_bfd, input_section, rel->r_offset);
615 1.1 christos
616 1.1 christos if (! r)
617 1.1 christos return FALSE;
618 1.1 christos }
619 1.1 christos }
620 1.1 christos
621 1.1 christos return TRUE;
622 1.1 christos }
623 1.1 christos
624 1.1 christos /* Return the section that should be marked against GC for a given
626 1.1 christos relocation. */
627 1.1 christos
628 1.1 christos static asection *
629 1.1 christos fr30_elf_gc_mark_hook (asection *sec,
630 1.1 christos struct bfd_link_info *info,
631 1.1 christos Elf_Internal_Rela *rel,
632 1.1 christos struct elf_link_hash_entry *h,
633 1.1 christos Elf_Internal_Sym *sym)
634 1.1 christos {
635 1.1 christos if (h != NULL)
636 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
637 1.1 christos {
638 1.1 christos case R_FR30_GNU_VTINHERIT:
639 1.1 christos case R_FR30_GNU_VTENTRY:
640 1.1 christos return NULL;
641 1.1 christos }
642 1.1 christos
643 1.1 christos return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
644 1.1 christos }
645 1.1 christos
646 1.1 christos /* Look through the relocs for a section during the first phase.
647 1.1 christos Since we don't do .gots or .plts, we just need to consider the
648 1.1 christos virtual table relocs for gc. */
649 1.1 christos
650 1.1 christos static bfd_boolean
651 1.1 christos fr30_elf_check_relocs (bfd *abfd,
652 1.1 christos struct bfd_link_info *info,
653 1.1 christos asection *sec,
654 1.1 christos const Elf_Internal_Rela *relocs)
655 1.1 christos {
656 1.1 christos Elf_Internal_Shdr *symtab_hdr;
657 1.1 christos struct elf_link_hash_entry **sym_hashes;
658 1.1 christos const Elf_Internal_Rela *rel;
659 1.1 christos const Elf_Internal_Rela *rel_end;
660 1.1 christos
661 1.1 christos if (info->relocatable)
662 1.1 christos return TRUE;
663 1.1 christos
664 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
665 1.1 christos sym_hashes = elf_sym_hashes (abfd);
666 1.1 christos
667 1.1 christos rel_end = relocs + sec->reloc_count;
668 1.1 christos for (rel = relocs; rel < rel_end; rel++)
669 1.1 christos {
670 1.1 christos struct elf_link_hash_entry *h;
671 1.1 christos unsigned long r_symndx;
672 1.1 christos
673 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
674 1.1 christos if (r_symndx < symtab_hdr->sh_info)
675 1.1 christos h = NULL;
676 1.1 christos else
677 1.1 christos {
678 1.1 christos h = sym_hashes[r_symndx - symtab_hdr->sh_info];
679 1.1 christos while (h->root.type == bfd_link_hash_indirect
680 1.1 christos || h->root.type == bfd_link_hash_warning)
681 1.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link;
682 1.1 christos
683 1.1 christos /* PR15323, ref flags aren't set for references in the same
684 1.1 christos object. */
685 1.1 christos h->root.non_ir_ref = 1;
686 1.1 christos }
687 1.1 christos
688 1.1 christos switch (ELF32_R_TYPE (rel->r_info))
689 1.1 christos {
690 1.1 christos /* This relocation describes the C++ object vtable hierarchy.
691 1.1 christos Reconstruct it for later use during GC. */
692 1.1 christos case R_FR30_GNU_VTINHERIT:
693 1.1 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
694 1.1 christos return FALSE;
695 1.1 christos break;
696 1.1 christos
697 1.1 christos /* This relocation describes which C++ vtable entries are actually
698 1.1 christos used. Record for later use during GC. */
699 1.1 christos case R_FR30_GNU_VTENTRY:
700 1.1 christos BFD_ASSERT (h != NULL);
701 1.1 christos if (h != NULL
702 1.1 christos && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
703 1.1 christos return FALSE;
704 1.1 christos break;
705 1.1 christos }
706 1.1 christos }
707 1.1 christos
708 1.1 christos return TRUE;
709 1.1 christos }
710 1.3 christos
711 1.1 christos #define ELF_ARCH bfd_arch_fr30
713 1.1 christos #define ELF_MACHINE_CODE EM_FR30
714 1.1 christos #define ELF_MACHINE_ALT1 EM_CYGNUS_FR30
715 1.1 christos #define ELF_MAXPAGESIZE 0x1000
716 1.1 christos
717 1.1 christos #define TARGET_BIG_SYM fr30_elf32_vec
718 1.1 christos #define TARGET_BIG_NAME "elf32-fr30"
719 1.1 christos
720 1.1 christos #define elf_info_to_howto_rel NULL
721 1.1 christos #define elf_info_to_howto fr30_info_to_howto_rela
722 1.1 christos #define elf_backend_relocate_section fr30_elf_relocate_section
723 1.1 christos #define elf_backend_gc_mark_hook fr30_elf_gc_mark_hook
724 1.1 christos #define elf_backend_check_relocs fr30_elf_check_relocs
725 1.1 christos
726 #define elf_backend_can_gc_sections 1
727 #define elf_backend_rela_normal 1
728
729 #define bfd_elf32_bfd_reloc_type_lookup fr30_reloc_type_lookup
730 #define bfd_elf32_bfd_reloc_name_lookup fr30_reloc_name_lookup
731
732 #include "elf32-target.h"
733