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