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