Add copyright notices
[deliverable/binutils-gdb.git] / bfd / elf32-fr30.c
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 \f
234 /* Utility to actually perform an R_FR30_20 reloc. */
235
236 static bfd_reloc_status_type
237 fr30_elf_i20_reloc (bfd *abfd,
238 arelent *reloc_entry,
239 asymbol *symbol,
240 void * data,
241 asection *input_section,
242 bfd *output_bfd,
243 char **error_message ATTRIBUTE_UNUSED)
244 {
245 bfd_vma relocation;
246 unsigned long x;
247
248 /* This part is from bfd_elf_generic_reloc. */
249 if (output_bfd != (bfd *) NULL
250 && (symbol->flags & BSF_SECTION_SYM) == 0
251 && (! reloc_entry->howto->partial_inplace
252 || reloc_entry->addend == 0))
253 {
254 reloc_entry->address += input_section->output_offset;
255 return bfd_reloc_ok;
256 }
257
258 if (output_bfd != NULL)
259 /* FIXME: See bfd_perform_relocation. Is this right? */
260 return bfd_reloc_ok;
261
262 relocation =
263 symbol->value
264 + symbol->section->output_section->vma
265 + symbol->section->output_offset
266 + reloc_entry->addend;
267
268 if (relocation > (((bfd_vma) 1 << 20) - 1))
269 return bfd_reloc_overflow;
270
271 x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
272 x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
273 bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
274
275 return bfd_reloc_ok;
276 }
277 \f
278 /* Utility to actually perform a R_FR30_48 reloc. */
279
280 static bfd_reloc_status_type
281 fr30_elf_i32_reloc (bfd *abfd,
282 arelent *reloc_entry,
283 asymbol *symbol,
284 void * data,
285 asection *input_section,
286 bfd *output_bfd,
287 char **error_message ATTRIBUTE_UNUSED)
288 {
289 bfd_vma relocation;
290
291 /* This part is from bfd_elf_generic_reloc. */
292 if (output_bfd != (bfd *) NULL
293 && (symbol->flags & BSF_SECTION_SYM) == 0
294 && (! reloc_entry->howto->partial_inplace
295 || reloc_entry->addend == 0))
296 {
297 reloc_entry->address += input_section->output_offset;
298 return bfd_reloc_ok;
299 }
300
301 if (output_bfd != NULL)
302 /* FIXME: See bfd_perform_relocation. Is this right? */
303 return bfd_reloc_ok;
304
305 relocation =
306 symbol->value
307 + symbol->section->output_section->vma
308 + symbol->section->output_offset
309 + reloc_entry->addend;
310
311 bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
312
313 return bfd_reloc_ok;
314 }
315 \f
316 /* Map BFD reloc types to FR30 ELF reloc types. */
317
318 struct fr30_reloc_map
319 {
320 bfd_reloc_code_real_type bfd_reloc_val;
321 unsigned int fr30_reloc_val;
322 };
323
324 static const struct fr30_reloc_map fr30_reloc_map [] =
325 {
326 { BFD_RELOC_NONE, R_FR30_NONE },
327 { BFD_RELOC_8, R_FR30_8 },
328 { BFD_RELOC_FR30_20, R_FR30_20 },
329 { BFD_RELOC_32, R_FR30_32 },
330 { BFD_RELOC_FR30_48, R_FR30_48 },
331 { BFD_RELOC_FR30_6_IN_4, R_FR30_6_IN_4 },
332 { BFD_RELOC_FR30_8_IN_8, R_FR30_8_IN_8 },
333 { BFD_RELOC_FR30_9_IN_8, R_FR30_9_IN_8 },
334 { BFD_RELOC_FR30_10_IN_8, R_FR30_10_IN_8 },
335 { BFD_RELOC_FR30_9_PCREL, R_FR30_9_PCREL },
336 { BFD_RELOC_FR30_12_PCREL, R_FR30_12_PCREL },
337 { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
338 { BFD_RELOC_VTABLE_ENTRY, R_FR30_GNU_VTENTRY },
339 };
340
341 static reloc_howto_type *
342 fr30_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
343 bfd_reloc_code_real_type code)
344 {
345 unsigned int i;
346
347 for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
348 --i;)
349 if (fr30_reloc_map [i].bfd_reloc_val == code)
350 return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
351
352 return NULL;
353 }
354
355 static reloc_howto_type *
356 fr30_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
357 {
358 unsigned int i;
359
360 for (i = 0;
361 i < sizeof (fr30_elf_howto_table) / sizeof (fr30_elf_howto_table[0]);
362 i++)
363 if (fr30_elf_howto_table[i].name != NULL
364 && strcasecmp (fr30_elf_howto_table[i].name, r_name) == 0)
365 return &fr30_elf_howto_table[i];
366
367 return NULL;
368 }
369
370 /* Set the howto pointer for an FR30 ELF reloc. */
371
372 static void
373 fr30_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
374 arelent *cache_ptr,
375 Elf_Internal_Rela *dst)
376 {
377 unsigned int r_type;
378
379 r_type = ELF32_R_TYPE (dst->r_info);
380 BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
381 cache_ptr->howto = & fr30_elf_howto_table [r_type];
382 }
383 \f
384 /* Perform a single relocation. By default we use the standard BFD
385 routines, but a few relocs, we have to do them ourselves. */
386
387 static bfd_reloc_status_type
388 fr30_final_link_relocate (reloc_howto_type *howto,
389 bfd *input_bfd,
390 asection *input_section,
391 bfd_byte *contents,
392 Elf_Internal_Rela *rel,
393 bfd_vma relocation)
394 {
395 bfd_reloc_status_type r = bfd_reloc_ok;
396 bfd_vma x;
397 bfd_signed_vma srel;
398
399 switch (howto->type)
400 {
401 case R_FR30_20:
402 contents += rel->r_offset;
403 relocation += rel->r_addend;
404
405 if (relocation > ((1 << 20) - 1))
406 return bfd_reloc_overflow;
407
408 x = bfd_get_32 (input_bfd, contents);
409 x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
410 bfd_put_32 (input_bfd, x, contents);
411 break;
412
413 case R_FR30_48:
414 contents += rel->r_offset + 2;
415 relocation += rel->r_addend;
416 bfd_put_32 (input_bfd, relocation, contents);
417 break;
418
419 case R_FR30_9_PCREL:
420 contents += rel->r_offset + 1;
421 srel = (bfd_signed_vma) relocation;
422 srel += rel->r_addend;
423 srel -= rel->r_offset;
424 srel -= 2; /* Branch instructions add 2 to the PC... */
425 srel -= (input_section->output_section->vma +
426 input_section->output_offset);
427
428 if (srel & 1)
429 return bfd_reloc_outofrange;
430 if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
431 return bfd_reloc_overflow;
432
433 bfd_put_8 (input_bfd, srel >> 1, contents);
434 break;
435
436 case R_FR30_12_PCREL:
437 contents += rel->r_offset;
438 srel = (bfd_signed_vma) relocation;
439 srel += rel->r_addend;
440 srel -= rel->r_offset;
441 srel -= 2; /* Branch instructions add 2 to the PC... */
442 srel -= (input_section->output_section->vma +
443 input_section->output_offset);
444
445 if (srel & 1)
446 return bfd_reloc_outofrange;
447 if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
448 return bfd_reloc_overflow;
449
450 x = bfd_get_16 (input_bfd, contents);
451 x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
452 bfd_put_16 (input_bfd, x, contents);
453 break;
454
455 default:
456 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
457 contents, rel->r_offset,
458 relocation, rel->r_addend);
459 }
460
461 return r;
462 }
463 \f
464 /* Relocate an FR30 ELF section.
465
466 The RELOCATE_SECTION function is called by the new ELF backend linker
467 to handle the relocations for a section.
468
469 The relocs are always passed as Rela structures; if the section
470 actually uses Rel structures, the r_addend field will always be
471 zero.
472
473 This function is responsible for adjusting the section contents as
474 necessary, and (if using Rela relocs and generating a relocatable
475 output file) adjusting the reloc addend as necessary.
476
477 This function does not have to worry about setting the reloc
478 address or the reloc symbol index.
479
480 LOCAL_SYMS is a pointer to the swapped in local symbols.
481
482 LOCAL_SECTIONS is an array giving the section in the input file
483 corresponding to the st_shndx field of each local symbol.
484
485 The global hash table entry for the global symbols can be found
486 via elf_sym_hashes (input_bfd).
487
488 When generating relocatable output, this function must handle
489 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
490 going to be the section symbol corresponding to the output
491 section, which means that the addend must be adjusted
492 accordingly. */
493
494 static bfd_boolean
495 fr30_elf_relocate_section (bfd *output_bfd,
496 struct bfd_link_info *info,
497 bfd *input_bfd,
498 asection *input_section,
499 bfd_byte *contents,
500 Elf_Internal_Rela *relocs,
501 Elf_Internal_Sym *local_syms,
502 asection **local_sections)
503 {
504 Elf_Internal_Shdr *symtab_hdr;
505 struct elf_link_hash_entry **sym_hashes;
506 Elf_Internal_Rela *rel;
507 Elf_Internal_Rela *relend;
508
509 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
510 sym_hashes = elf_sym_hashes (input_bfd);
511 relend = relocs + input_section->reloc_count;
512
513 for (rel = relocs; rel < relend; rel ++)
514 {
515 reloc_howto_type *howto;
516 unsigned long r_symndx;
517 Elf_Internal_Sym *sym;
518 asection *sec;
519 struct elf_link_hash_entry *h;
520 bfd_vma relocation;
521 bfd_reloc_status_type r;
522 const char *name;
523 int r_type;
524
525 r_type = ELF32_R_TYPE (rel->r_info);
526
527 if ( r_type == R_FR30_GNU_VTINHERIT
528 || r_type == R_FR30_GNU_VTENTRY)
529 continue;
530
531 r_symndx = ELF32_R_SYM (rel->r_info);
532
533 howto = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
534 h = NULL;
535 sym = NULL;
536 sec = NULL;
537
538 if (r_symndx < symtab_hdr->sh_info)
539 {
540 sym = local_syms + r_symndx;
541 sec = local_sections [r_symndx];
542 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
543
544 name = bfd_elf_string_from_elf_section
545 (input_bfd, symtab_hdr->sh_link, sym->st_name);
546 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
547 }
548 else
549 {
550 bfd_boolean unresolved_reloc, warned;
551
552 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
553 r_symndx, symtab_hdr, sym_hashes,
554 h, sec, relocation,
555 unresolved_reloc, warned);
556
557 name = h->root.root.string;
558 }
559
560 if (sec != NULL && discarded_section (sec))
561 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
562 rel, 1, relend, howto, 0, contents);
563
564 if (info->relocatable)
565 continue;
566
567 r = fr30_final_link_relocate (howto, input_bfd, input_section,
568 contents, rel, relocation);
569
570 if (r != bfd_reloc_ok)
571 {
572 const char * msg = (const char *) NULL;
573
574 switch (r)
575 {
576 case bfd_reloc_overflow:
577 r = info->callbacks->reloc_overflow
578 (info, (h ? &h->root : NULL), name, howto->name,
579 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
580 break;
581
582 case bfd_reloc_undefined:
583 r = info->callbacks->undefined_symbol
584 (info, name, input_bfd, input_section, rel->r_offset,
585 TRUE);
586 break;
587
588 case bfd_reloc_outofrange:
589 msg = _("internal error: out of range error");
590 break;
591
592 case bfd_reloc_notsupported:
593 msg = _("internal error: unsupported relocation error");
594 break;
595
596 case bfd_reloc_dangerous:
597 msg = _("internal error: dangerous relocation");
598 break;
599
600 default:
601 msg = _("internal error: unknown error");
602 break;
603 }
604
605 if (msg)
606 r = info->callbacks->warning
607 (info, msg, name, input_bfd, input_section, rel->r_offset);
608
609 if (! r)
610 return FALSE;
611 }
612 }
613
614 return TRUE;
615 }
616 \f
617 /* Return the section that should be marked against GC for a given
618 relocation. */
619
620 static asection *
621 fr30_elf_gc_mark_hook (asection *sec,
622 struct bfd_link_info *info,
623 Elf_Internal_Rela *rel,
624 struct elf_link_hash_entry *h,
625 Elf_Internal_Sym *sym)
626 {
627 if (h != NULL)
628 switch (ELF32_R_TYPE (rel->r_info))
629 {
630 case R_FR30_GNU_VTINHERIT:
631 case R_FR30_GNU_VTENTRY:
632 return NULL;
633 }
634
635 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
636 }
637
638 /* Look through the relocs for a section during the first phase.
639 Since we don't do .gots or .plts, we just need to consider the
640 virtual table relocs for gc. */
641
642 static bfd_boolean
643 fr30_elf_check_relocs (bfd *abfd,
644 struct bfd_link_info *info,
645 asection *sec,
646 const Elf_Internal_Rela *relocs)
647 {
648 Elf_Internal_Shdr *symtab_hdr;
649 struct elf_link_hash_entry **sym_hashes;
650 const Elf_Internal_Rela *rel;
651 const Elf_Internal_Rela *rel_end;
652
653 if (info->relocatable)
654 return TRUE;
655
656 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
657 sym_hashes = elf_sym_hashes (abfd);
658
659 rel_end = relocs + sec->reloc_count;
660 for (rel = relocs; rel < rel_end; rel++)
661 {
662 struct elf_link_hash_entry *h;
663 unsigned long r_symndx;
664
665 r_symndx = ELF32_R_SYM (rel->r_info);
666 if (r_symndx < symtab_hdr->sh_info)
667 h = NULL;
668 else
669 {
670 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
671 while (h->root.type == bfd_link_hash_indirect
672 || h->root.type == bfd_link_hash_warning)
673 h = (struct elf_link_hash_entry *) h->root.u.i.link;
674 }
675
676 switch (ELF32_R_TYPE (rel->r_info))
677 {
678 /* This relocation describes the C++ object vtable hierarchy.
679 Reconstruct it for later use during GC. */
680 case R_FR30_GNU_VTINHERIT:
681 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
682 return FALSE;
683 break;
684
685 /* This relocation describes which C++ vtable entries are actually
686 used. Record for later use during GC. */
687 case R_FR30_GNU_VTENTRY:
688 BFD_ASSERT (h != NULL);
689 if (h != NULL
690 && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
691 return FALSE;
692 break;
693 }
694 }
695
696 return TRUE;
697 }
698 \f
699 #define ELF_ARCH bfd_arch_fr30
700 #define ELF_MACHINE_CODE EM_FR30
701 #define ELF_MACHINE_ALT1 EM_CYGNUS_FR30
702 #define ELF_MAXPAGESIZE 0x1000
703
704 #define TARGET_BIG_SYM bfd_elf32_fr30_vec
705 #define TARGET_BIG_NAME "elf32-fr30"
706
707 #define elf_info_to_howto_rel NULL
708 #define elf_info_to_howto fr30_info_to_howto_rela
709 #define elf_backend_relocate_section fr30_elf_relocate_section
710 #define elf_backend_gc_mark_hook fr30_elf_gc_mark_hook
711 #define elf_backend_check_relocs fr30_elf_check_relocs
712
713 #define elf_backend_can_gc_sections 1
714 #define elf_backend_rela_normal 1
715
716 #define bfd_elf32_bfd_reloc_type_lookup fr30_reloc_type_lookup
717 #define bfd_elf32_bfd_reloc_name_lookup fr30_reloc_name_lookup
718
719 #include "elf32-target.h"
This page took 0.059754 seconds and 4 git commands to generate.