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