1 /* FR30-specific support for 32-bit ELF. 2 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 3 2010, 2012 4 Free Software Foundation, Inc. 5 6 This file is part of BFD, the Binary File Descriptor library. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 MA 02110-1301, USA. */ 22 23 #include "sysdep.h" 24 #include "bfd.h" 25 #include "libbfd.h" 26 #include "elf-bfd.h" 27 #include "elf/fr30.h" 28 29 /* Forward declarations. */ 30 static bfd_reloc_status_type 31 fr30_elf_i20_reloc (bfd *, arelent *, asymbol *, void * data, 32 asection *, bfd *, char **error_message); 33 static bfd_reloc_status_type 34 fr30_elf_i32_reloc (bfd *, arelent *, asymbol *, void *, 35 asection *, bfd *, char **); 36 37 static reloc_howto_type fr30_elf_howto_table [] = 38 { 39 /* This reloc does nothing. */ 40 HOWTO (R_FR30_NONE, /* type */ 41 0, /* rightshift */ 42 2, /* size (0 = byte, 1 = short, 2 = long) */ 43 32, /* bitsize */ 44 FALSE, /* pc_relative */ 45 0, /* bitpos */ 46 complain_overflow_bitfield, /* complain_on_overflow */ 47 bfd_elf_generic_reloc, /* special_function */ 48 "R_FR30_NONE", /* name */ 49 FALSE, /* partial_inplace */ 50 0, /* src_mask */ 51 0, /* dst_mask */ 52 FALSE), /* pcrel_offset */ 53 54 /* An 8 bit absolute relocation. */ 55 HOWTO (R_FR30_8, /* type */ 56 0, /* rightshift */ 57 1, /* size (0 = byte, 1 = short, 2 = long) */ 58 8, /* bitsize */ 59 FALSE, /* pc_relative */ 60 4, /* bitpos */ 61 complain_overflow_bitfield, /* complain_on_overflow */ 62 bfd_elf_generic_reloc, /* special_function */ 63 "R_FR30_8", /* name */ 64 FALSE, /* partial_inplace */ 65 0x0000, /* src_mask */ 66 0x0ff0, /* dst_mask */ 67 FALSE), /* pcrel_offset */ 68 69 /* A 20 bit absolute relocation. */ 70 HOWTO (R_FR30_20, /* type */ 71 0, /* rightshift */ 72 2, /* size (0 = byte, 1 = short, 2 = long) */ 73 20, /* bitsize */ 74 FALSE, /* pc_relative */ 75 0, /* bitpos */ 76 complain_overflow_bitfield, /* complain_on_overflow */ 77 fr30_elf_i20_reloc, /* special_function */ 78 "R_FR30_20", /* name */ 79 FALSE, /* partial_inplace */ 80 0x00000000, /* src_mask */ 81 0x00f0ffff, /* dst_mask */ 82 FALSE), /* pcrel_offset */ 83 84 /* A 32 bit absolute relocation. */ 85 HOWTO (R_FR30_32, /* type */ 86 0, /* rightshift */ 87 2, /* size (0 = byte, 1 = short, 2 = long) */ 88 32, /* bitsize */ 89 FALSE, /* pc_relative */ 90 0, /* bitpos */ 91 complain_overflow_bitfield, /* complain_on_overflow */ 92 bfd_elf_generic_reloc, /* special_function */ 93 "R_FR30_32", /* name */ 94 FALSE, /* partial_inplace */ 95 0x00000000, /* src_mask */ 96 0xffffffff, /* dst_mask */ 97 FALSE), /* pcrel_offset */ 98 99 /* A 32 bit into 48 bits absolute relocation. */ 100 HOWTO (R_FR30_48, /* type */ 101 0, /* rightshift */ 102 2, /* size (0 = byte, 1 = short, 2 = long) */ 103 32, /* bitsize */ 104 FALSE, /* pc_relative */ 105 0, /* bitpos */ 106 complain_overflow_bitfield, /* complain_on_overflow */ 107 fr30_elf_i32_reloc, /* special_function */ 108 "R_FR30_48", /* name */ 109 FALSE, /* partial_inplace */ 110 0x00000000, /* src_mask */ 111 0xffffffff, /* dst_mask */ 112 FALSE), /* pcrel_offset */ 113 114 /* A 6 bit absolute relocation. */ 115 HOWTO (R_FR30_6_IN_4, /* type */ 116 2, /* rightshift */ 117 1, /* size (0 = byte, 1 = short, 2 = long) */ 118 6, /* bitsize */ 119 FALSE, /* pc_relative */ 120 4, /* bitpos */ 121 complain_overflow_unsigned, /* complain_on_overflow */ 122 bfd_elf_generic_reloc, /* special_function */ 123 "R_FR30_6_IN_4", /* name */ 124 FALSE, /* partial_inplace */ 125 0x0000, /* src_mask */ 126 0x00f0, /* dst_mask */ 127 FALSE), /* pcrel_offset */ 128 129 /* An 8 bit absolute relocation. */ 130 HOWTO (R_FR30_8_IN_8, /* type */ 131 0, /* rightshift */ 132 1, /* size (0 = byte, 1 = short, 2 = long) */ 133 8, /* bitsize */ 134 FALSE, /* pc_relative */ 135 4, /* bitpos */ 136 complain_overflow_signed, /* complain_on_overflow */ 137 bfd_elf_generic_reloc,/* special_function */ 138 "R_FR30_8_IN_8", /* name */ 139 FALSE, /* partial_inplace */ 140 0x0000, /* src_mask */ 141 0x0ff0, /* dst_mask */ 142 FALSE), /* pcrel_offset */ 143 144 /* A 9 bit absolute relocation. */ 145 HOWTO (R_FR30_9_IN_8, /* type */ 146 1, /* rightshift */ 147 1, /* size (0 = byte, 1 = short, 2 = long) */ 148 9, /* bitsize */ 149 FALSE, /* pc_relative */ 150 4, /* bitpos */ 151 complain_overflow_signed, /* complain_on_overflow */ 152 bfd_elf_generic_reloc,/* special_function */ 153 "R_FR30_9_IN_8", /* name */ 154 FALSE, /* partial_inplace */ 155 0x0000, /* src_mask */ 156 0x0ff0, /* dst_mask */ 157 FALSE), /* pcrel_offset */ 158 159 /* A 10 bit absolute relocation. */ 160 HOWTO (R_FR30_10_IN_8, /* type */ 161 2, /* rightshift */ 162 1, /* size (0 = byte, 1 = short, 2 = long) */ 163 10, /* bitsize */ 164 FALSE, /* pc_relative */ 165 4, /* bitpos */ 166 complain_overflow_signed, /* complain_on_overflow */ 167 bfd_elf_generic_reloc,/* special_function */ 168 "R_FR30_10_IN_8", /* name */ 169 FALSE, /* partial_inplace */ 170 0x0000, /* src_mask */ 171 0x0ff0, /* dst_mask */ 172 FALSE), /* pcrel_offset */ 173 174 /* A PC relative 9 bit relocation, right shifted by 1. */ 175 HOWTO (R_FR30_9_PCREL, /* type */ 176 1, /* rightshift */ 177 1, /* size (0 = byte, 1 = short, 2 = long) */ 178 9, /* bitsize */ 179 TRUE, /* pc_relative */ 180 0, /* bitpos */ 181 complain_overflow_signed, /* complain_on_overflow */ 182 bfd_elf_generic_reloc, /* special_function */ 183 "R_FR30_9_PCREL", /* name */ 184 FALSE, /* partial_inplace */ 185 0x0000, /* src_mask */ 186 0x00ff, /* dst_mask */ 187 FALSE), /* pcrel_offset */ 188 189 /* A PC relative 12 bit relocation, right shifted by 1. */ 190 HOWTO (R_FR30_12_PCREL, /* type */ 191 1, /* rightshift */ 192 1, /* size (0 = byte, 1 = short, 2 = long) */ 193 12, /* bitsize */ 194 TRUE, /* pc_relative */ 195 0, /* bitpos */ 196 complain_overflow_signed, /* complain_on_overflow */ 197 bfd_elf_generic_reloc, /* special_function */ 198 "R_FR30_12_PCREL", /* name */ 199 FALSE, /* partial_inplace */ 200 0x0000, /* src_mask */ 201 0x07ff, /* dst_mask */ 202 FALSE), /* pcrel_offset */ 203 /* GNU extension to record C++ vtable hierarchy */ 204 HOWTO (R_FR30_GNU_VTINHERIT, /* type */ 205 0, /* rightshift */ 206 2, /* size (0 = byte, 1 = short, 2 = long) */ 207 0, /* bitsize */ 208 FALSE, /* pc_relative */ 209 0, /* bitpos */ 210 complain_overflow_dont, /* complain_on_overflow */ 211 NULL, /* special_function */ 212 "R_FR30_GNU_VTINHERIT", /* name */ 213 FALSE, /* partial_inplace */ 214 0, /* src_mask */ 215 0, /* dst_mask */ 216 FALSE), /* pcrel_offset */ 217 218 /* GNU extension to record C++ vtable member usage */ 219 HOWTO (R_FR30_GNU_VTENTRY, /* type */ 220 0, /* rightshift */ 221 2, /* size (0 = byte, 1 = short, 2 = long) */ 222 0, /* bitsize */ 223 FALSE, /* pc_relative */ 224 0, /* bitpos */ 225 complain_overflow_dont, /* complain_on_overflow */ 226 _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 227 "R_FR30_GNU_VTENTRY", /* name */ 228 FALSE, /* partial_inplace */ 229 0, /* src_mask */ 230 0, /* dst_mask */ 231 FALSE), /* pcrel_offset */ 232 }; 233 234 /* Utility to actually perform an R_FR30_20 reloc. */ 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 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 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 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 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 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 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" 720