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