source: trunk/src/binutils/bfd/elf32-fr30.c@ 610

Last change on this file since 610 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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