1 /* ft32-specific support for 32-bit ELF. 2 Copyright (C) 2013-2022 Free Software Foundation, Inc. 3 4 Copied from elf32-moxie.c which is.. 5 Copyright (C) 2009-2022 Free Software Foundation, Inc. 6 Free Software Foundation, Inc. 7 8 This file is part of BFD, the Binary File Descriptor library. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 3 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 23 MA 02110-1301, USA. */ 24 25 #include "sysdep.h" 26 #include "bfd.h" 27 #include "libbfd.h" 28 #include "elf-bfd.h" 29 #include "elf/ft32.h" 30 #include "opcode/ft32.h" 31 32 static bool debug_relax = false; 33 34 static bfd_reloc_status_type 35 bfd_elf_ft32_diff_reloc (bfd *, arelent *, asymbol *, void *, 36 asection *, bfd *, char **); 37 38 static reloc_howto_type ft32_elf_howto_table [] = 39 { 40 /* This reloc does nothing. */ 41 HOWTO (R_FT32_NONE, /* type */ 42 0, /* rightshift */ 43 0, /* size */ 44 0, /* bitsize */ 45 false, /* pc_relative */ 46 0, /* bitpos */ 47 complain_overflow_dont, /* complain_on_overflow */ 48 bfd_elf_generic_reloc, /* special_function */ 49 "R_FT32_NONE", /* name */ 50 false, /* partial_inplace */ 51 0, /* src_mask */ 52 0, /* dst_mask */ 53 false), /* pcrel_offset */ 54 55 /* A 32 bit absolute relocation. */ 56 57 HOWTO (R_FT32_32, /* type */ 58 0, /* rightshift */ 59 4, /* size */ 60 32, /* bitsize */ 61 false, /* pc_relative */ 62 0, /* bitpos */ 63 complain_overflow_bitfield, /* complain_on_overflow */ 64 bfd_elf_generic_reloc, /* special_function */ 65 "R_FT32_32", /* name */ 66 false, /* partial_inplace */ 67 0x00000000, /* src_mask */ 68 0xffffffff, /* dst_mask */ 69 false), /* pcrel_offset */ 70 71 HOWTO (R_FT32_16, /* type */ 72 0, /* rightshift */ 73 2, /* size */ 74 16, /* bitsize */ 75 false, /* pc_relative */ 76 0, /* bitpos */ 77 complain_overflow_dont, /* complain_on_overflow */ 78 bfd_elf_generic_reloc, /* special_function */ 79 "R_FT32_16", /* name */ 80 false, /* partial_inplace */ 81 0x00000000, /* src_mask */ 82 0x0000ffff, /* dst_mask */ 83 false), /* pcrel_offset */ 84 85 HOWTO (R_FT32_8, /* type */ 86 0, /* rightshift */ 87 1, /* size */ 88 8, /* bitsize */ 89 false, /* pc_relative */ 90 0, /* bitpos */ 91 complain_overflow_signed, /* complain_on_overflow */ 92 bfd_elf_generic_reloc, /* special_function */ 93 "R_FT32_8", /* name */ 94 false, /* partial_inplace */ 95 0x00000000, /* src_mask */ 96 0x000000ff, /* dst_mask */ 97 false), /* pcrel_offset */ 98 99 HOWTO (R_FT32_10, /* type */ 100 0, /* rightshift */ 101 2, /* size */ 102 10, /* bitsize */ 103 false, /* pc_relative */ 104 4, /* bitpos */ 105 complain_overflow_bitfield, /* complain_on_overflow */ 106 bfd_elf_generic_reloc, /* special_function */ 107 "R_FT32_10", /* name */ 108 false, /* partial_inplace */ 109 0x00000000, /* src_mask */ 110 0x00003ff0, /* dst_mask */ 111 false), /* pcrel_offset */ 112 113 HOWTO (R_FT32_20, /* type */ 114 0, /* rightshift */ 115 4, /* size */ 116 20, /* bitsize */ 117 false, /* pc_relative */ 118 0, /* bitpos */ 119 complain_overflow_dont, /* complain_on_overflow */ 120 bfd_elf_generic_reloc, /* special_function */ 121 "R_FT32_20", /* name */ 122 false, /* partial_inplace */ 123 0x00000000, /* src_mask */ 124 0x000fffff, /* dst_mask */ 125 false), /* pcrel_offset */ 126 127 HOWTO (R_FT32_17, /* type */ 128 0, /* rightshift */ 129 4, /* size */ 130 17, /* bitsize */ 131 false, /* pc_relative */ 132 0, /* bitpos */ 133 complain_overflow_dont, /* complain_on_overflow */ 134 bfd_elf_generic_reloc, /* special_function */ 135 "R_FT32_17", /* name */ 136 false, /* partial_inplace */ 137 0x00000000, /* src_mask */ 138 0x0001ffff, /* dst_mask */ 139 false), /* pcrel_offset */ 140 141 HOWTO (R_FT32_18, /* type */ 142 2, /* rightshift */ 143 4, /* size */ 144 18, /* bitsize */ 145 false, /* pc_relative */ 146 0, /* bitpos */ 147 complain_overflow_dont, /* complain_on_overflow */ 148 bfd_elf_generic_reloc, /* special_function */ 149 "R_FT32_18", /* name */ 150 false, /* partial_inplace */ 151 0x00000000, /* src_mask */ 152 0x0003ffff, /* dst_mask */ 153 false), /* pcrel_offset */ 154 155 HOWTO (R_FT32_RELAX, /* type */ 156 0, /* rightshift */ 157 2, /* size */ 158 10, /* bitsize */ 159 false, /* pc_relative */ 160 4, /* bitpos */ 161 complain_overflow_signed, /* complain_on_overflow */ 162 bfd_elf_generic_reloc, /* special_function */ 163 "R_FT32_RELAX", /* name */ 164 false, /* partial_inplace */ 165 0x00000000, /* src_mask */ 166 0x00000000, /* dst_mask */ 167 false), /* pcrel_offset */ 168 169 HOWTO (R_FT32_SC0, /* type */ 170 0, /* rightshift */ 171 2, /* size */ 172 10, /* bitsize */ 173 false, /* pc_relative */ 174 4, /* bitpos */ 175 complain_overflow_signed, /* complain_on_overflow */ 176 bfd_elf_generic_reloc, /* special_function */ 177 "R_FT32_SC0", /* name */ 178 false, /* partial_inplace */ 179 0x00000000, /* src_mask */ 180 0x00000000, /* dst_mask */ 181 false), /* pcrel_offset */ 182 HOWTO (R_FT32_SC1, /* type */ 183 2, /* rightshift */ 184 4, /* size */ 185 22, /* bitsize */ 186 true, /* pc_relative */ 187 7, /* bitpos */ 188 complain_overflow_dont, /* complain_on_overflow */ 189 bfd_elf_generic_reloc, /* special_function */ 190 "R_FT32_SC1", /* name */ 191 true, /* partial_inplace */ 192 0x07ffff80, /* src_mask */ 193 0x07ffff80, /* dst_mask */ 194 false), /* pcrel_offset */ 195 HOWTO (R_FT32_15, /* type */ 196 0, /* rightshift */ 197 4, /* size */ 198 15, /* bitsize */ 199 false, /* pc_relative */ 200 0, /* bitpos */ 201 complain_overflow_dont, /* complain_on_overflow */ 202 bfd_elf_generic_reloc, /* special_function */ 203 "R_FT32_15", /* name */ 204 false, /* partial_inplace */ 205 0x00000000, /* src_mask */ 206 0x00007fff, /* dst_mask */ 207 false), /* pcrel_offset */ 208 HOWTO (R_FT32_DIFF32, /* type */ 209 0, /* rightshift */ 210 4, /* size */ 211 32, /* bitsize */ 212 false, /* pc_relative */ 213 0, /* bitpos */ 214 complain_overflow_dont, /* complain_on_overflow */ 215 bfd_elf_ft32_diff_reloc, /* special_function */ 216 "R_FT32_DIFF32", /* name */ 217 false, /* partial_inplace */ 218 0, /* src_mask */ 219 0xffffffff, /* dst_mask */ 220 false), /* pcrel_offset */ 221 }; 222 223 /* Map BFD reloc types to FT32 ELF reloc types. */ 224 225 struct ft32_reloc_map 226 { 227 bfd_reloc_code_real_type bfd_reloc_val; 228 unsigned int ft32_reloc_val; 229 }; 230 231 static const struct ft32_reloc_map ft32_reloc_map [] = 232 { 233 { BFD_RELOC_NONE, R_FT32_NONE }, 234 { BFD_RELOC_32, R_FT32_32 }, 235 { BFD_RELOC_16, R_FT32_16 }, 236 { BFD_RELOC_8, R_FT32_8 }, 237 { BFD_RELOC_FT32_10, R_FT32_10 }, 238 { BFD_RELOC_FT32_20, R_FT32_20 }, 239 { BFD_RELOC_FT32_17, R_FT32_17 }, 240 { BFD_RELOC_FT32_18, R_FT32_18 }, 241 { BFD_RELOC_FT32_RELAX, R_FT32_RELAX }, 242 { BFD_RELOC_FT32_SC0, R_FT32_SC0 }, 243 { BFD_RELOC_FT32_SC1, R_FT32_SC1 }, 244 { BFD_RELOC_FT32_15, R_FT32_15 }, 245 { BFD_RELOC_FT32_DIFF32, R_FT32_DIFF32 }, 246 }; 247 248 /* Perform a diff relocation. Nothing to do, as the difference value is 249 already written into the section's contents. */ 250 251 static bfd_reloc_status_type 252 bfd_elf_ft32_diff_reloc (bfd *abfd ATTRIBUTE_UNUSED, 253 arelent *reloc_entry ATTRIBUTE_UNUSED, 254 asymbol *symbol ATTRIBUTE_UNUSED, 255 void *data ATTRIBUTE_UNUSED, 256 asection *input_section ATTRIBUTE_UNUSED, 257 bfd *output_bfd ATTRIBUTE_UNUSED, 258 char **error_message ATTRIBUTE_UNUSED) 259 { 260 return bfd_reloc_ok; 261 } 262 263 static reloc_howto_type * 264 ft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 265 bfd_reloc_code_real_type code) 266 { 267 unsigned int i; 268 269 for (i = 0; i < sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]); i++) 270 if (ft32_reloc_map [i].bfd_reloc_val == code) 271 return & ft32_elf_howto_table [ft32_reloc_map[i].ft32_reloc_val]; 272 273 return NULL; 274 } 275 276 static reloc_howto_type * 277 ft32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 278 { 279 unsigned int i; 280 281 for (i = 0; 282 i < sizeof (ft32_elf_howto_table) / sizeof (ft32_elf_howto_table[0]); 283 i++) 284 if (ft32_elf_howto_table[i].name != NULL 285 && strcasecmp (ft32_elf_howto_table[i].name, r_name) == 0) 286 return &ft32_elf_howto_table[i]; 287 288 return NULL; 289 } 290 291 /* Set the howto pointer for an FT32 ELF reloc. */ 292 293 static bool 294 ft32_info_to_howto_rela (bfd *abfd, 295 arelent *cache_ptr, 296 Elf_Internal_Rela *dst) 297 { 298 unsigned int r_type; 299 300 r_type = ELF32_R_TYPE (dst->r_info); 301 if (r_type >= (unsigned int) R_FT32_max) 302 { 303 /* xgettext:c-format */ 304 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 305 abfd, r_type); 306 bfd_set_error (bfd_error_bad_value); 307 return false; 308 } 309 310 cache_ptr->howto = & ft32_elf_howto_table [r_type]; 311 return cache_ptr->howto != NULL; 312 } 313 314 /* Relocate an FT32 ELF section. 315 316 The RELOCATE_SECTION function is called by the new ELF backend linker 317 to handle the relocations for a section. 318 319 The relocs are always passed as Rela structures; if the section 320 actually uses Rel structures, the r_addend field will always be 321 zero. 322 323 This function is responsible for adjusting the section contents as 324 necessary, and (if using Rela relocs and generating a relocatable 325 output file) adjusting the reloc addend as necessary. 326 327 This function does not have to worry about setting the reloc 328 address or the reloc symbol index. 329 330 LOCAL_SYMS is a pointer to the swapped in local symbols. 331 332 LOCAL_SECTIONS is an array giving the section in the input file 333 corresponding to the st_shndx field of each local symbol. 334 335 The global hash table entry for the global symbols can be found 336 via elf_sym_hashes (input_bfd). 337 338 When generating relocatable output, this function must handle 339 STB_LOCAL/STT_SECTION symbols specially. The output symbol is 340 going to be the section symbol corresponding to the output 341 section, which means that the addend must be adjusted 342 accordingly. */ 343 344 static int 345 ft32_elf_relocate_section (bfd *output_bfd, 346 struct bfd_link_info *info, 347 bfd *input_bfd, 348 asection *input_section, 349 bfd_byte *contents, 350 Elf_Internal_Rela *relocs, 351 Elf_Internal_Sym *local_syms, 352 asection **local_sections) 353 { 354 Elf_Internal_Shdr *symtab_hdr; 355 struct elf_link_hash_entry **sym_hashes; 356 Elf_Internal_Rela *rel; 357 Elf_Internal_Rela *relend; 358 359 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; 360 sym_hashes = elf_sym_hashes (input_bfd); 361 relend = relocs + input_section->reloc_count; 362 363 for (rel = relocs; rel < relend; rel ++) 364 { 365 reloc_howto_type *howto; 366 unsigned long r_symndx; 367 Elf_Internal_Sym *sym; 368 asection *sec; 369 struct elf_link_hash_entry *h; 370 bfd_vma relocation; 371 bfd_reloc_status_type r; 372 const char *name; 373 int r_type; 374 375 r_type = ELF32_R_TYPE (rel->r_info); 376 r_symndx = ELF32_R_SYM (rel->r_info); 377 howto = ft32_elf_howto_table + r_type; 378 h = NULL; 379 sym = NULL; 380 sec = NULL; 381 382 if (r_symndx < symtab_hdr->sh_info) 383 { 384 sym = local_syms + r_symndx; 385 sec = local_sections [r_symndx]; 386 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 387 388 name = bfd_elf_string_from_elf_section 389 (input_bfd, symtab_hdr->sh_link, sym->st_name); 390 name = name == NULL ? bfd_section_name (sec) : name; 391 } 392 else 393 { 394 bool unresolved_reloc, warned, ignored; 395 396 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 397 r_symndx, symtab_hdr, sym_hashes, 398 h, sec, relocation, 399 unresolved_reloc, warned, ignored); 400 401 name = h->root.root.string; 402 } 403 404 if (sec != NULL && discarded_section (sec)) 405 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, 406 rel, 1, relend, howto, 0, contents); 407 408 if (bfd_link_relocatable (info)) 409 continue; 410 411 switch (howto->type) 412 { 413 case R_FT32_SC0: 414 { 415 unsigned int insn; 416 int offset; 417 unsigned int code15[2]; 418 419 insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 420 ft32_split_shortcode (insn, code15); 421 422 offset = (int)relocation; 423 offset += (int)(rel->r_addend - rel->r_offset); 424 offset -= (input_section->output_section->vma + 425 input_section->output_offset); 426 if ((offset < -1024) || (offset >= 1024)) 427 { 428 r = bfd_reloc_outofrange; 429 break; 430 } 431 code15[0] |= ((offset / 4) & 511); 432 insn = ft32_merge_shortcode (code15); 433 bfd_put_32 (input_bfd, insn, contents + rel->r_offset); 434 } 435 r = bfd_reloc_ok; 436 break; 437 438 case R_FT32_SC1: 439 { 440 unsigned int insn; 441 int offset; 442 unsigned int code15[2]; 443 444 insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 445 ft32_split_shortcode (insn, code15); 446 447 offset = (int)relocation; 448 offset += (int)(rel->r_addend - rel->r_offset); 449 offset -= (input_section->output_section->vma + 450 input_section->output_offset); 451 if ((offset < -1024) || (offset >= 1024)) 452 { 453 r = bfd_reloc_outofrange; 454 break; 455 } 456 code15[1] |= ((offset / 4) & 511); 457 insn = ft32_merge_shortcode (code15); 458 bfd_put_32 (input_bfd, insn, contents + rel->r_offset); 459 } 460 r = bfd_reloc_ok; 461 break; 462 463 case R_FT32_DIFF32: 464 r = bfd_reloc_ok; 465 break; 466 467 default: 468 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 469 contents, rel->r_offset, 470 relocation, rel->r_addend); 471 break; 472 } 473 474 if (r != bfd_reloc_ok) 475 { 476 const char * msg = NULL; 477 478 switch (r) 479 { 480 case bfd_reloc_overflow: 481 (*info->callbacks->reloc_overflow) 482 (info, (h ? &h->root : NULL), name, howto->name, 483 (bfd_vma) 0, input_bfd, input_section, rel->r_offset); 484 break; 485 486 case bfd_reloc_undefined: 487 (*info->callbacks->undefined_symbol) 488 (info, name, input_bfd, input_section, rel->r_offset, true); 489 break; 490 491 case bfd_reloc_outofrange: 492 msg = _("internal error: out of range error"); 493 break; 494 495 case bfd_reloc_notsupported: 496 msg = _("internal error: unsupported relocation error"); 497 break; 498 499 case bfd_reloc_dangerous: 500 msg = _("internal error: dangerous relocation"); 501 break; 502 503 default: 504 msg = _("internal error: unknown error"); 505 break; 506 } 507 508 if (msg) 509 (*info->callbacks->warning) (info, msg, name, input_bfd, 510 input_section, rel->r_offset); 511 } 512 } 513 514 return true; 515 } 516 517 /* Relaxation. */ 518 519 static bool 520 ft32_reloc_shortable 521 (bfd * abfd, 522 asection * sec, 523 Elf_Internal_Sym * isymbuf ATTRIBUTE_UNUSED, 524 bfd_byte * contents, 525 bfd_vma pc ATTRIBUTE_UNUSED, 526 Elf_Internal_Rela * irel, 527 unsigned int * sc) 528 { 529 Elf_Internal_Shdr *symtab_hdr ATTRIBUTE_UNUSED; 530 bfd_vma symval; 531 532 enum elf_ft32_reloc_type r_type; 533 reloc_howto_type *howto = NULL; 534 unsigned int insn; 535 int offset; 536 bfd_vma dot, value; 537 538 r_type = ELF32_R_TYPE (irel->r_info); 539 howto = &ft32_elf_howto_table [r_type]; 540 541 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 542 543 /* Get the value of the symbol referred to by the reloc. */ 544 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 545 { 546 /* A local symbol. */ 547 Elf_Internal_Sym *isym; 548 asection *sym_sec; 549 550 isym = isymbuf + ELF32_R_SYM (irel->r_info); 551 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 552 symval = isym->st_value; 553 /* If the reloc is absolute, it will not have 554 a symbol or section associated with it. */ 555 if (sym_sec) 556 symval += sym_sec->output_section->vma 557 + sym_sec->output_offset; 558 } 559 else 560 { 561 unsigned long indx; 562 struct elf_link_hash_entry *h; 563 564 /* An external symbol. */ 565 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; 566 h = elf_sym_hashes (abfd)[indx]; 567 BFD_ASSERT (h != NULL); 568 if (h->root.type != bfd_link_hash_defined 569 && h->root.type != bfd_link_hash_defweak) 570 /* This appears to be a reference to an undefined 571 symbol. Just ignore it--it will be caught by the 572 regular reloc processing. */ 573 return false; 574 575 symval = (h->root.u.def.value 576 + h->root.u.def.section->output_section->vma 577 + h->root.u.def.section->output_offset); 578 } 579 580 switch (r_type) 581 { 582 case R_FT32_8: 583 case R_FT32_10: 584 case R_FT32_16: 585 case R_FT32_20: 586 case R_FT32_RELAX: 587 if (symval != 0) 588 return false; 589 insn = bfd_get_32 (abfd, contents + irel->r_offset); 590 insn |= ((symval + irel->r_addend) << howto->bitpos) & howto->dst_mask; 591 return ft32_shortcode (insn, sc); 592 593 case R_FT32_18: 594 insn = bfd_get_32 (abfd, contents + irel->r_offset); 595 /* Get the address of this instruction. */ 596 dot = (sec->output_section->vma 597 + sec->output_offset + irel->r_offset); 598 value = symval + irel->r_addend; 599 offset = (value - dot) / 4; 600 601 if ((dot > 0x8c) && (-256 <= offset) && (offset < 256)) 602 { 603 switch (insn) 604 { 605 case 0x00200000: *sc = (3 << 13) | (0 << 9); return true; 606 case 0x00280000: *sc = (3 << 13) | (1 << 9); return true; 607 case 0x00600000: *sc = (3 << 13) | (2 << 9); return true; 608 case 0x00680000: *sc = (3 << 13) | (3 << 9); return true; 609 case 0x00a00000: *sc = (3 << 13) | (4 << 9); return true; 610 case 0x00a80000: *sc = (3 << 13) | (5 << 9); return true; 611 case 0x00e00000: *sc = (3 << 13) | (6 << 9); return true; 612 case 0x00e80000: *sc = (3 << 13) | (7 << 9); return true; 613 case 0x01200000: *sc = (3 << 13) | (8 << 9); return true; 614 case 0x01280000: *sc = (3 << 13) | (9 << 9); return true; 615 case 0x01600000: *sc = (3 << 13) | (10 << 9); return true; 616 case 0x01680000: *sc = (3 << 13) | (11 << 9); return true; 617 case 0x01a00000: *sc = (3 << 13) | (12 << 9); return true; 618 case 0x01a80000: *sc = (3 << 13) | (13 << 9); return true; 619 620 case 0x00300000: *sc = (3 << 13) | (14 << 9); return true; 621 case 0x00340000: *sc = (3 << 13) | (15 << 9); return true; 622 623 default: 624 break; 625 } 626 } 627 break; 628 629 default: 630 break; 631 } 632 return false; 633 } 634 635 /* Returns whether the relocation type passed is a diff reloc. */ 636 637 static bool 638 elf32_ft32_is_diff_reloc (Elf_Internal_Rela *irel) 639 { 640 return (ELF32_R_TYPE (irel->r_info) == R_FT32_DIFF32); 641 } 642 643 /* Reduce the diff value written in the section by count if the shrinked 644 insn address happens to fall between the two symbols for which this 645 diff reloc was emitted. */ 646 647 static bool 648 elf32_ft32_adjust_diff_reloc_value (bfd *abfd, 649 struct bfd_section *isec, 650 Elf_Internal_Rela *irel, 651 bfd_vma symval, 652 bfd_vma shrinked_insn_address, 653 int count) 654 { 655 unsigned char * reloc_contents = NULL; 656 unsigned char * isec_contents = elf_section_data (isec)->this_hdr.contents; 657 bfd_signed_vma x = 0; 658 bfd_vma sym2_address; 659 bfd_vma sym1_address; 660 bfd_vma start_address; 661 bfd_vma end_address; 662 663 664 if (isec_contents == NULL) 665 { 666 if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents)) 667 return false; 668 669 elf_section_data (isec)->this_hdr.contents = isec_contents; 670 } 671 672 reloc_contents = isec_contents + irel->r_offset; 673 674 /* Read value written in object file. */ 675 switch (ELF32_R_TYPE (irel->r_info)) 676 { 677 case R_FT32_DIFF32: 678 x = bfd_get_signed_32 (abfd, reloc_contents); 679 break; 680 681 default: 682 return false; 683 } 684 685 /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written 686 into the object file at the reloc offset. sym2's logical value is 687 symval (<start_of_section>) + reloc addend. Compute the start and end 688 addresses and check if the shrinked insn falls between sym1 and sym2. */ 689 sym2_address = symval + irel->r_addend; 690 sym1_address = sym2_address - x; 691 692 /* Don't assume sym2 is bigger than sym1 - the difference 693 could be negative. Compute start and end addresses, and 694 use those to see if they span shrinked_insn_address. */ 695 start_address = sym1_address < sym2_address ? sym1_address : sym2_address; 696 end_address = sym1_address > sym2_address ? sym1_address : sym2_address; 697 698 if (shrinked_insn_address >= start_address 699 && shrinked_insn_address < end_address) 700 { 701 /* Reduce the diff value by count bytes and write it back into section 702 contents. */ 703 bfd_signed_vma new_diff = x < 0 ? x + count : x - count; 704 705 if (sym2_address > shrinked_insn_address) 706 irel->r_addend -= count; 707 708 switch (ELF32_R_TYPE (irel->r_info)) 709 { 710 case R_FT32_DIFF32: 711 bfd_put_signed_32 (abfd, new_diff & 0xFFFFFFFF, reloc_contents); 712 break; 713 714 default: 715 return false; 716 } 717 } 718 719 return true; 720 } 721 722 static bool 723 elf32_ft32_adjust_reloc_if_spans_insn (bfd *abfd, 724 asection *isec, 725 Elf_Internal_Rela *irel, bfd_vma symval, 726 bfd_vma shrinked_insn_address, 727 bfd_vma shrink_boundary, 728 int count) 729 { 730 731 if (elf32_ft32_is_diff_reloc (irel)) 732 { 733 if (!elf32_ft32_adjust_diff_reloc_value (abfd, isec, irel, 734 symval, 735 shrinked_insn_address, 736 count)) 737 return false; 738 } 739 else 740 { 741 bfd_vma reloc_value = symval + irel->r_addend; 742 bool addend_within_shrink_boundary = 743 (reloc_value <= shrink_boundary); 744 bool reloc_spans_insn = 745 (symval <= shrinked_insn_address 746 && reloc_value > shrinked_insn_address 747 && addend_within_shrink_boundary); 748 749 if (! reloc_spans_insn) 750 return true; 751 752 irel->r_addend -= count; 753 754 if (debug_relax) 755 printf ("Relocation's addend needed to be fixed \n"); 756 } 757 return true; 758 } 759 760 /* Delete some bytes from a section while relaxing. */ 761 762 static bool 763 elf32_ft32_relax_delete_bytes (struct bfd_link_info *link_info, bfd * abfd, 764 asection * sec, bfd_vma addr, int count) 765 { 766 Elf_Internal_Shdr *symtab_hdr; 767 unsigned int sec_shndx; 768 bfd_byte *contents; 769 Elf_Internal_Rela *irel, *irelend; 770 bfd_vma toaddr; 771 Elf_Internal_Sym *isym; 772 Elf_Internal_Sym *isymend; 773 struct elf_link_hash_entry **sym_hashes; 774 struct elf_link_hash_entry **end_hashes; 775 struct elf_link_hash_entry **start_hashes; 776 unsigned int symcount; 777 Elf_Internal_Sym *isymbuf = NULL; 778 779 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 780 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); 781 782 contents = elf_section_data (sec)->this_hdr.contents; 783 784 toaddr = sec->size; 785 786 irel = elf_section_data (sec)->relocs; 787 irelend = irel + sec->reloc_count; 788 789 /* Actually delete the bytes. */ 790 memmove (contents + addr, contents + addr + count, 791 (size_t) (toaddr - addr - count)); 792 sec->size -= count; 793 794 /* Adjust all the relocs. */ 795 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) 796 /* Get the new reloc address. */ 797 if ((irel->r_offset > addr && irel->r_offset < toaddr)) 798 irel->r_offset -= count; 799 800 /* The reloc's own addresses are now ok. However, we need to readjust 801 the reloc's addend, i.e. the reloc's value if two conditions are met: 802 1.) the reloc is relative to a symbol in this section that 803 is located in front of the shrinked instruction 804 2.) symbol plus addend end up behind the shrinked instruction. 805 806 The most common case where this happens are relocs relative to 807 the section-start symbol. 808 809 This step needs to be done for all of the sections of the bfd. */ 810 { 811 struct bfd_section *isec; 812 813 for (isec = abfd->sections; isec; isec = isec->next) 814 { 815 bfd_vma symval; 816 bfd_vma shrinked_insn_address; 817 818 if (isec->reloc_count == 0) 819 continue; 820 821 shrinked_insn_address = (sec->output_section->vma 822 + sec->output_offset + addr - count); 823 824 irel = elf_section_data (isec)->relocs; 825 /* PR 12161: Read in the relocs for this section if necessary. */ 826 if (irel == NULL) 827 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, true); 828 829 for (irelend = irel + isec->reloc_count; irel < irelend; irel++) 830 { 831 /* Read this BFD's local symbols if we haven't done 832 so already. */ 833 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 834 { 835 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 836 if (isymbuf == NULL) 837 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 838 symtab_hdr->sh_info, 0, 839 NULL, NULL, NULL); 840 if (isymbuf == NULL) 841 return false; 842 } 843 844 /* Get the value of the symbol referred to by the reloc. */ 845 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 846 { 847 /* A local symbol. */ 848 asection *sym_sec; 849 850 isym = isymbuf + ELF32_R_SYM (irel->r_info); 851 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 852 symval = isym->st_value; 853 /* If the reloc is absolute, it will not have 854 a symbol or section associated with it. */ 855 if (sym_sec == sec) 856 { 857 symval += sym_sec->output_section->vma 858 + sym_sec->output_offset; 859 860 if (debug_relax) 861 printf ("Checking if the relocation's " 862 "addend needs corrections.\n" 863 "Address of anchor symbol: 0x%x \n" 864 "Address of relocation target: 0x%x \n" 865 "Address of relaxed insn: 0x%x \n", 866 (unsigned int) symval, 867 (unsigned int) (symval + irel->r_addend), 868 (unsigned int) shrinked_insn_address); 869 870 if (symval <= shrinked_insn_address 871 && (symval + irel->r_addend) > shrinked_insn_address) 872 { 873 /* If there is an alignment boundary, we only need to 874 adjust addends that end up below the boundary. */ 875 bfd_vma shrink_boundary = (toaddr 876 + sec->output_section->vma 877 + sec->output_offset); 878 879 if (debug_relax) 880 printf 881 ("Relocation's addend needed to be fixed \n"); 882 883 if (!elf32_ft32_adjust_reloc_if_spans_insn (abfd, isec, 884 irel, symval, 885 shrinked_insn_address, 886 shrink_boundary, 887 count)) 888 return false; 889 } 890 } 891 /* else reference symbol is absolute. No adjustment needed. */ 892 } 893 /* else...Reference symbol is extern. No need for adjusting 894 the addend. */ 895 } 896 } 897 } 898 899 /* Adjust the local symbols defined in this section. */ 900 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 901 isym = (Elf_Internal_Sym *) symtab_hdr->contents; 902 if (isym) 903 { 904 for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) 905 { 906 if (isym->st_shndx == sec_shndx 907 && isym->st_value > addr && isym->st_value < toaddr) 908 isym->st_value -= count; 909 } 910 } 911 912 /* Now adjust the global symbols defined in this section. */ 913 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) 914 - symtab_hdr->sh_info); 915 sym_hashes = start_hashes = elf_sym_hashes (abfd); 916 end_hashes = sym_hashes + symcount; 917 918 for (; sym_hashes < end_hashes; sym_hashes++) 919 { 920 struct elf_link_hash_entry *sym_hash = *sym_hashes; 921 922 /* The '--wrap SYMBOL' option is causing a pain when the object file, 923 containing the definition of __wrap_SYMBOL, includes a direct 924 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference 925 the same symbol (which is __wrap_SYMBOL), but still exist as two 926 different symbols in 'sym_hashes', we don't want to adjust 927 the global symbol __wrap_SYMBOL twice. 928 This check is only relevant when symbols are being wrapped. */ 929 if (link_info->wrap_hash != NULL) 930 { 931 struct elf_link_hash_entry **cur_sym_hashes; 932 933 /* Loop only over the symbols whom been already checked. */ 934 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes; 935 cur_sym_hashes++) 936 /* If the current symbol is identical to 'sym_hash', that means 937 the symbol was already adjusted (or at least checked). */ 938 if (*cur_sym_hashes == sym_hash) 939 break; 940 941 /* Don't adjust the symbol again. */ 942 if (cur_sym_hashes < sym_hashes) 943 continue; 944 } 945 946 if ((sym_hash->root.type == bfd_link_hash_defined 947 || sym_hash->root.type == bfd_link_hash_defweak) 948 && sym_hash->root.u.def.section == sec 949 && sym_hash->root.u.def.value > addr 950 && sym_hash->root.u.def.value < toaddr) 951 sym_hash->root.u.def.value -= count; 952 } 953 954 return true; 955 } 956 957 /* Return TRUE if LOC can be a target of a branch, jump or call. */ 958 959 static bool 960 elf32_ft32_relax_is_branch_target (struct bfd_link_info *link_info, 961 bfd * abfd, asection * sec, 962 bfd_vma loc) 963 { 964 Elf_Internal_Shdr *symtab_hdr; 965 Elf_Internal_Rela *irel, *irelend; 966 Elf_Internal_Sym *isym; 967 Elf_Internal_Sym *isymbuf = NULL; 968 bfd_vma symval; 969 struct bfd_section *isec; 970 971 struct elf_link_hash_entry **sym_hashes; 972 struct elf_link_hash_entry **end_hashes; 973 struct elf_link_hash_entry **start_hashes; 974 unsigned int symcount; 975 976 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 977 978 /* Now we check for relocations pointing to ret. */ 979 for (isec = abfd->sections; isec; isec = isec->next) 980 { 981 irel = elf_section_data (isec)->relocs; 982 if (irel == NULL) 983 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, true); 984 985 irelend = irel + isec->reloc_count; 986 987 for (; irel < irelend; irel++) 988 { 989 /* Read this BFD's local symbols if we haven't done 990 so already. */ 991 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 992 { 993 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 994 if (isymbuf == NULL) 995 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 996 symtab_hdr->sh_info, 0, 997 NULL, NULL, NULL); 998 if (isymbuf == NULL) 999 return false; 1000 } 1001 1002 /* Get the value of the symbol referred to by the reloc. */ 1003 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 1004 { 1005 /* A local symbol. */ 1006 asection *sym_sec; 1007 1008 isym = isymbuf + ELF32_R_SYM (irel->r_info); 1009 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 1010 symval = isym->st_value; 1011 /* If the reloc is absolute, it will not have 1012 a symbol or section associated with it. */ 1013 if (sym_sec == sec) 1014 { 1015 symval += sym_sec->output_section->vma 1016 + sym_sec->output_offset; 1017 1018 if (debug_relax) 1019 printf ("0x%x: Address of anchor symbol: 0x%x " 1020 "Address of relocation target: 0x%x \n", 1021 (unsigned int) irel->r_offset, 1022 (unsigned int) symval, 1023 (unsigned int) (symval + irel->r_addend)); 1024 if ((irel->r_addend) == loc) 1025 return true; 1026 } 1027 } 1028 } 1029 } 1030 1031 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) 1032 - symtab_hdr->sh_info); 1033 sym_hashes = start_hashes = elf_sym_hashes (abfd); 1034 end_hashes = sym_hashes + symcount; 1035 1036 for (; sym_hashes < end_hashes; sym_hashes++) 1037 { 1038 struct elf_link_hash_entry *sym_hash = *sym_hashes; 1039 1040 /* The '--wrap SYMBOL' option is causing a pain when the object file, 1041 containing the definition of __wrap_SYMBOL, includes a direct 1042 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference 1043 the same symbol (which is __wrap_SYMBOL), but still exist as two 1044 different symbols in 'sym_hashes', we don't want to adjust 1045 the global symbol __wrap_SYMBOL twice. 1046 This check is only relevant when symbols are being wrapped. */ 1047 if (link_info->wrap_hash != NULL) 1048 { 1049 struct elf_link_hash_entry **cur_sym_hashes; 1050 1051 /* Loop only over the symbols whom been already checked. */ 1052 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes; 1053 cur_sym_hashes++) 1054 /* If the current symbol is identical to 'sym_hash', that means 1055 the symbol was already adjusted (or at least checked). */ 1056 if (*cur_sym_hashes == sym_hash) 1057 break; 1058 1059 /* Don't adjust the symbol again. */ 1060 if (cur_sym_hashes < sym_hashes) 1061 continue; 1062 } 1063 1064 if ((sym_hash->root.type == bfd_link_hash_defined 1065 || sym_hash->root.type == bfd_link_hash_defweak) 1066 && sym_hash->root.u.def.section == sec 1067 && sym_hash->root.u.def.value == loc) 1068 return true; 1069 } 1070 1071 return false; 1072 } 1073 1074 static bool 1075 ft32_elf_relax_section (bfd *abfd, 1076 asection *sec, 1077 struct bfd_link_info *link_info, 1078 bool *again) 1079 { 1080 Elf_Internal_Rela * free_relocs = NULL; 1081 Elf_Internal_Rela * internal_relocs; 1082 Elf_Internal_Rela * irelend; 1083 Elf_Internal_Rela * irel; 1084 bfd_byte * contents = NULL; 1085 Elf_Internal_Shdr * symtab_hdr; 1086 Elf_Internal_Sym * isymbuf = NULL; 1087 1088 /* Assume nothing changes. */ 1089 *again = false; 1090 1091 /* We don't have to do anything for a relocatable link, if 1092 this section does not have relocs, or if this is not a 1093 code section. */ 1094 if (bfd_link_relocatable (link_info) 1095 || (sec->flags & SEC_RELOC) == 0 1096 || sec->reloc_count == 0 1097 || (sec->flags & SEC_CODE) == 0) 1098 return true; 1099 1100 /* Get the section contents. */ 1101 if (elf_section_data (sec)->this_hdr.contents != NULL) 1102 contents = elf_section_data (sec)->this_hdr.contents; 1103 /* Go get them off disk. */ 1104 else 1105 { 1106 if (! bfd_malloc_and_get_section (abfd, sec, &contents)) 1107 goto error_return; 1108 elf_section_data (sec)->this_hdr.contents = contents; 1109 } 1110 1111 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 1112 1113 /* Read this BFD's local symbols if we haven't done so already. */ 1114 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 1115 { 1116 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 1117 if (isymbuf == NULL) 1118 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 1119 symtab_hdr->sh_info, 0, 1120 NULL, NULL, NULL); 1121 if (isymbuf == NULL) 1122 goto error_return; 1123 symtab_hdr->contents = (unsigned char *) isymbuf; 1124 } 1125 1126 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, 1127 link_info->keep_memory); 1128 if (internal_relocs == NULL) 1129 goto error_return; 1130 if (! link_info->keep_memory) 1131 free_relocs = internal_relocs; 1132 1133 /* Walk through them looking for relaxing opportunities. */ 1134 irelend = internal_relocs + sec->reloc_count; 1135 1136 /* Test every adjacent pair of relocs. If both have shortcodes, 1137 fuse them and delete the relocs. */ 1138 irel = internal_relocs; 1139 while (irel < irelend - 1) 1140 { 1141 Elf_Internal_Rela * irel_next = irel + 1; 1142 unsigned int sc0, sc1; 1143 bfd_vma pc; 1144 1145 pc = irel->r_offset; 1146 1147 if (((pc + 4) == (irel_next->r_offset)) 1148 && ft32_reloc_shortable (abfd, sec, isymbuf, contents, pc, irel, 1149 &sc0) 1150 && ft32_reloc_shortable (abfd, sec, isymbuf, contents, pc, 1151 irel_next, &sc1) 1152 && !elf32_ft32_relax_is_branch_target (link_info, abfd, sec, 1153 irel_next->r_offset)) 1154 { 1155 unsigned int code30 = (sc1 << 15) | sc0; 1156 unsigned int code27 = code30 >> 3; 1157 unsigned int code3 = code30 & 7; 1158 static const unsigned char pat3[] = {2, 3, 4, 5, 6, 9, 10, 14}; 1159 unsigned int pattern = pat3[code3]; 1160 unsigned int fused = (pattern << 27) | code27; 1161 1162 /* Move second reloc to same place as first. */ 1163 irel_next->r_offset = irel->r_offset; 1164 1165 /* Change both relocs to R_FT32_NONE. */ 1166 1167 if (ELF32_R_TYPE (irel->r_info) == R_FT32_18) 1168 { 1169 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1170 R_FT32_SC0); 1171 } 1172 else 1173 { 1174 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1175 R_FT32_NONE); 1176 } 1177 1178 if (ELF32_R_TYPE (irel_next->r_info) == R_FT32_18) 1179 { 1180 irel_next->r_info = ELF32_R_INFO (ELF32_R_SYM (irel_next->r_info), 1181 R_FT32_SC1); 1182 } 1183 else 1184 { 1185 irel_next->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1186 R_FT32_NONE); 1187 } 1188 1189 /* Replace the first insn with the fused version. */ 1190 bfd_put_32 (abfd, fused, contents + irel->r_offset); 1191 1192 /* Delete the second insn. */ 1193 if (!elf32_ft32_relax_delete_bytes (link_info, abfd, sec, 1194 irel->r_offset + 4, 4)) 1195 goto error_return; 1196 1197 /* That will change things, so, we should relax again. 1198 Note that this is not required, and it may be slow. */ 1199 *again = true; 1200 1201 irel += 2; 1202 } 1203 else 1204 { 1205 irel += 1; 1206 } 1207 } 1208 1209 if (isymbuf != NULL 1210 && symtab_hdr->contents != (unsigned char *) isymbuf) 1211 { 1212 if (! link_info->keep_memory) 1213 free (isymbuf); 1214 else 1215 /* Cache the symbols for elf_link_input_bfd. */ 1216 symtab_hdr->contents = (unsigned char *) isymbuf; 1217 } 1218 1219 if (contents != NULL 1220 && elf_section_data (sec)->this_hdr.contents != contents) 1221 { 1222 if (! link_info->keep_memory) 1223 free (contents); 1224 else 1225 /* Cache the section contents for elf_link_input_bfd. */ 1226 elf_section_data (sec)->this_hdr.contents = contents; 1227 1228 } 1229 1230 if (elf_section_data (sec)->relocs != internal_relocs) 1231 free (internal_relocs); 1232 1233 return true; 1234 1235 error_return: 1236 free (free_relocs); 1237 1238 return true; 1239 } 1240 1241 #define ELF_ARCH bfd_arch_ft32 1242 #define ELF_MACHINE_CODE EM_FT32 1243 #define ELF_MAXPAGESIZE 0x1 1244 1245 #define TARGET_LITTLE_SYM ft32_elf32_vec 1246 #define TARGET_LITTLE_NAME "elf32-ft32" 1247 1248 #define elf_info_to_howto_rel NULL 1249 #define elf_info_to_howto ft32_info_to_howto_rela 1250 #define elf_backend_relocate_section ft32_elf_relocate_section 1251 1252 #define elf_backend_can_gc_sections 1 1253 #define elf_backend_rela_normal 1 1254 1255 #define bfd_elf32_bfd_reloc_type_lookup ft32_reloc_type_lookup 1256 #define bfd_elf32_bfd_reloc_name_lookup ft32_reloc_name_lookup 1257 1258 #define bfd_elf32_bfd_relax_section ft32_elf_relax_section 1259 1260 #include "elf32-target.h" 1261