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