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