1228753Smm/* ft32-specific support for 32-bit ELF. 2228753Smm Copyright (C) 2013-2020 Free Software Foundation, Inc. 3228753Smm 4228753Smm Copied from elf32-moxie.c which is.. 5228753Smm Copyright (C) 2009-2020 Free Software Foundation, Inc. 6228753Smm Free Software Foundation, Inc. 7228753Smm 8228753Smm This file is part of BFD, the Binary File Descriptor library. 9228753Smm 10228753Smm This program is free software; you can redistribute it and/or modify 11228753Smm it under the terms of the GNU General Public License as published by 12228753Smm the Free Software Foundation; either version 3 of the License, or 13228753Smm (at your option) any later version. 14228753Smm 15228753Smm This program is distributed in the hope that it will be useful, 16228753Smm but WITHOUT ANY WARRANTY; without even the implied warranty of 17228753Smm MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18228753Smm GNU General Public License for more details. 19228753Smm 20228753Smm You should have received a copy of the GNU General Public License 21228753Smm along with this program; if not, write to the Free Software 22228753Smm Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 23228753Smm MA 02110-1301, USA. */ 24228753Smm 25228753Smm#include "sysdep.h" 26228753Smm#include "bfd.h" 27228763Smm#include "libbfd.h" 28228753Smm#include "elf-bfd.h" 29228753Smm#include "elf/ft32.h" 30228753Smm#include "opcode/ft32.h" 31228753Smm 32228753Smmstatic bfd_boolean debug_relax = FALSE; 33228753Smm 34228753Smmstatic bfd_reloc_status_type 35228753Smmbfd_elf_ft32_diff_reloc (bfd *, arelent *, asymbol *, void *, 36228753Smm asection *, bfd *, char **); 37228753Smm 38228753Smmstatic reloc_howto_type ft32_elf_howto_table [] = 39228753Smm{ 40228753Smm /* This reloc does nothing. */ 41228753Smm HOWTO (R_FT32_NONE, /* type */ 42228753Smm 0, /* rightshift */ 43228753Smm 2, /* size (0 = byte, 1 = short, 2 = long) */ 44228753Smm 32, /* bitsize */ 45228753Smm FALSE, /* pc_relative */ 46228753Smm 0, /* bitpos */ 47228753Smm complain_overflow_bitfield, /* complain_on_overflow */ 48228753Smm bfd_elf_generic_reloc, /* special_function */ 49228753Smm "R_FT32_NONE", /* name */ 50228753Smm FALSE, /* partial_inplace */ 51228753Smm 0, /* src_mask */ 52228753Smm 0, /* dst_mask */ 53228753Smm FALSE), /* pcrel_offset */ 54228753Smm 55228753Smm /* A 32 bit absolute relocation. */ 56228753Smm 57228753Smm HOWTO (R_FT32_32, /* type */ 58228753Smm 0, /* rightshift */ 59228753Smm 2, /* size (0 = byte, 1 = short, 2 = long) */ 60228753Smm 32, /* bitsize */ 61228753Smm FALSE, /* pc_relative */ 62228753Smm 0, /* bitpos */ 63228753Smm complain_overflow_bitfield, /* complain_on_overflow */ 64228753Smm bfd_elf_generic_reloc, /* special_function */ 65228753Smm "R_FT32_32", /* name */ 66228753Smm FALSE, /* partial_inplace */ 67228753Smm 0x00000000, /* src_mask */ 68228753Smm 0xffffffff, /* dst_mask */ 69228753Smm FALSE), /* pcrel_offset */ 70228753Smm 71228753Smm HOWTO (R_FT32_16, /* type */ 72228753Smm 0, /* rightshift */ 73228753Smm 1, /* size (0 = byte, 1 = short, 2 = long) */ 74228753Smm 16, /* bitsize */ 75228753Smm FALSE, /* pc_relative */ 76228753Smm 0, /* bitpos */ 77228753Smm complain_overflow_dont, /* complain_on_overflow */ 78228753Smm bfd_elf_generic_reloc, /* special_function */ 79228753Smm "R_FT32_16", /* name */ 80228753Smm FALSE, /* partial_inplace */ 81228753Smm 0x00000000, /* src_mask */ 82228753Smm 0x0000ffff, /* dst_mask */ 83228753Smm FALSE), /* pcrel_offset */ 84228753Smm 85228753Smm HOWTO (R_FT32_8, /* type */ 86228753Smm 0, /* rightshift */ 87228753Smm 0, /* size (0 = byte, 1 = short, 2 = long) */ 88228753Smm 8, /* bitsize */ 89228753Smm FALSE, /* pc_relative */ 90228753Smm 0, /* bitpos */ 91228753Smm complain_overflow_signed, /* complain_on_overflow */ 92228753Smm bfd_elf_generic_reloc, /* special_function */ 93228753Smm "R_FT32_8", /* name */ 94228753Smm FALSE, /* partial_inplace */ 95228753Smm 0x00000000, /* src_mask */ 96228753Smm 0x000000ff, /* dst_mask */ 97228753Smm FALSE), /* pcrel_offset */ 98228753Smm 99228753Smm HOWTO (R_FT32_10, /* type */ 100228753Smm 0, /* rightshift */ 101228753Smm 1, /* size (0 = byte, 1 = short, 2 = long) */ 102228753Smm 10, /* bitsize */ 103228753Smm FALSE, /* pc_relative */ 104228753Smm 4, /* bitpos */ 105228753Smm complain_overflow_bitfield, /* complain_on_overflow */ 106228753Smm bfd_elf_generic_reloc, /* special_function */ 107228753Smm "R_FT32_10", /* name */ 108228753Smm FALSE, /* partial_inplace */ 109228753Smm 0x00000000, /* src_mask */ 110228753Smm 0x00003ff0, /* dst_mask */ 111228753Smm FALSE), /* pcrel_offset */ 112228753Smm 113228753Smm HOWTO (R_FT32_20, /* type */ 114228753Smm 0, /* rightshift */ 115228753Smm 2, /* size (0 = byte, 1 = short, 2 = long) */ 116228753Smm 20, /* bitsize */ 117228753Smm FALSE, /* pc_relative */ 118228753Smm 0, /* bitpos */ 119228753Smm complain_overflow_dont, /* complain_on_overflow */ 120228753Smm bfd_elf_generic_reloc, /* special_function */ 121228753Smm "R_FT32_20", /* name */ 122228753Smm FALSE, /* partial_inplace */ 123228753Smm 0x00000000, /* src_mask */ 124228753Smm 0x000fffff, /* dst_mask */ 125228753Smm FALSE), /* pcrel_offset */ 126228753Smm 127228753Smm HOWTO (R_FT32_17, /* type */ 128228753Smm 0, /* rightshift */ 129228753Smm 2, /* size (0 = byte, 1 = short, 2 = long) */ 130228753Smm 17, /* bitsize */ 131228753Smm FALSE, /* pc_relative */ 132228753Smm 0, /* bitpos */ 133228753Smm complain_overflow_dont, /* complain_on_overflow */ 134228753Smm bfd_elf_generic_reloc, /* special_function */ 135228753Smm "R_FT32_17", /* name */ 136228753Smm FALSE, /* partial_inplace */ 137228753Smm 0x00000000, /* src_mask */ 138228753Smm 0x0001ffff, /* dst_mask */ 139228753Smm FALSE), /* pcrel_offset */ 140228753Smm 141228753Smm HOWTO (R_FT32_18, /* type */ 142228753Smm 2, /* rightshift */ 143228753Smm 2, /* size (0 = byte, 1 = short, 2 = long) */ 144228753Smm 18, /* bitsize */ 145228753Smm FALSE, /* pc_relative */ 146228753Smm 0, /* bitpos */ 147228753Smm complain_overflow_dont, /* complain_on_overflow */ 148228753Smm bfd_elf_generic_reloc, /* special_function */ 149228753Smm "R_FT32_18", /* name */ 150228753Smm FALSE, /* partial_inplace */ 151228753Smm 0x00000000, /* src_mask */ 152228753Smm 0x0003ffff, /* dst_mask */ 153228753Smm FALSE), /* pcrel_offset */ 154228753Smm 155228753Smm HOWTO (R_FT32_RELAX, /* type */ 156228753Smm 0, /* rightshift */ 157228753Smm 1, /* size (0 = byte, 1 = short, 2 = long) */ 158228753Smm 10, /* bitsize */ 159228753Smm FALSE, /* pc_relative */ 160228753Smm 4, /* bitpos */ 161228753Smm complain_overflow_signed, /* complain_on_overflow */ 162228753Smm bfd_elf_generic_reloc, /* special_function */ 163228753Smm "R_FT32_RELAX", /* name */ 164228753Smm FALSE, /* partial_inplace */ 165228753Smm 0x00000000, /* src_mask */ 166228753Smm 0x00000000, /* dst_mask */ 167228753Smm FALSE), /* pcrel_offset */ 168228753Smm 169228753Smm HOWTO (R_FT32_SC0, /* type */ 170228753Smm 0, /* rightshift */ 171228753Smm 1, /* size (0 = byte, 1 = short, 2 = long) */ 172228753Smm 10, /* bitsize */ 173228753Smm FALSE, /* pc_relative */ 174228753Smm 4, /* bitpos */ 175228753Smm complain_overflow_signed, /* complain_on_overflow */ 176228753Smm bfd_elf_generic_reloc, /* special_function */ 177228753Smm "R_FT32_SC0", /* name */ 178228753Smm FALSE, /* partial_inplace */ 179228753Smm 0x00000000, /* src_mask */ 180228753Smm 0x00000000, /* dst_mask */ 181228753Smm FALSE), /* pcrel_offset */ 182228753Smm HOWTO (R_FT32_SC1, /* type */ 183228753Smm 2, /* rightshift */ 184228753Smm 2, /* size (0 = byte, 1 = short, 2 = long) */ 185228753Smm 22, /* bitsize */ 186228753Smm TRUE, /* pc_relative */ 187228753Smm 7, /* bitpos */ 188228753Smm complain_overflow_dont, /* complain_on_overflow */ 189228753Smm bfd_elf_generic_reloc, /* special_function */ 190228753Smm "R_FT32_SC1", /* name */ 191228753Smm TRUE, /* partial_inplace */ 192228753Smm 0x07ffff80, /* src_mask */ 193228753Smm 0x07ffff80, /* dst_mask */ 194228753Smm FALSE), /* pcrel_offset */ 195228753Smm HOWTO (R_FT32_15, /* type */ 196228753Smm 0, /* rightshift */ 197228753Smm 2, /* size (0 = byte, 1 = short, 2 = long) */ 198228753Smm 15, /* bitsize */ 199228753Smm FALSE, /* pc_relative */ 200228753Smm 0, /* bitpos */ 201228753Smm complain_overflow_dont, /* complain_on_overflow */ 202228753Smm bfd_elf_generic_reloc, /* special_function */ 203228753Smm "R_FT32_15", /* name */ 204228753Smm FALSE, /* partial_inplace */ 205228753Smm 0x00000000, /* src_mask */ 206228753Smm 0x00007fff, /* dst_mask */ 207228753Smm FALSE), /* pcrel_offset */ 208228753Smm HOWTO (R_FT32_DIFF32, /* type */ 209228753Smm 0, /* rightshift */ 210228753Smm 2, /* size (0 = byte, 1 = short, 2 = long) */ 211228753Smm 32, /* bitsize */ 212228753Smm FALSE, /* pc_relative */ 213228753Smm 0, /* bitpos */ 214228753Smm complain_overflow_dont, /* complain_on_overflow */ 215228753Smm bfd_elf_ft32_diff_reloc, /* special_function */ 216228753Smm "R_FT32_DIFF32", /* name */ 217228753Smm FALSE, /* partial_inplace */ 218228753Smm 0, /* src_mask */ 219228753Smm 0xffffffff, /* dst_mask */ 220228753Smm FALSE), /* pcrel_offset */ 221228753Smm}; 222228753Smm 223228753Smm 224228753Smm/* Map BFD reloc types to FT32 ELF reloc types. */ 225228753Smm 226228753Smmstruct ft32_reloc_map 227228753Smm{ 228228753Smm bfd_reloc_code_real_type bfd_reloc_val; 229228753Smm unsigned int ft32_reloc_val; 230228753Smm}; 231228753Smm 232228753Smmstatic const struct ft32_reloc_map ft32_reloc_map [] = 233228753Smm{ 234228753Smm { BFD_RELOC_NONE, R_FT32_NONE }, 235228753Smm { BFD_RELOC_32, R_FT32_32 }, 236228753Smm { BFD_RELOC_16, R_FT32_16 }, 237228753Smm { BFD_RELOC_8, R_FT32_8 }, 238228753Smm { BFD_RELOC_FT32_10, R_FT32_10 }, 239228753Smm { BFD_RELOC_FT32_20, R_FT32_20 }, 240228753Smm { BFD_RELOC_FT32_17, R_FT32_17 }, 241228753Smm { BFD_RELOC_FT32_18, R_FT32_18 }, 242228753Smm { BFD_RELOC_FT32_RELAX, R_FT32_RELAX }, 243228753Smm { BFD_RELOC_FT32_SC0, R_FT32_SC0 }, 244228753Smm { BFD_RELOC_FT32_SC1, R_FT32_SC1 }, 245228753Smm { BFD_RELOC_FT32_15, R_FT32_15 }, 246228753Smm { BFD_RELOC_FT32_DIFF32, R_FT32_DIFF32 }, 247228753Smm}; 248228753Smm 249228753Smm/* Perform a diff relocation. Nothing to do, as the difference value is 250228753Smm already written into the section's contents. */ 251228753Smm 252228753Smmstatic bfd_reloc_status_type 253228753Smmbfd_elf_ft32_diff_reloc (bfd *abfd ATTRIBUTE_UNUSED, 254228753Smm arelent *reloc_entry ATTRIBUTE_UNUSED, 255228753Smm asymbol *symbol ATTRIBUTE_UNUSED, 256228753Smm void *data ATTRIBUTE_UNUSED, 257228753Smm asection *input_section ATTRIBUTE_UNUSED, 258228753Smm bfd *output_bfd ATTRIBUTE_UNUSED, 259228753Smm char **error_message ATTRIBUTE_UNUSED) 260228753Smm{ 261228753Smm return bfd_reloc_ok; 262228753Smm} 263228753Smm 264228753Smmstatic reloc_howto_type * 265228753Smmft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 266228753Smm bfd_reloc_code_real_type code) 267228753Smm{ 268228753Smm unsigned int i; 269228753Smm 270228753Smm for (i = sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]); 271228753Smm --i;) 272228753Smm if (ft32_reloc_map [i].bfd_reloc_val == code) 273228753Smm return & ft32_elf_howto_table [ft32_reloc_map[i].ft32_reloc_val]; 274228753Smm 275228753Smm return NULL; 276228753Smm} 277228753Smm 278228753Smmstatic reloc_howto_type * 279228753Smmft32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 280228753Smm{ 281228753Smm unsigned int i; 282228753Smm 283228753Smm for (i = 0; 284228753Smm i < sizeof (ft32_elf_howto_table) / sizeof (ft32_elf_howto_table[0]); 285228753Smm i++) 286228753Smm if (ft32_elf_howto_table[i].name != NULL 287228753Smm && strcasecmp (ft32_elf_howto_table[i].name, r_name) == 0) 288228753Smm return &ft32_elf_howto_table[i]; 289228753Smm 290228753Smm return NULL; 291228753Smm} 292228753Smm 293228753Smm/* Set the howto pointer for an FT32 ELF reloc. */ 294228753Smm 295228753Smmstatic bfd_boolean 296228753Smmft32_info_to_howto_rela (bfd *abfd, 297228753Smm arelent *cache_ptr, 298228753Smm Elf_Internal_Rela *dst) 299228753Smm{ 300228753Smm unsigned int r_type; 301228753Smm 302228753Smm r_type = ELF32_R_TYPE (dst->r_info); 303228753Smm if (r_type >= (unsigned int) R_FT32_max) 304228753Smm { 305228753Smm /* xgettext:c-format */ 306228753Smm _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 307228753Smm abfd, r_type); 308228753Smm bfd_set_error (bfd_error_bad_value); 309228753Smm return FALSE; 310228753Smm } 311228753Smm 312228753Smm cache_ptr->howto = & ft32_elf_howto_table [r_type]; 313228753Smm return cache_ptr->howto != NULL; 314228753Smm} 315228753Smm 316228753Smm/* Relocate an FT32 ELF section. 317228753Smm 318228753Smm The RELOCATE_SECTION function is called by the new ELF backend linker 319228753Smm to handle the relocations for a section. 320228753Smm 321228753Smm The relocs are always passed as Rela structures; if the section 322228753Smm actually uses Rel structures, the r_addend field will always be 323228753Smm zero. 324228753Smm 325228753Smm This function is responsible for adjusting the section contents as 326228753Smm necessary, and (if using Rela relocs and generating a relocatable 327228753Smm output file) adjusting the reloc addend as necessary. 328228753Smm 329228753Smm This function does not have to worry about setting the reloc 330228753Smm address or the reloc symbol index. 331228753Smm 332228753Smm LOCAL_SYMS is a pointer to the swapped in local symbols. 333228753Smm 334228753Smm LOCAL_SECTIONS is an array giving the section in the input file 335228753Smm corresponding to the st_shndx field of each local symbol. 336228753Smm 337228753Smm The global hash table entry for the global symbols can be found 338228753Smm via elf_sym_hashes (input_bfd). 339228753Smm 340228753Smm When generating relocatable output, this function must handle 341228753Smm STB_LOCAL/STT_SECTION symbols specially. The output symbol is 342228753Smm going to be the section symbol corresponding to the output 343228753Smm section, which means that the addend must be adjusted 344228753Smm accordingly. */ 345228753Smm 346228753Smmstatic bfd_boolean 347228753Smmft32_elf_relocate_section (bfd *output_bfd, 348228753Smm struct bfd_link_info *info, 349228753Smm bfd *input_bfd, 350228753Smm asection *input_section, 351228753Smm bfd_byte *contents, 352228753Smm Elf_Internal_Rela *relocs, 353228753Smm Elf_Internal_Sym *local_syms, 354228753Smm asection **local_sections) 355228753Smm{ 356228753Smm Elf_Internal_Shdr *symtab_hdr; 357228753Smm struct elf_link_hash_entry **sym_hashes; 358228753Smm Elf_Internal_Rela *rel; 359228753Smm Elf_Internal_Rela *relend; 360228753Smm 361228753Smm symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; 362228753Smm sym_hashes = elf_sym_hashes (input_bfd); 363228753Smm relend = relocs + input_section->reloc_count; 364228753Smm 365228753Smm for (rel = relocs; rel < relend; rel ++) 366228753Smm { 367228753Smm reloc_howto_type *howto; 368228753Smm unsigned long r_symndx; 369228753Smm Elf_Internal_Sym *sym; 370228753Smm asection *sec; 371228753Smm struct elf_link_hash_entry *h; 372228753Smm bfd_vma relocation; 373228753Smm bfd_reloc_status_type r; 374228753Smm const char *name; 375228753Smm int r_type; 376228753Smm 377228753Smm r_type = ELF32_R_TYPE (rel->r_info); 378228753Smm r_symndx = ELF32_R_SYM (rel->r_info); 379228753Smm howto = ft32_elf_howto_table + r_type; 380228753Smm h = NULL; 381228753Smm sym = NULL; 382228753Smm sec = NULL; 383228753Smm 384228753Smm if (r_symndx < symtab_hdr->sh_info) 385228753Smm { 386228753Smm sym = local_syms + r_symndx; 387228753Smm sec = local_sections [r_symndx]; 388228753Smm relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 389228753Smm 390228753Smm name = bfd_elf_string_from_elf_section 391228753Smm (input_bfd, symtab_hdr->sh_link, sym->st_name); 392228753Smm name = name == NULL ? bfd_section_name (sec) : name; 393228753Smm } 394228753Smm else 395228753Smm { 396228753Smm bfd_boolean unresolved_reloc, warned, ignored; 397228753Smm 398228753Smm RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 399228753Smm r_symndx, symtab_hdr, sym_hashes, 400228753Smm h, sec, relocation, 401228753Smm unresolved_reloc, warned, ignored); 402228753Smm 403228753Smm name = h->root.root.string; 404228753Smm } 405228753Smm 406228753Smm if (sec != NULL && discarded_section (sec)) 407228753Smm RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, 408228753Smm rel, 1, relend, howto, 0, contents); 409228753Smm 410228753Smm if (bfd_link_relocatable (info)) 411228753Smm continue; 412228753Smm 413228753Smm switch (howto->type) 414228753Smm { 415228753Smm case R_FT32_SC0: 416228753Smm { 417228753Smm unsigned int insn; 418228753Smm int offset; 419228753Smm unsigned int code15[2]; 420228753Smm 421228753Smm insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 422228753Smm ft32_split_shortcode (insn, code15); 423228753Smm 424228753Smm offset = (int)relocation; 425228753Smm offset += (int)(rel->r_addend - rel->r_offset); 426228753Smm offset -= (input_section->output_section->vma + 427228753Smm input_section->output_offset); 428228753Smm if ((offset < -1024) || (offset >= 1024)) 429228753Smm { 430228753Smm r = bfd_reloc_outofrange; 431228753Smm break; 432228753Smm } 433228753Smm code15[0] |= ((offset / 4) & 511); 434228753Smm insn = ft32_merge_shortcode (code15); 435228753Smm bfd_put_32 (input_bfd, insn, contents + rel->r_offset); 436228753Smm } 437228753Smm r = bfd_reloc_ok; 438228753Smm break; 439228753Smm 440228753Smm case R_FT32_SC1: 441228753Smm { 442228753Smm unsigned int insn; 443228753Smm int offset; 444228753Smm unsigned int code15[2]; 445228753Smm 446228753Smm insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 447228753Smm ft32_split_shortcode (insn, code15); 448228753Smm 449228753Smm offset = (int)relocation; 450228753Smm offset += (int)(rel->r_addend - rel->r_offset); 451228753Smm offset -= (input_section->output_section->vma + 452228753Smm input_section->output_offset); 453228753Smm if ((offset < -1024) || (offset >= 1024)) 454 { 455 r = bfd_reloc_outofrange; 456 break; 457 } 458 code15[1] |= ((offset / 4) & 511); 459 insn = ft32_merge_shortcode (code15); 460 bfd_put_32 (input_bfd, insn, contents + rel->r_offset); 461 } 462 r = bfd_reloc_ok; 463 break; 464 465 case R_FT32_DIFF32: 466 r = bfd_reloc_ok; 467 break; 468 469 default: 470 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 471 contents, rel->r_offset, 472 relocation, rel->r_addend); 473 break; 474 } 475 476 if (r != bfd_reloc_ok) 477 { 478 const char * msg = NULL; 479 480 switch (r) 481 { 482 case bfd_reloc_overflow: 483 (*info->callbacks->reloc_overflow) 484 (info, (h ? &h->root : NULL), name, howto->name, 485 (bfd_vma) 0, input_bfd, input_section, rel->r_offset); 486 break; 487 488 case bfd_reloc_undefined: 489 (*info->callbacks->undefined_symbol) 490 (info, name, input_bfd, input_section, rel->r_offset, TRUE); 491 break; 492 493 case bfd_reloc_outofrange: 494 msg = _("internal error: out of range error"); 495 break; 496 497 case bfd_reloc_notsupported: 498 msg = _("internal error: unsupported relocation error"); 499 break; 500 501 case bfd_reloc_dangerous: 502 msg = _("internal error: dangerous relocation"); 503 break; 504 505 default: 506 msg = _("internal error: unknown error"); 507 break; 508 } 509 510 if (msg) 511 (*info->callbacks->warning) (info, msg, name, input_bfd, 512 input_section, rel->r_offset); 513 } 514 } 515 516 return TRUE; 517} 518 519/* Relaxation. */ 520 521static bfd_boolean 522ft32_reloc_shortable 523 (bfd * abfd, 524 asection * sec, 525 Elf_Internal_Sym * isymbuf ATTRIBUTE_UNUSED, 526 bfd_byte * contents, 527 bfd_vma pc ATTRIBUTE_UNUSED, 528 Elf_Internal_Rela * irel, 529 unsigned int * sc) 530{ 531 Elf_Internal_Shdr *symtab_hdr ATTRIBUTE_UNUSED; 532 bfd_vma symval; 533 534 enum elf_ft32_reloc_type r_type; 535 reloc_howto_type *howto = NULL; 536 unsigned int insn; 537 int offset; 538 bfd_vma dot, value; 539 540 r_type = ELF32_R_TYPE (irel->r_info); 541 howto = &ft32_elf_howto_table [r_type]; 542 543 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 544 545 /* Get the value of the symbol referred to by the reloc. */ 546 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 547 { 548 /* A local symbol. */ 549 Elf_Internal_Sym *isym; 550 asection *sym_sec; 551 552 isym = isymbuf + ELF32_R_SYM (irel->r_info); 553 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 554 symval = isym->st_value; 555 /* If the reloc is absolute, it will not have 556 a symbol or section associated with it. */ 557 if (sym_sec) 558 symval += sym_sec->output_section->vma 559 + sym_sec->output_offset; 560 } 561 else 562 { 563 unsigned long indx; 564 struct elf_link_hash_entry *h; 565 566 /* An external symbol. */ 567 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; 568 h = elf_sym_hashes (abfd)[indx]; 569 BFD_ASSERT (h != NULL); 570 if (h->root.type != bfd_link_hash_defined 571 && h->root.type != bfd_link_hash_defweak) 572 /* This appears to be a reference to an undefined 573 symbol. Just ignore it--it will be caught by the 574 regular reloc processing. */ 575 return FALSE; 576 577 symval = (h->root.u.def.value 578 + h->root.u.def.section->output_section->vma 579 + h->root.u.def.section->output_offset); 580 } 581 582 switch (r_type) 583 { 584 case R_FT32_8: 585 case R_FT32_10: 586 case R_FT32_16: 587 case R_FT32_20: 588 case R_FT32_RELAX: 589 if (symval != 0) 590 return FALSE; 591 insn = bfd_get_32 (abfd, contents + irel->r_offset); 592 insn |= ((symval + irel->r_addend) << howto->bitpos) & howto->dst_mask; 593 return ft32_shortcode (insn, sc); 594 595 case R_FT32_18: 596 insn = bfd_get_32 (abfd, contents + irel->r_offset); 597 /* Get the address of this instruction. */ 598 dot = (sec->output_section->vma 599 + sec->output_offset + irel->r_offset); 600 value = symval + irel->r_addend; 601 offset = (value - dot) / 4; 602 603 if ((dot > 0x8c) && (-256 <= offset) && (offset < 256)) 604 { 605 switch (insn) 606 { 607 case 0x00200000: *sc = (3 << 13) | (0 << 9); return TRUE; 608 case 0x00280000: *sc = (3 << 13) | (1 << 9); return TRUE; 609 case 0x00600000: *sc = (3 << 13) | (2 << 9); return TRUE; 610 case 0x00680000: *sc = (3 << 13) | (3 << 9); return TRUE; 611 case 0x00a00000: *sc = (3 << 13) | (4 << 9); return TRUE; 612 case 0x00a80000: *sc = (3 << 13) | (5 << 9); return TRUE; 613 case 0x00e00000: *sc = (3 << 13) | (6 << 9); return TRUE; 614 case 0x00e80000: *sc = (3 << 13) | (7 << 9); return TRUE; 615 case 0x01200000: *sc = (3 << 13) | (8 << 9); return TRUE; 616 case 0x01280000: *sc = (3 << 13) | (9 << 9); return TRUE; 617 case 0x01600000: *sc = (3 << 13) | (10 << 9); return TRUE; 618 case 0x01680000: *sc = (3 << 13) | (11 << 9); return TRUE; 619 case 0x01a00000: *sc = (3 << 13) | (12 << 9); return TRUE; 620 case 0x01a80000: *sc = (3 << 13) | (13 << 9); return TRUE; 621 622 case 0x00300000: *sc = (3 << 13) | (14 << 9); return TRUE; 623 case 0x00340000: *sc = (3 << 13) | (15 << 9); return TRUE; 624 625 default: 626 break; 627 } 628 } 629 break; 630 631 default: 632 break; 633 } 634 return FALSE; 635} 636 637/* Returns whether the relocation type passed is a diff reloc. */ 638 639static bfd_boolean 640elf32_ft32_is_diff_reloc (Elf_Internal_Rela *irel) 641{ 642 return (ELF32_R_TYPE (irel->r_info) == R_FT32_DIFF32); 643} 644 645/* Reduce the diff value written in the section by count if the shrinked 646 insn address happens to fall between the two symbols for which this 647 diff reloc was emitted. */ 648 649static bfd_boolean 650elf32_ft32_adjust_diff_reloc_value (bfd *abfd, 651 struct bfd_section *isec, 652 Elf_Internal_Rela *irel, 653 bfd_vma symval, 654 bfd_vma shrinked_insn_address, 655 int count) 656{ 657 unsigned char * reloc_contents = NULL; 658 unsigned char * isec_contents = elf_section_data (isec)->this_hdr.contents; 659 bfd_signed_vma x = 0; 660 bfd_vma sym2_address; 661 bfd_vma sym1_address; 662 bfd_vma start_address; 663 bfd_vma end_address; 664 665 666 if (isec_contents == NULL) 667 { 668 if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents)) 669 return FALSE; 670 671 elf_section_data (isec)->this_hdr.contents = isec_contents; 672 } 673 674 reloc_contents = isec_contents + irel->r_offset; 675 676 /* Read value written in object file. */ 677 switch (ELF32_R_TYPE (irel->r_info)) 678 { 679 case R_FT32_DIFF32: 680 x = bfd_get_signed_32 (abfd, reloc_contents); 681 break; 682 683 default: 684 return FALSE; 685 } 686 687 /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written 688 into the object file at the reloc offset. sym2's logical value is 689 symval (<start_of_section>) + reloc addend. Compute the start and end 690 addresses and check if the shrinked insn falls between sym1 and sym2. */ 691 sym2_address = symval + irel->r_addend; 692 sym1_address = sym2_address - x; 693 694 /* Don't assume sym2 is bigger than sym1 - the difference 695 could be negative. Compute start and end addresses, and 696 use those to see if they span shrinked_insn_address. */ 697 start_address = sym1_address < sym2_address ? sym1_address : sym2_address; 698 end_address = sym1_address > sym2_address ? sym1_address : sym2_address; 699 700 if (shrinked_insn_address >= start_address 701 && shrinked_insn_address < end_address) 702 { 703 /* Reduce the diff value by count bytes and write it back into section 704 contents. */ 705 bfd_signed_vma new_diff = x < 0 ? x + count : x - count; 706 707 if (sym2_address > shrinked_insn_address) 708 irel->r_addend -= count; 709 710 switch (ELF32_R_TYPE (irel->r_info)) 711 { 712 case R_FT32_DIFF32: 713 bfd_put_signed_32 (abfd, new_diff & 0xFFFFFFFF, reloc_contents); 714 break; 715 716 default: 717 return FALSE; 718 } 719 } 720 721 return TRUE; 722} 723 724static bfd_boolean 725elf32_ft32_adjust_reloc_if_spans_insn (bfd *abfd, 726 asection *isec, 727 Elf_Internal_Rela *irel, bfd_vma symval, 728 bfd_vma shrinked_insn_address, 729 bfd_vma shrink_boundary, 730 int count) 731{ 732 733 if (elf32_ft32_is_diff_reloc (irel)) 734 { 735 if (!elf32_ft32_adjust_diff_reloc_value (abfd, isec, irel, 736 symval, 737 shrinked_insn_address, 738 count)) 739 return FALSE; 740 } 741 else 742 { 743 bfd_vma reloc_value = symval + irel->r_addend; 744 bfd_boolean addend_within_shrink_boundary = 745 (reloc_value <= shrink_boundary); 746 bfd_boolean reloc_spans_insn = 747 (symval <= shrinked_insn_address 748 && reloc_value > shrinked_insn_address 749 && addend_within_shrink_boundary); 750 751 if (! reloc_spans_insn) 752 return TRUE; 753 754 irel->r_addend -= count; 755 756 if (debug_relax) 757 printf ("Relocation's addend needed to be fixed \n"); 758 } 759 return TRUE; 760} 761 762/* Delete some bytes from a section while relaxing. */ 763 764static bfd_boolean 765elf32_ft32_relax_delete_bytes (struct bfd_link_info *link_info, bfd * abfd, 766 asection * sec, bfd_vma addr, int count) 767{ 768 Elf_Internal_Shdr *symtab_hdr; 769 unsigned int sec_shndx; 770 bfd_byte *contents; 771 Elf_Internal_Rela *irel, *irelend; 772 bfd_vma toaddr; 773 Elf_Internal_Sym *isym; 774 Elf_Internal_Sym *isymend; 775 struct elf_link_hash_entry **sym_hashes; 776 struct elf_link_hash_entry **end_hashes; 777 struct elf_link_hash_entry **start_hashes; 778 unsigned int symcount; 779 Elf_Internal_Sym *isymbuf = NULL; 780 781 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 782 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); 783 784 contents = elf_section_data (sec)->this_hdr.contents; 785 786 toaddr = sec->size; 787 788 irel = elf_section_data (sec)->relocs; 789 irelend = irel + sec->reloc_count; 790 791 /* Actually delete the bytes. */ 792 memmove (contents + addr, contents + addr + count, 793 (size_t) (toaddr - addr - count)); 794 sec->size -= count; 795 796 /* Adjust all the relocs. */ 797 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) 798 /* Get the new reloc address. */ 799 if ((irel->r_offset > addr && irel->r_offset < toaddr)) 800 irel->r_offset -= count; 801 802 /* The reloc's own addresses are now ok. However, we need to readjust 803 the reloc's addend, i.e. the reloc's value if two conditions are met: 804 1.) the reloc is relative to a symbol in this section that 805 is located in front of the shrinked instruction 806 2.) symbol plus addend end up behind the shrinked instruction. 807 808 The most common case where this happens are relocs relative to 809 the section-start symbol. 810 811 This step needs to be done for all of the sections of the bfd. */ 812 { 813 struct bfd_section *isec; 814 815 for (isec = abfd->sections; isec; isec = isec->next) 816 { 817 bfd_vma symval; 818 bfd_vma shrinked_insn_address; 819 820 if (isec->reloc_count == 0) 821 continue; 822 823 shrinked_insn_address = (sec->output_section->vma 824 + sec->output_offset + addr - count); 825 826 irel = elf_section_data (isec)->relocs; 827 /* PR 12161: Read in the relocs for this section if necessary. */ 828 if (irel == NULL) 829 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE); 830 831 for (irelend = irel + isec->reloc_count; irel < irelend; irel++) 832 { 833 /* Read this BFD's local symbols if we haven't done 834 so already. */ 835 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 836 { 837 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 838 if (isymbuf == NULL) 839 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 840 symtab_hdr->sh_info, 0, 841 NULL, NULL, NULL); 842 if (isymbuf == NULL) 843 return FALSE; 844 } 845 846 /* Get the value of the symbol referred to by the reloc. */ 847 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 848 { 849 /* A local symbol. */ 850 asection *sym_sec; 851 852 isym = isymbuf + ELF32_R_SYM (irel->r_info); 853 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 854 symval = isym->st_value; 855 /* If the reloc is absolute, it will not have 856 a symbol or section associated with it. */ 857 if (sym_sec == sec) 858 { 859 symval += sym_sec->output_section->vma 860 + sym_sec->output_offset; 861 862 if (debug_relax) 863 printf ("Checking if the relocation's " 864 "addend needs corrections.\n" 865 "Address of anchor symbol: 0x%x \n" 866 "Address of relocation target: 0x%x \n" 867 "Address of relaxed insn: 0x%x \n", 868 (unsigned int) symval, 869 (unsigned int) (symval + irel->r_addend), 870 (unsigned int) shrinked_insn_address); 871 872 if (symval <= shrinked_insn_address 873 && (symval + irel->r_addend) > shrinked_insn_address) 874 { 875 /* If there is an alignment boundary, we only need to 876 adjust addends that end up below the boundary. */ 877 bfd_vma shrink_boundary = (toaddr 878 + sec->output_section->vma 879 + sec->output_offset); 880 881 if (debug_relax) 882 printf 883 ("Relocation's addend needed to be fixed \n"); 884 885 if (!elf32_ft32_adjust_reloc_if_spans_insn (abfd, isec, 886 irel, symval, 887 shrinked_insn_address, 888 shrink_boundary, 889 count)) 890 return FALSE; 891 } 892 } 893 /* else reference symbol is absolute. No adjustment needed. */ 894 } 895 /* else...Reference symbol is extern. No need for adjusting 896 the addend. */ 897 } 898 } 899 } 900 901 /* Adjust the local symbols defined in this section. */ 902 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 903 isym = (Elf_Internal_Sym *) symtab_hdr->contents; 904 if (isym) 905 { 906 for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) 907 { 908 if (isym->st_shndx == sec_shndx 909 && isym->st_value > addr && isym->st_value < toaddr) 910 isym->st_value -= count; 911 } 912 } 913 914 /* Now adjust the global symbols defined in this section. */ 915 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) 916 - symtab_hdr->sh_info); 917 sym_hashes = start_hashes = elf_sym_hashes (abfd); 918 end_hashes = sym_hashes + symcount; 919 920 for (; sym_hashes < end_hashes; sym_hashes++) 921 { 922 struct elf_link_hash_entry *sym_hash = *sym_hashes; 923 924 /* The '--wrap SYMBOL' option is causing a pain when the object file, 925 containing the definition of __wrap_SYMBOL, includes a direct 926 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference 927 the same symbol (which is __wrap_SYMBOL), but still exist as two 928 different symbols in 'sym_hashes', we don't want to adjust 929 the global symbol __wrap_SYMBOL twice. 930 This check is only relevant when symbols are being wrapped. */ 931 if (link_info->wrap_hash != NULL) 932 { 933 struct elf_link_hash_entry **cur_sym_hashes; 934 935 /* Loop only over the symbols whom been already checked. */ 936 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes; 937 cur_sym_hashes++) 938 /* If the current symbol is identical to 'sym_hash', that means 939 the symbol was already adjusted (or at least checked). */ 940 if (*cur_sym_hashes == sym_hash) 941 break; 942 943 /* Don't adjust the symbol again. */ 944 if (cur_sym_hashes < sym_hashes) 945 continue; 946 } 947 948 if ((sym_hash->root.type == bfd_link_hash_defined 949 || sym_hash->root.type == bfd_link_hash_defweak) 950 && sym_hash->root.u.def.section == sec 951 && sym_hash->root.u.def.value > addr 952 && sym_hash->root.u.def.value < toaddr) 953 sym_hash->root.u.def.value -= count; 954 } 955 956 return TRUE; 957} 958 959/* Return TRUE if LOC can be a target of a branch, jump or call. */ 960 961static bfd_boolean 962elf32_ft32_relax_is_branch_target (struct bfd_link_info *link_info, 963 bfd * abfd, asection * sec, 964 bfd_vma loc) 965{ 966 Elf_Internal_Shdr *symtab_hdr; 967 Elf_Internal_Rela *irel, *irelend; 968 Elf_Internal_Sym *isym; 969 Elf_Internal_Sym *isymbuf = NULL; 970 bfd_vma symval; 971 struct bfd_section *isec; 972 973 struct elf_link_hash_entry **sym_hashes; 974 struct elf_link_hash_entry **end_hashes; 975 struct elf_link_hash_entry **start_hashes; 976 unsigned int symcount; 977 978 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 979 980 /* Now we check for relocations pointing to ret. */ 981 for (isec = abfd->sections; isec; isec = isec->next) 982 { 983 irel = elf_section_data (isec)->relocs; 984 if (irel == NULL) 985 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE); 986 987 irelend = irel + isec->reloc_count; 988 989 for (; irel < irelend; irel++) 990 { 991 /* Read this BFD's local symbols if we haven't done 992 so already. */ 993 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 994 { 995 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 996 if (isymbuf == NULL) 997 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 998 symtab_hdr->sh_info, 0, 999 NULL, NULL, NULL); 1000 if (isymbuf == NULL) 1001 return FALSE; 1002 } 1003 1004 /* Get the value of the symbol referred to by the reloc. */ 1005 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 1006 { 1007 /* A local symbol. */ 1008 asection *sym_sec; 1009 1010 isym = isymbuf + ELF32_R_SYM (irel->r_info); 1011 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 1012 symval = isym->st_value; 1013 /* If the reloc is absolute, it will not have 1014 a symbol or section associated with it. */ 1015 if (sym_sec == sec) 1016 { 1017 symval += sym_sec->output_section->vma 1018 + sym_sec->output_offset; 1019 1020 if (debug_relax) 1021 printf ("0x%x: Address of anchor symbol: 0x%x " 1022 "Address of relocation target: 0x%x \n", 1023 (unsigned int) irel->r_offset, 1024 (unsigned int) symval, 1025 (unsigned int) (symval + irel->r_addend)); 1026 if ((irel->r_addend) == loc) 1027 return TRUE; 1028 } 1029 } 1030 } 1031 } 1032 1033 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) 1034 - symtab_hdr->sh_info); 1035 sym_hashes = start_hashes = elf_sym_hashes (abfd); 1036 end_hashes = sym_hashes + symcount; 1037 1038 for (; sym_hashes < end_hashes; sym_hashes++) 1039 { 1040 struct elf_link_hash_entry *sym_hash = *sym_hashes; 1041 1042 /* The '--wrap SYMBOL' option is causing a pain when the object file, 1043 containing the definition of __wrap_SYMBOL, includes a direct 1044 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference 1045 the same symbol (which is __wrap_SYMBOL), but still exist as two 1046 different symbols in 'sym_hashes', we don't want to adjust 1047 the global symbol __wrap_SYMBOL twice. 1048 This check is only relevant when symbols are being wrapped. */ 1049 if (link_info->wrap_hash != NULL) 1050 { 1051 struct elf_link_hash_entry **cur_sym_hashes; 1052 1053 /* Loop only over the symbols whom been already checked. */ 1054 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes; 1055 cur_sym_hashes++) 1056 /* If the current symbol is identical to 'sym_hash', that means 1057 the symbol was already adjusted (or at least checked). */ 1058 if (*cur_sym_hashes == sym_hash) 1059 break; 1060 1061 /* Don't adjust the symbol again. */ 1062 if (cur_sym_hashes < sym_hashes) 1063 continue; 1064 } 1065 1066 if ((sym_hash->root.type == bfd_link_hash_defined 1067 || sym_hash->root.type == bfd_link_hash_defweak) 1068 && sym_hash->root.u.def.section == sec 1069 && sym_hash->root.u.def.value == loc) 1070 return TRUE; 1071 } 1072 1073 return FALSE; 1074} 1075 1076static bfd_boolean 1077ft32_elf_relax_section 1078 (bfd * abfd, 1079 asection * sec, 1080 struct bfd_link_info * link_info, 1081 bfd_boolean * again) 1082{ 1083 Elf_Internal_Rela * free_relocs = NULL; 1084 Elf_Internal_Rela * internal_relocs; 1085 Elf_Internal_Rela * irelend; 1086 Elf_Internal_Rela * irel; 1087 bfd_byte * contents = NULL; 1088 Elf_Internal_Shdr * symtab_hdr; 1089 Elf_Internal_Sym * isymbuf = NULL; 1090 1091 /* Assume nothing changes. */ 1092 *again = FALSE; 1093 1094 /* We don't have to do anything for a relocatable link, if 1095 this section does not have relocs, or if this is not a 1096 code section. */ 1097 if (bfd_link_relocatable (link_info) 1098 || (sec->flags & SEC_RELOC) == 0 1099 || sec->reloc_count == 0 1100 || (sec->flags & SEC_CODE) == 0) 1101 return TRUE; 1102 1103 /* Get the section contents. */ 1104 if (elf_section_data (sec)->this_hdr.contents != NULL) 1105 contents = elf_section_data (sec)->this_hdr.contents; 1106 /* Go get them off disk. */ 1107 else 1108 { 1109 if (! bfd_malloc_and_get_section (abfd, sec, &contents)) 1110 goto error_return; 1111 elf_section_data (sec)->this_hdr.contents = contents; 1112 } 1113 1114 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 1115 1116 /* Read this BFD's local symbols if we haven't done so already. */ 1117 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 1118 { 1119 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 1120 if (isymbuf == NULL) 1121 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 1122 symtab_hdr->sh_info, 0, 1123 NULL, NULL, NULL); 1124 if (isymbuf == NULL) 1125 goto error_return; 1126 symtab_hdr->contents = (unsigned char *) isymbuf; 1127 } 1128 1129 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, 1130 link_info->keep_memory); 1131 if (internal_relocs == NULL) 1132 goto error_return; 1133 if (! link_info->keep_memory) 1134 free_relocs = internal_relocs; 1135 1136 /* Walk through them looking for relaxing opportunities. */ 1137 irelend = internal_relocs + sec->reloc_count; 1138 1139 /* Test every adjacent pair of relocs. If both have shortcodes, 1140 fuse them and delete the relocs. */ 1141 irel = internal_relocs; 1142 while (irel < irelend - 1) 1143 { 1144 Elf_Internal_Rela * irel_next = irel + 1; 1145 unsigned int sc0, sc1; 1146 bfd_vma pc; 1147 1148 pc = irel->r_offset; 1149 1150 if (((pc + 4) == (irel_next->r_offset)) 1151 && ft32_reloc_shortable (abfd, sec, isymbuf, contents, pc, irel, 1152 &sc0) 1153 && ft32_reloc_shortable (abfd, sec, isymbuf, contents, pc, 1154 irel_next, &sc1) 1155 && !elf32_ft32_relax_is_branch_target (link_info, abfd, sec, 1156 irel_next->r_offset)) 1157 { 1158 unsigned int code30 = (sc1 << 15) | sc0; 1159 unsigned int code27 = code30 >> 3; 1160 unsigned int code3 = code30 & 7; 1161 static const unsigned char pat3[] = {2, 3, 4, 5, 6, 9, 10, 14}; 1162 unsigned int pattern = pat3[code3]; 1163 unsigned int fused = (pattern << 27) | code27; 1164 1165 /* Move second reloc to same place as first. */ 1166 irel_next->r_offset = irel->r_offset; 1167 1168 /* Change both relocs to R_FT32_NONE. */ 1169 1170 if (ELF32_R_TYPE (irel->r_info) == R_FT32_18) 1171 { 1172 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1173 R_FT32_SC0); 1174 } 1175 else 1176 { 1177 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1178 R_FT32_NONE); 1179 } 1180 1181 if (ELF32_R_TYPE (irel_next->r_info) == R_FT32_18) 1182 { 1183 irel_next->r_info = ELF32_R_INFO (ELF32_R_SYM (irel_next->r_info), 1184 R_FT32_SC1); 1185 } 1186 else 1187 { 1188 irel_next->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1189 R_FT32_NONE); 1190 } 1191 1192 /* Replace the first insn with the fused version. */ 1193 bfd_put_32 (abfd, fused, contents + irel->r_offset); 1194 1195 /* Delete the second insn. */ 1196 if (!elf32_ft32_relax_delete_bytes (link_info, abfd, sec, 1197 irel->r_offset + 4, 4)) 1198 goto error_return; 1199 1200 /* That will change things, so, we should relax again. 1201 Note that this is not required, and it may be slow. */ 1202 *again = TRUE; 1203 1204 irel += 2; 1205 } 1206 else 1207 { 1208 irel += 1; 1209 } 1210 } 1211 1212 if (isymbuf != NULL 1213 && symtab_hdr->contents != (unsigned char *) isymbuf) 1214 { 1215 if (! link_info->keep_memory) 1216 free (isymbuf); 1217 else 1218 /* Cache the symbols for elf_link_input_bfd. */ 1219 symtab_hdr->contents = (unsigned char *) isymbuf; 1220 } 1221 1222 if (contents != NULL 1223 && elf_section_data (sec)->this_hdr.contents != contents) 1224 { 1225 if (! link_info->keep_memory) 1226 free (contents); 1227 else 1228 /* Cache the section contents for elf_link_input_bfd. */ 1229 elf_section_data (sec)->this_hdr.contents = contents; 1230 1231 } 1232 1233 if (elf_section_data (sec)->relocs != internal_relocs) 1234 free (internal_relocs); 1235 1236 return TRUE; 1237 1238 error_return: 1239 free (free_relocs); 1240 1241 return TRUE; 1242} 1243 1244#define ELF_ARCH bfd_arch_ft32 1245#define ELF_MACHINE_CODE EM_FT32 1246#define ELF_MAXPAGESIZE 0x1 1247 1248#define TARGET_LITTLE_SYM ft32_elf32_vec 1249#define TARGET_LITTLE_NAME "elf32-ft32" 1250 1251#define elf_info_to_howto_rel NULL 1252#define elf_info_to_howto ft32_info_to_howto_rela 1253#define elf_backend_relocate_section ft32_elf_relocate_section 1254 1255#define elf_backend_can_gc_sections 1 1256#define elf_backend_rela_normal 1 1257 1258#define bfd_elf32_bfd_reloc_type_lookup ft32_reloc_type_lookup 1259#define bfd_elf32_bfd_reloc_name_lookup ft32_reloc_name_lookup 1260 1261#define bfd_elf32_bfd_relax_section ft32_elf_relax_section 1262 1263#include "elf32-target.h" 1264