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