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