(root)/
binutils-2.41/
bfd/
elf32-crx.c
       1  /* BFD back-end for National Semiconductor's CRX ELF
       2     Copyright (C) 2004-2023 Free Software Foundation, Inc.
       3     Written by Tomer Levi, NSC, Israel.
       4  
       5     This file is part of BFD, the Binary File Descriptor library.
       6  
       7     This program is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3 of the License, or
      10     (at your option) any later version.
      11  
      12     This program is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with this program; if not, write to the Free Software
      19     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      20     MA 02110-1301, USA.  */
      21  
      22  #include "sysdep.h"
      23  #include "bfd.h"
      24  #include "bfdlink.h"
      25  #include "libbfd.h"
      26  #include "elf-bfd.h"
      27  #include "elf/crx.h"
      28  
      29  static reloc_howto_type *elf_crx_reloc_type_lookup
      30    (bfd *, bfd_reloc_code_real_type);
      31  static bool elf_crx_info_to_howto
      32    (bfd *, arelent *, Elf_Internal_Rela *);
      33  static bool elf32_crx_relax_delete_bytes
      34    (struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
      35  static bfd_reloc_status_type crx_elf_final_link_relocate
      36    (reloc_howto_type *, bfd *, bfd *, asection *,
      37     bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
      38     struct bfd_link_info *, asection *, int);
      39  static int elf32_crx_relocate_section
      40    (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
      41     Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
      42  static bool elf32_crx_relax_section
      43    (bfd *, asection *, struct bfd_link_info *, bool *);
      44  static bfd_byte * elf32_crx_get_relocated_section_contents
      45    (bfd *, struct bfd_link_info *, struct bfd_link_order *,
      46     bfd_byte *, bool, asymbol **);
      47  
      48  /* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
      49  
      50  struct crx_reloc_map
      51  {
      52    bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
      53    unsigned short crx_reloc_type;	   /* CRX relocation type.  */
      54  };
      55  
      56  static const struct crx_reloc_map crx_reloc_map[R_CRX_MAX] =
      57  {
      58    {BFD_RELOC_NONE,	    R_CRX_NONE},
      59    {BFD_RELOC_CRX_REL4,	    R_CRX_REL4},
      60    {BFD_RELOC_CRX_REL8,	    R_CRX_REL8},
      61    {BFD_RELOC_CRX_REL8_CMP,  R_CRX_REL8_CMP},
      62    {BFD_RELOC_CRX_REL16,	    R_CRX_REL16},
      63    {BFD_RELOC_CRX_REL24,	    R_CRX_REL24},
      64    {BFD_RELOC_CRX_REL32,	    R_CRX_REL32},
      65    {BFD_RELOC_CRX_REGREL12,  R_CRX_REGREL12},
      66    {BFD_RELOC_CRX_REGREL22,  R_CRX_REGREL22},
      67    {BFD_RELOC_CRX_REGREL28,  R_CRX_REGREL28},
      68    {BFD_RELOC_CRX_REGREL32,  R_CRX_REGREL32},
      69    {BFD_RELOC_CRX_ABS16,	    R_CRX_ABS16},
      70    {BFD_RELOC_CRX_ABS32,	    R_CRX_ABS32},
      71    {BFD_RELOC_CRX_NUM8,	    R_CRX_NUM8},
      72    {BFD_RELOC_CRX_NUM16,	    R_CRX_NUM16},
      73    {BFD_RELOC_CRX_NUM32,	    R_CRX_NUM32},
      74    {BFD_RELOC_CRX_IMM16,	    R_CRX_IMM16},
      75    {BFD_RELOC_CRX_IMM32,	    R_CRX_IMM32},
      76    {BFD_RELOC_CRX_SWITCH8,   R_CRX_SWITCH8},
      77    {BFD_RELOC_CRX_SWITCH16,  R_CRX_SWITCH16},
      78    {BFD_RELOC_CRX_SWITCH32,  R_CRX_SWITCH32}
      79  };
      80  
      81  static reloc_howto_type crx_elf_howto_table[] =
      82  {
      83    HOWTO (R_CRX_NONE,		/* type */
      84  	 0,			/* rightshift */
      85  	 0,			/* size */
      86  	 0,			/* bitsize */
      87  	 false,			/* pc_relative */
      88  	 0,			/* bitpos */
      89  	 complain_overflow_dont,/* complain_on_overflow */
      90  	 bfd_elf_generic_reloc,	/* special_function */
      91  	 "R_CRX_NONE",		/* name */
      92  	 false,			/* partial_inplace */
      93  	 0,			/* src_mask */
      94  	 0,			/* dst_mask */
      95  	 false),		/* pcrel_offset */
      96  
      97    HOWTO (R_CRX_REL4,		/* type */
      98  	 1,			/* rightshift */
      99  	 1,			/* size */
     100  	 4,			/* bitsize */
     101  	 true,			/* pc_relative */
     102  	 0,			/* bitpos */
     103  	 complain_overflow_bitfield,/* complain_on_overflow */
     104  	 bfd_elf_generic_reloc,	/* special_function */
     105  	 "R_CRX_REL4",		/* name */
     106  	 false,			/* partial_inplace */
     107  	 0x0,			/* src_mask */
     108  	 0xf,			/* dst_mask */
     109  	 false),		/* pcrel_offset */
     110  
     111    HOWTO (R_CRX_REL8,		/* type */
     112  	 1,			/* rightshift */
     113  	 1,			/* size */
     114  	 8,			/* bitsize */
     115  	 true,			/* pc_relative */
     116  	 0,			/* bitpos */
     117  	 complain_overflow_bitfield,/* complain_on_overflow */
     118  	 bfd_elf_generic_reloc,	/* special_function */
     119  	 "R_CRX_REL8",		/* name */
     120  	 false,			/* partial_inplace */
     121  	 0x0,			/* src_mask */
     122  	 0xff,			/* dst_mask */
     123  	 false),		/* pcrel_offset */
     124  
     125    HOWTO (R_CRX_REL8_CMP,	/* type */
     126  	 1,			/* rightshift */
     127  	 1,			/* size */
     128  	 8,			/* bitsize */
     129  	 true,			/* pc_relative */
     130  	 0,			/* bitpos */
     131  	 complain_overflow_bitfield,/* complain_on_overflow */
     132  	 bfd_elf_generic_reloc,	/* special_function */
     133  	 "R_CRX_REL8_CMP",	/* name */
     134  	 false,			/* partial_inplace */
     135  	 0x0,			/* src_mask */
     136  	 0xff,			/* dst_mask */
     137  	 false),		/* pcrel_offset */
     138  
     139    HOWTO (R_CRX_REL16,		/* type */
     140  	 1,			/* rightshift */
     141  	 2,			/* size */
     142  	 16,			/* bitsize */
     143  	 true,			/* pc_relative */
     144  	 0,			/* bitpos */
     145  	 complain_overflow_bitfield,/* complain_on_overflow */
     146  	 bfd_elf_generic_reloc,	/* special_function */
     147  	 "R_CRX_REL16",		/* name */
     148  	 false,			/* partial_inplace */
     149  	 0x0,			/* src_mask */
     150  	 0xffff,		/* dst_mask */
     151  	 false),		/* pcrel_offset */
     152  
     153    HOWTO (R_CRX_REL24,		/* type */
     154  	 1,			/* rightshift */
     155  	 4,			/* size */
     156  	 24,			/* bitsize */
     157  	 true,			/* pc_relative */
     158  	 0,			/* bitpos */
     159  	 complain_overflow_bitfield,/* complain_on_overflow */
     160  	 bfd_elf_generic_reloc,	/* special_function */
     161  	 "R_CRX_REL24",		/* name */
     162  	 false,			/* partial_inplace */
     163  	 0x0,			/* src_mask */
     164  	 0xffffff,		/* dst_mask */
     165  	 false),		/* pcrel_offset */
     166  
     167    HOWTO (R_CRX_REL32,		/* type */
     168  	 1,			/* rightshift */
     169  	 4,			/* size */
     170  	 32,			/* bitsize */
     171  	 true,			/* pc_relative */
     172  	 0,			/* bitpos */
     173  	 complain_overflow_bitfield,/* complain_on_overflow */
     174  	 bfd_elf_generic_reloc,	/* special_function */
     175  	 "R_CRX_REL32",		/* name */
     176  	 false,			/* partial_inplace */
     177  	 0x0,			/* src_mask */
     178  	 0xffffffff,		/* dst_mask */
     179  	 false),		/* pcrel_offset */
     180  
     181    HOWTO (R_CRX_REGREL12,	/* type */
     182  	 0,			/* rightshift */
     183  	 2,			/* size */
     184  	 12,			/* bitsize */
     185  	 false,			/* pc_relative */
     186  	 0,			/* bitpos */
     187  	 complain_overflow_bitfield,/* complain_on_overflow */
     188  	 bfd_elf_generic_reloc,	/* special_function */
     189  	 "R_CRX_REGREL12",	/* name */
     190  	 false,			/* partial_inplace */
     191  	 0x0,			/* src_mask */
     192  	 0xfff,			/* dst_mask */
     193  	 false),		/* pcrel_offset */
     194  
     195    HOWTO (R_CRX_REGREL22,	/* type */
     196  	 0,			/* rightshift */
     197  	 4,			/* size */
     198  	 22,			/* bitsize */
     199  	 false,			/* pc_relative */
     200  	 0,			/* bitpos */
     201  	 complain_overflow_bitfield,/* complain_on_overflow */
     202  	 bfd_elf_generic_reloc,	/* special_function */
     203  	 "R_CRX_REGREL22",	/* name */
     204  	 false,			/* partial_inplace */
     205  	 0x0,			/* src_mask */
     206  	 0x3fffff,		/* dst_mask */
     207  	 false),		/* pcrel_offset */
     208  
     209    HOWTO (R_CRX_REGREL28,	/* type */
     210  	 0,			/* rightshift */
     211  	 4,			/* size */
     212  	 28,			/* bitsize */
     213  	 false,			/* pc_relative */
     214  	 0,			/* bitpos */
     215  	 complain_overflow_bitfield,/* complain_on_overflow */
     216  	 bfd_elf_generic_reloc,	/* special_function */
     217  	 "R_CRX_REGREL28",	/* name */
     218  	 false,			/* partial_inplace */
     219  	 0x0,			/* src_mask */
     220  	 0xfffffff,		/* dst_mask */
     221  	 false),		/* pcrel_offset */
     222  
     223    HOWTO (R_CRX_REGREL32,	/* type */
     224  	 0,			/* rightshift */
     225  	 4,			/* size */
     226  	 32,			/* bitsize */
     227  	 false,			/* pc_relative */
     228  	 0,			/* bitpos */
     229  	 complain_overflow_bitfield,/* complain_on_overflow */
     230  	 bfd_elf_generic_reloc,	/* special_function */
     231  	 "R_CRX_REGREL32",	/* name */
     232  	 false,			/* partial_inplace */
     233  	 0x0,			/* src_mask */
     234  	 0xffffffff,		/* dst_mask */
     235  	 false),		/* pcrel_offset */
     236  
     237    HOWTO (R_CRX_ABS16,		/* type */
     238  	 0,			/* rightshift */
     239  	 2,			/* size */
     240  	 16,			/* bitsize */
     241  	 false,			/* pc_relative */
     242  	 0,			/* bitpos */
     243  	 complain_overflow_bitfield,/* complain_on_overflow */
     244  	 bfd_elf_generic_reloc,	/* special_function */
     245  	 "R_CRX_ABS16",		/* name */
     246  	 false,			/* partial_inplace */
     247  	 0x0,			/* src_mask */
     248  	 0xffff,		/* dst_mask */
     249  	 false),		/* pcrel_offset */
     250  
     251    HOWTO (R_CRX_ABS32,		/* type */
     252  	 0,			/* rightshift */
     253  	 4,			/* size */
     254  	 32,			/* bitsize */
     255  	 false,			/* pc_relative */
     256  	 0,			/* bitpos */
     257  	 complain_overflow_bitfield,/* complain_on_overflow */
     258  	 bfd_elf_generic_reloc,	/* special_function */
     259  	 "R_CRX_ABS32",		/* name */
     260  	 false,			/* partial_inplace */
     261  	 0x0,			/* src_mask */
     262  	 0xffffffff,		/* dst_mask */
     263  	 false),		/* pcrel_offset */
     264  
     265    HOWTO (R_CRX_NUM8,		/* type */
     266  	 0,			/* rightshift */
     267  	 1,			/* size */
     268  	 8,			/* bitsize */
     269  	 false,			/* pc_relative */
     270  	 0,			/* bitpos */
     271  	 complain_overflow_bitfield,/* complain_on_overflow */
     272  	 bfd_elf_generic_reloc,	/* special_function */
     273  	 "R_CRX_NUM8",		/* name */
     274  	 false,			/* partial_inplace */
     275  	 0x0,			/* src_mask */
     276  	 0xff,			/* dst_mask */
     277  	 false),		/* pcrel_offset */
     278  
     279    HOWTO (R_CRX_NUM16,		/* type */
     280  	 0,			/* rightshift */
     281  	 2,			/* size */
     282  	 16,			/* bitsize */
     283  	 false,			/* pc_relative */
     284  	 0,			/* bitpos */
     285  	 complain_overflow_bitfield,/* complain_on_overflow */
     286  	 bfd_elf_generic_reloc,	/* special_function */
     287  	 "R_CRX_NUM16",		/* name */
     288  	 false,			/* partial_inplace */
     289  	 0x0,			/* src_mask */
     290  	 0xffff,		/* dst_mask */
     291  	 false),		/* pcrel_offset */
     292  
     293    HOWTO (R_CRX_NUM32,		/* type */
     294  	 0,			/* rightshift */
     295  	 4,			/* size */
     296  	 32,			/* bitsize */
     297  	 false,			/* pc_relative */
     298  	 0,			/* bitpos */
     299  	 complain_overflow_bitfield,/* complain_on_overflow */
     300  	 bfd_elf_generic_reloc,	/* special_function */
     301  	 "R_CRX_NUM32",		/* name */
     302  	 false,			/* partial_inplace */
     303  	 0x0,			/* src_mask */
     304  	 0xffffffff,		/* dst_mask */
     305  	 false),		/* pcrel_offset */
     306  
     307    HOWTO (R_CRX_IMM16,		/* type */
     308  	 0,			/* rightshift */
     309  	 2,			/* size */
     310  	 16,			/* bitsize */
     311  	 false,			/* pc_relative */
     312  	 0,			/* bitpos */
     313  	 complain_overflow_bitfield,/* complain_on_overflow */
     314  	 bfd_elf_generic_reloc,	/* special_function */
     315  	 "R_CRX_IMM16",		/* name */
     316  	 false,			/* partial_inplace */
     317  	 0x0,			/* src_mask */
     318  	 0xffff,		/* dst_mask */
     319  	 false),		/* pcrel_offset */
     320  
     321    HOWTO (R_CRX_IMM32,		/* type */
     322  	 0,			/* rightshift */
     323  	 4,			/* size */
     324  	 32,			/* bitsize */
     325  	 false,			/* pc_relative */
     326  	 0,			/* bitpos */
     327  	 complain_overflow_bitfield,/* complain_on_overflow */
     328  	 bfd_elf_generic_reloc,	/* special_function */
     329  	 "R_CRX_IMM32",		/* name */
     330  	 false,			/* partial_inplace */
     331  	 0x0,			/* src_mask */
     332  	 0xffffffff,		/* dst_mask */
     333  	 false),		/* pcrel_offset */
     334  
     335    /* An 8 bit switch table entry.  This is generated for an expression
     336       such as ``.byte L1 - L2''.  The offset holds the difference
     337       between the reloc address and L2.  */
     338    HOWTO (R_CRX_SWITCH8,		/* type */
     339  	 0,			/* rightshift */
     340  	 1,			/* size */
     341  	 8,			/* bitsize */
     342  	 false,			/* pc_relative */
     343  	 0,			/* bitpos */
     344  	 complain_overflow_unsigned, /* complain_on_overflow */
     345  	 bfd_elf_generic_reloc,	/* special_function */
     346  	 "R_CRX_SWITCH8",	/* name */
     347  	 false,			/* partial_inplace */
     348  	 0x0,			/* src_mask */
     349  	 0xff,			/* dst_mask */
     350  	 true),			/* pcrel_offset */
     351  
     352    /* A 16 bit switch table entry.  This is generated for an expression
     353       such as ``.word L1 - L2''.  The offset holds the difference
     354       between the reloc address and L2.  */
     355    HOWTO (R_CRX_SWITCH16,	/* type */
     356  	 0,			/* rightshift */
     357  	 2,			/* size */
     358  	 16,			/* bitsize */
     359  	 false,			/* pc_relative */
     360  	 0,			/* bitpos */
     361  	 complain_overflow_unsigned, /* complain_on_overflow */
     362  	 bfd_elf_generic_reloc,	/* special_function */
     363  	 "R_CRX_SWITCH16",	/* name */
     364  	 false,			/* partial_inplace */
     365  	 0x0,			/* src_mask */
     366  	 0xffff,		/* dst_mask */
     367  	 true),			/* pcrel_offset */
     368  
     369    /* A 32 bit switch table entry.  This is generated for an expression
     370       such as ``.long L1 - L2''.  The offset holds the difference
     371       between the reloc address and L2.  */
     372    HOWTO (R_CRX_SWITCH32,	/* type */
     373  	 0,			/* rightshift */
     374  	 4,			/* size */
     375  	 32,			/* bitsize */
     376  	 false,			/* pc_relative */
     377  	 0,			/* bitpos */
     378  	 complain_overflow_unsigned, /* complain_on_overflow */
     379  	 bfd_elf_generic_reloc,	/* special_function */
     380  	 "R_CRX_SWITCH32",	/* name */
     381  	 false,			/* partial_inplace */
     382  	 0x0,			/* src_mask */
     383  	 0xffffffff,		/* dst_mask */
     384  	 true)			/* pcrel_offset */
     385  };
     386  
     387  /* Retrieve a howto ptr using a BFD reloc_code.  */
     388  
     389  static reloc_howto_type *
     390  elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     391  			   bfd_reloc_code_real_type code)
     392  {
     393    unsigned int i;
     394  
     395    for (i = 0; i < R_CRX_MAX; i++)
     396      if (code == crx_reloc_map[i].bfd_reloc_enum)
     397        return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type];
     398  
     399    printf ("This relocation Type is not supported -0x%x\n", code);
     400    return 0;
     401  }
     402  
     403  static reloc_howto_type *
     404  elf_crx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     405  			   const char *r_name)
     406  {
     407    unsigned int i;
     408  
     409    for (i = 0;
     410         i < sizeof (crx_elf_howto_table) / sizeof (crx_elf_howto_table[0]);
     411         i++)
     412      if (crx_elf_howto_table[i].name != NULL
     413  	&& strcasecmp (crx_elf_howto_table[i].name, r_name) == 0)
     414        return &crx_elf_howto_table[i];
     415  
     416    return NULL;
     417  }
     418  
     419  /* Retrieve a howto ptr using an internal relocation entry.  */
     420  
     421  static bool
     422  elf_crx_info_to_howto (bfd *abfd, arelent *cache_ptr,
     423  		       Elf_Internal_Rela *dst)
     424  {
     425    unsigned int r_type = ELF32_R_TYPE (dst->r_info);
     426    if (r_type >= R_CRX_MAX)
     427      {
     428        /* xgettext:c-format */
     429        _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
     430  			  abfd, r_type);
     431        bfd_set_error (bfd_error_bad_value);
     432        return false;
     433      }
     434    cache_ptr->howto = &crx_elf_howto_table[r_type];
     435    return true;
     436  }
     437  
     438  /* Perform a relocation as part of a final link.  */
     439  
     440  static bfd_reloc_status_type
     441  crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
     442  			     bfd *output_bfd ATTRIBUTE_UNUSED,
     443  			     asection *input_section, bfd_byte *contents,
     444  			     bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
     445  			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
     446  			     asection *sec ATTRIBUTE_UNUSED,
     447  			     int is_local ATTRIBUTE_UNUSED)
     448  {
     449    unsigned short r_type = howto->type;
     450    bfd_byte *hit_data = contents + offset;
     451    bfd_vma reloc_bits, check;
     452  
     453    switch (r_type)
     454      {
     455       case R_CRX_IMM16:
     456       case R_CRX_IMM32:
     457       case R_CRX_ABS16:
     458       case R_CRX_ABS32:
     459       case R_CRX_REL8_CMP:
     460       case R_CRX_REL16:
     461       case R_CRX_REL24:
     462       case R_CRX_REL32:
     463       case R_CRX_REGREL12:
     464       case R_CRX_REGREL22:
     465       case R_CRX_REGREL28:
     466       case R_CRX_REGREL32:
     467         /* 'hit_data' is relative to the start of the instruction, not the
     468  	  relocation offset. Advance it to account for the exact offset.  */
     469         hit_data += 2;
     470         break;
     471  
     472       case R_CRX_REL4:
     473         /* This relocation type is used only in 'Branch if Equal to 0'
     474  	  instructions and requires special handling.  */
     475         Rvalue -= 1;
     476         break;
     477  
     478       case R_CRX_NONE:
     479         return bfd_reloc_ok;
     480         break;
     481  
     482       case R_CRX_SWITCH8:
     483       case R_CRX_SWITCH16:
     484       case R_CRX_SWITCH32:
     485         /* We only care about the addend, where the difference between
     486  	  expressions is kept.  */
     487         Rvalue = 0;
     488  
     489       default:
     490         break;
     491      }
     492  
     493    if (howto->pc_relative)
     494      {
     495        /* Subtract the address of the section containing the location.  */
     496        Rvalue -= (input_section->output_section->vma
     497  		 + input_section->output_offset);
     498        /* Subtract the position of the location within the section.  */
     499        Rvalue -= offset;
     500      }
     501  
     502    /* Add in supplied addend.  */
     503    Rvalue += addend;
     504  
     505    /* Complain if the bitfield overflows, whether it is considered
     506       as signed or unsigned.  */
     507    check = Rvalue >> howto->rightshift;
     508  
     509    reloc_bits = ((bfd_vma) 1 << (howto->bitsize - 1) << 1) - 1;
     510  
     511    if ((check & ~reloc_bits) != 0
     512        && (check & ~reloc_bits) != ((bfd_vma) -1 & ~reloc_bits))
     513      {
     514        /* The above right shift is incorrect for a signed
     515  	 value.  See if turning on the upper bits fixes the
     516  	 overflow.  */
     517        if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
     518  	{
     519  	  check |= (bfd_vma) -1 & ~((bfd_vma) -1 >> howto->rightshift);
     520  	  if ((check & ~reloc_bits) != ((bfd_vma) -1 & ~reloc_bits))
     521  	    return bfd_reloc_overflow;
     522  	}
     523        else
     524  	return bfd_reloc_overflow;
     525      }
     526  
     527    /* Drop unwanted bits from the value we are relocating to.  */
     528    Rvalue >>= howto->rightshift;
     529  
     530    /* Apply dst_mask to select only relocatable part of the insn.  */
     531    Rvalue &= howto->dst_mask;
     532  
     533    switch (bfd_get_reloc_size (howto))
     534      {
     535       case 1:
     536         if (r_type == R_CRX_REL4)
     537  	 {
     538  	   Rvalue <<= 4;
     539  	   Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
     540  	 }
     541  
     542         bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
     543         break;
     544  
     545       case 2:
     546         if (r_type == R_CRX_REGREL12)
     547  	 Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
     548  
     549         bfd_put_16 (input_bfd, Rvalue, hit_data);
     550         break;
     551  
     552       case 4:
     553         if (r_type == R_CRX_REL24
     554  	   || r_type == R_CRX_REGREL22
     555  	   || r_type == R_CRX_REGREL28)
     556  	 Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
     557  		      bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
     558  
     559         if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32)
     560  	 /* Relocation on DATA is purely little-endian, that is, for a
     561  	    multi-byte datum, the lowest address in memory contains the
     562  	    little end of the datum, that is, the least significant byte.
     563  	    Therefore we use BFD's byte Putting functions.  */
     564  	 bfd_put_32 (input_bfd, Rvalue, hit_data);
     565         else
     566  	 /* Relocation on INSTRUCTIONS is different : Instructions are
     567  	    word-addressable, that is, each word itself is arranged according
     568  	    to little-endian convention, whereas the words are arranged with
     569  	    respect to one another in BIG ENDIAN fashion.
     570  	    When there is an immediate value that spans a word boundary, it is
     571  	    split in a big-endian way with respect to the words.  */
     572  	 {
     573  	   bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
     574  	   bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
     575  	 }
     576       break;
     577  
     578       default:
     579         return bfd_reloc_notsupported;
     580      }
     581  
     582    return bfd_reloc_ok;
     583  }
     584  
     585  /* Delete some bytes from a section while relaxing.  */
     586  
     587  static bool
     588  elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
     589  			      asection *sec, bfd_vma addr, int count)
     590  {
     591    Elf_Internal_Shdr *symtab_hdr;
     592    unsigned int sec_shndx;
     593    bfd_byte *contents;
     594    Elf_Internal_Rela *irel, *irelend;
     595    bfd_vma toaddr;
     596    Elf_Internal_Sym *isym;
     597    Elf_Internal_Sym *isymend;
     598    struct elf_link_hash_entry **sym_hashes;
     599    struct elf_link_hash_entry **end_hashes;
     600    struct elf_link_hash_entry **start_hashes;
     601    unsigned int symcount;
     602  
     603    sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
     604  
     605    contents = elf_section_data (sec)->this_hdr.contents;
     606  
     607    toaddr = sec->size;
     608  
     609    irel = elf_section_data (sec)->relocs;
     610    irelend = irel + sec->reloc_count;
     611  
     612    /* Actually delete the bytes.  */
     613    memmove (contents + addr, contents + addr + count,
     614  	   (size_t) (toaddr - addr - count));
     615    sec->size -= count;
     616  
     617    /* Adjust all the relocs.  */
     618    for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
     619      {
     620        /* Get the new reloc address.  */
     621        if ((irel->r_offset > addr
     622  	   && irel->r_offset < toaddr))
     623  	irel->r_offset -= count;
     624      }
     625  
     626    /* Adjust the local symbols defined in this section.  */
     627    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
     628    isym = (Elf_Internal_Sym *) symtab_hdr->contents;
     629    for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
     630      {
     631        if (isym->st_shndx == sec_shndx
     632  	  && isym->st_value > addr
     633  	  && isym->st_value < toaddr)
     634  	{
     635  	  /* Adjust the addend of SWITCH relocations in this section,
     636  	     which reference this local symbol.  */
     637  	  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
     638  	    {
     639  	      unsigned long r_symndx;
     640  	      Elf_Internal_Sym *rsym;
     641  	      bfd_vma addsym, subsym;
     642  
     643  	      /* Skip if not a SWITCH relocation.  */
     644  	      if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
     645  		  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
     646  		  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
     647  		  continue;
     648  
     649  	      r_symndx = ELF32_R_SYM (irel->r_info);
     650  	      rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
     651  
     652  	      /* Skip if not the local adjusted symbol.  */
     653  	      if (rsym != isym)
     654  		continue;
     655  
     656  	      addsym = isym->st_value;
     657  	      subsym = addsym - irel->r_addend;
     658  
     659  	      /* Fix the addend only when -->> (addsym > addr >= subsym).  */
     660  	      if (subsym <= addr)
     661  		irel->r_addend -= count;
     662  	      else
     663  		continue;
     664  	    }
     665  
     666  	  isym->st_value -= count;
     667  	}
     668      }
     669  
     670    /* Now adjust the global symbols defined in this section.  */
     671    symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
     672  	      - symtab_hdr->sh_info);
     673    sym_hashes = start_hashes = elf_sym_hashes (abfd);
     674    end_hashes = sym_hashes + symcount;
     675  
     676    for (; sym_hashes < end_hashes; sym_hashes++)
     677      {
     678        struct elf_link_hash_entry *sym_hash = *sym_hashes;
     679  
     680        /* The '--wrap SYMBOL' option is causing a pain when the object file,
     681  	 containing the definition of __wrap_SYMBOL, includes a direct
     682  	 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
     683  	 the same symbol (which is __wrap_SYMBOL), but still exist as two
     684  	 different symbols in 'sym_hashes', we don't want to adjust
     685  	 the global symbol __wrap_SYMBOL twice.
     686  	 This check is only relevant when symbols are being wrapped.  */
     687        if (link_info->wrap_hash != NULL)
     688  	{
     689  	  struct elf_link_hash_entry **cur_sym_hashes;
     690  
     691  	  /* Loop only over the symbols whom been already checked.  */
     692  	  for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
     693  	       cur_sym_hashes++)
     694  	    {
     695  	      /* If the current symbol is identical to 'sym_hash', that means
     696  		 the symbol was already adjusted (or at least checked).  */
     697  	      if (*cur_sym_hashes == sym_hash)
     698  		break;
     699  	    }
     700  	  /* Don't adjust the symbol again.  */
     701  	  if (cur_sym_hashes < sym_hashes)
     702  	    continue;
     703  	}
     704  
     705        if ((sym_hash->root.type == bfd_link_hash_defined
     706  	   || sym_hash->root.type == bfd_link_hash_defweak)
     707  	  && sym_hash->root.u.def.section == sec
     708  	  && sym_hash->root.u.def.value > addr
     709  	  && sym_hash->root.u.def.value < toaddr)
     710  	sym_hash->root.u.def.value -= count;
     711      }
     712  
     713    return true;
     714  }
     715  
     716  /* This is a version of bfd_generic_get_relocated_section_contents
     717     which uses elf32_crx_relocate_section.  */
     718  
     719  static bfd_byte *
     720  elf32_crx_get_relocated_section_contents (bfd *output_bfd,
     721  					  struct bfd_link_info *link_info,
     722  					  struct bfd_link_order *link_order,
     723  					  bfd_byte *data,
     724  					  bool relocatable,
     725  					  asymbol **symbols)
     726  {
     727    Elf_Internal_Shdr *symtab_hdr;
     728    asection *input_section = link_order->u.indirect.section;
     729    bfd *input_bfd = input_section->owner;
     730    asection **sections = NULL;
     731    Elf_Internal_Rela *internal_relocs = NULL;
     732    Elf_Internal_Sym *isymbuf = NULL;
     733  
     734    /* We only need to handle the case of relaxing, or of having a
     735       particular set of section contents, specially.  */
     736    if (relocatable
     737        || elf_section_data (input_section)->this_hdr.contents == NULL)
     738      return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
     739  						       link_order, data,
     740  						       relocatable,
     741  						       symbols);
     742  
     743    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
     744  
     745    bfd_byte *orig_data = data;
     746    if (data == NULL)
     747      {
     748        data = bfd_malloc (input_section->size);
     749        if (data == NULL)
     750  	return NULL;
     751      }
     752    memcpy (data, elf_section_data (input_section)->this_hdr.contents,
     753  	  (size_t) input_section->size);
     754  
     755    if ((input_section->flags & SEC_RELOC) != 0
     756        && input_section->reloc_count > 0)
     757      {
     758        Elf_Internal_Sym *isym;
     759        Elf_Internal_Sym *isymend;
     760        asection **secpp;
     761        bfd_size_type amt;
     762  
     763        internal_relocs = (_bfd_elf_link_read_relocs
     764  			 (input_bfd, input_section, NULL,
     765  			  (Elf_Internal_Rela *) NULL, false));
     766        if (internal_relocs == NULL)
     767  	goto error_return;
     768  
     769        if (symtab_hdr->sh_info != 0)
     770  	{
     771  	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
     772  	  if (isymbuf == NULL)
     773  	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
     774  					    symtab_hdr->sh_info, 0,
     775  					    NULL, NULL, NULL);
     776  	  if (isymbuf == NULL)
     777  	    goto error_return;
     778  	}
     779  
     780        amt = symtab_hdr->sh_info;
     781        amt *= sizeof (asection *);
     782        sections = bfd_malloc (amt);
     783        if (sections == NULL && amt != 0)
     784  	goto error_return;
     785  
     786        isymend = isymbuf + symtab_hdr->sh_info;
     787        for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
     788  	{
     789  	  asection *isec;
     790  
     791  	  if (isym->st_shndx == SHN_UNDEF)
     792  	    isec = bfd_und_section_ptr;
     793  	  else if (isym->st_shndx == SHN_ABS)
     794  	    isec = bfd_abs_section_ptr;
     795  	  else if (isym->st_shndx == SHN_COMMON)
     796  	    isec = bfd_com_section_ptr;
     797  	  else
     798  	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
     799  
     800  	  *secpp = isec;
     801  	}
     802  
     803        if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
     804  				     input_section, data, internal_relocs,
     805  				     isymbuf, sections))
     806  	goto error_return;
     807  
     808        free (sections);
     809        if (symtab_hdr->contents != (unsigned char *) isymbuf)
     810  	free (isymbuf);
     811        if (elf_section_data (input_section)->relocs != internal_relocs)
     812  	free (internal_relocs);
     813      }
     814  
     815    return data;
     816  
     817   error_return:
     818    free (sections);
     819    if (symtab_hdr->contents != (unsigned char *) isymbuf)
     820      free (isymbuf);
     821    if (elf_section_data (input_section)->relocs != internal_relocs)
     822      free (internal_relocs);
     823    if (orig_data == NULL)
     824      free (data);
     825    return NULL;
     826  }
     827  
     828  /* Relocate a CRX ELF section.  */
     829  
     830  static int
     831  elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
     832  			    bfd *input_bfd, asection *input_section,
     833  			    bfd_byte *contents, Elf_Internal_Rela *relocs,
     834  			    Elf_Internal_Sym *local_syms,
     835  			    asection **local_sections)
     836  {
     837    Elf_Internal_Shdr *symtab_hdr;
     838    struct elf_link_hash_entry **sym_hashes;
     839    Elf_Internal_Rela *rel, *relend;
     840  
     841    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
     842    sym_hashes = elf_sym_hashes (input_bfd);
     843  
     844    rel = relocs;
     845    relend = relocs + input_section->reloc_count;
     846    for (; rel < relend; rel++)
     847      {
     848        int r_type;
     849        reloc_howto_type *howto;
     850        unsigned long r_symndx;
     851        Elf_Internal_Sym *sym;
     852        asection *sec;
     853        struct elf_link_hash_entry *h;
     854        bfd_vma relocation;
     855        bfd_reloc_status_type r;
     856  
     857        r_symndx = ELF32_R_SYM (rel->r_info);
     858        r_type = ELF32_R_TYPE (rel->r_info);
     859        howto = crx_elf_howto_table + (r_type);
     860  
     861        h = NULL;
     862        sym = NULL;
     863        sec = NULL;
     864        if (r_symndx < symtab_hdr->sh_info)
     865  	{
     866  	  sym = local_syms + r_symndx;
     867  	  sec = local_sections[r_symndx];
     868  	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
     869  	}
     870        else
     871  	{
     872  	  bool unresolved_reloc, warned, ignored;
     873  
     874  	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
     875  				   r_symndx, symtab_hdr, sym_hashes,
     876  				   h, sec, relocation,
     877  				   unresolved_reloc, warned, ignored);
     878  	}
     879  
     880        if (sec != NULL && discarded_section (sec))
     881  	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
     882  					 rel, 1, relend, howto, 0, contents);
     883  
     884        if (bfd_link_relocatable (info))
     885  	continue;
     886  
     887        r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
     888  					input_section,
     889  					contents, rel->r_offset,
     890  					relocation, rel->r_addend,
     891  					info, sec, h == NULL);
     892  
     893        if (r != bfd_reloc_ok)
     894  	{
     895  	  const char *name;
     896  	  const char *msg = (const char *) 0;
     897  
     898  	  if (h != NULL)
     899  	    name = h->root.root.string;
     900  	  else
     901  	    {
     902  	      name = (bfd_elf_string_from_elf_section
     903  		      (input_bfd, symtab_hdr->sh_link, sym->st_name));
     904  	      if (name == NULL || *name == '\0')
     905  		name = bfd_section_name (sec);
     906  	    }
     907  
     908  	  switch (r)
     909  	    {
     910  	     case bfd_reloc_overflow:
     911  	       (*info->callbacks->reloc_overflow)
     912  		 (info, (h ? &h->root : NULL), name, howto->name,
     913  		  (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
     914  	       break;
     915  
     916  	     case bfd_reloc_undefined:
     917  	       (*info->callbacks->undefined_symbol)
     918  		 (info, name, input_bfd, input_section, rel->r_offset, true);
     919  	       break;
     920  
     921  	     case bfd_reloc_outofrange:
     922  	       msg = _("internal error: out of range error");
     923  	       goto common_error;
     924  
     925  	     case bfd_reloc_notsupported:
     926  	       msg = _("internal error: unsupported relocation error");
     927  	       goto common_error;
     928  
     929  	     case bfd_reloc_dangerous:
     930  	       msg = _("internal error: dangerous error");
     931  	       goto common_error;
     932  
     933  	     default:
     934  	       msg = _("internal error: unknown error");
     935  	       /* Fall through.  */
     936  
     937  	     common_error:
     938  	       (*info->callbacks->warning) (info, msg, name, input_bfd,
     939  					    input_section, rel->r_offset);
     940  	       break;
     941  	    }
     942  	}
     943      }
     944  
     945    return true;
     946  }
     947  
     948  /* This function handles relaxing for the CRX.
     949  
     950     There's quite a few relaxing opportunites available on the CRX:
     951  
     952  	* bal/bcond:32 -> bal/bcond:16				   2 bytes
     953  	* bcond:16 -> bcond:8					   2 bytes
     954  	* cmpbcond:24 -> cmpbcond:8				   2 bytes
     955  	* arithmetic imm32 -> arithmetic imm16			   2 bytes
     956  
     957     Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
     958  
     959  static bool
     960  elf32_crx_relax_section (bfd *abfd, asection *sec,
     961  			 struct bfd_link_info *link_info, bool *again)
     962  {
     963    Elf_Internal_Shdr *symtab_hdr;
     964    Elf_Internal_Rela *internal_relocs;
     965    Elf_Internal_Rela *irel, *irelend;
     966    bfd_byte *contents = NULL;
     967    Elf_Internal_Sym *isymbuf = NULL;
     968  
     969    /* Assume nothing changes.  */
     970    *again = false;
     971  
     972    /* We don't have to do anything for a relocatable link, if
     973       this section does not have relocs, or if this is not a
     974       code section.  */
     975    if (bfd_link_relocatable (link_info)
     976        || sec->reloc_count == 0
     977        || (sec->flags & SEC_RELOC) == 0
     978        || (sec->flags & SEC_HAS_CONTENTS) == 0
     979        || (sec->flags & SEC_CODE) == 0)
     980      return true;
     981  
     982    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
     983  
     984    /* Get a copy of the native relocations.  */
     985    internal_relocs = (_bfd_elf_link_read_relocs
     986  		     (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
     987  		      link_info->keep_memory));
     988    if (internal_relocs == NULL)
     989      goto error_return;
     990  
     991    /* Walk through them looking for relaxing opportunities.  */
     992    irelend = internal_relocs + sec->reloc_count;
     993    for (irel = internal_relocs; irel < irelend; irel++)
     994      {
     995        bfd_vma symval;
     996  
     997        /* If this isn't something that can be relaxed, then ignore
     998  	 this reloc.  */
     999        if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
    1000  	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
    1001  	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
    1002  	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
    1003  	continue;
    1004  
    1005        /* Get the section contents if we haven't done so already.  */
    1006        if (contents == NULL)
    1007  	{
    1008  	  /* Get cached copy if it exists.  */
    1009  	  if (elf_section_data (sec)->this_hdr.contents != NULL)
    1010  	    contents = elf_section_data (sec)->this_hdr.contents;
    1011  	  /* Go get them off disk.  */
    1012  	  else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
    1013  	    goto error_return;
    1014  	}
    1015  
    1016        /* Read this BFD's local symbols if we haven't done so already.  */
    1017        if (isymbuf == NULL && symtab_hdr->sh_info != 0)
    1018  	{
    1019  	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
    1020  	  if (isymbuf == NULL)
    1021  	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
    1022  					    symtab_hdr->sh_info, 0,
    1023  					    NULL, NULL, NULL);
    1024  	  if (isymbuf == NULL)
    1025  	    goto error_return;
    1026  	}
    1027  
    1028        /* Get the value of the symbol referred to by the reloc.  */
    1029        if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
    1030  	{
    1031  	  /* A local symbol.  */
    1032  	  Elf_Internal_Sym *isym;
    1033  	  asection *sym_sec;
    1034  
    1035  	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
    1036  	  if (isym->st_shndx == SHN_UNDEF)
    1037  	    sym_sec = bfd_und_section_ptr;
    1038  	  else if (isym->st_shndx == SHN_ABS)
    1039  	    sym_sec = bfd_abs_section_ptr;
    1040  	  else if (isym->st_shndx == SHN_COMMON)
    1041  	    sym_sec = bfd_com_section_ptr;
    1042  	  else
    1043  	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
    1044  	  symval = (isym->st_value
    1045  		    + sym_sec->output_section->vma
    1046  		    + sym_sec->output_offset);
    1047  	}
    1048        else
    1049  	{
    1050  	  unsigned long indx;
    1051  	  struct elf_link_hash_entry *h;
    1052  
    1053  	  /* An external symbol.  */
    1054  	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
    1055  	  h = elf_sym_hashes (abfd)[indx];
    1056  	  BFD_ASSERT (h != NULL);
    1057  
    1058  	  if (h->root.type != bfd_link_hash_defined
    1059  	      && h->root.type != bfd_link_hash_defweak)
    1060  	    /* This appears to be a reference to an undefined
    1061  	       symbol.  Just ignore it--it will be caught by the
    1062  	       regular reloc processing.  */
    1063  	    continue;
    1064  
    1065  	  symval = (h->root.u.def.value
    1066  		    + h->root.u.def.section->output_section->vma
    1067  		    + h->root.u.def.section->output_offset);
    1068  	}
    1069  
    1070        /* For simplicity of coding, we are going to modify the section
    1071  	 contents, the section relocs, and the BFD symbol table.  We
    1072  	 must tell the rest of the code not to free up this
    1073  	 information.  It would be possible to instead create a table
    1074  	 of changes which have to be made, as is done in coff-mips.c;
    1075  	 that would be more work, but would require less memory when
    1076  	 the linker is run.  */
    1077  
    1078        /* Try to turn a 32bit pc-relative branch/call into
    1079  	 a 16bit pc-relative branch/call.  */
    1080        if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
    1081  	{
    1082  	  bfd_vma value = symval;
    1083  
    1084  	  /* Deal with pc-relative gunk.  */
    1085  	  value -= (sec->output_section->vma + sec->output_offset);
    1086  	  value -= irel->r_offset;
    1087  	  value += irel->r_addend;
    1088  
    1089  	  /* See if the value will fit in 16 bits, note the high value is
    1090  	     0xfffe + 2 as the target will be two bytes closer if we are
    1091  	     able to relax.  */
    1092  	  if ((long) value < 0x10000 && (long) value > -0x10002)
    1093  	    {
    1094  	      unsigned short code;
    1095  
    1096  	      /* Get the opcode.  */
    1097  	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
    1098  
    1099  	      /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
    1100  	      if ((code & 0xfff0) == 0x3170)
    1101  		bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
    1102  	      else if ((code & 0xf0ff) == 0x707f)
    1103  		bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
    1104  	      else
    1105  		continue;
    1106  
    1107  	      /* Note that we've changed the relocs, section contents, etc.  */
    1108  	      elf_section_data (sec)->relocs = internal_relocs;
    1109  	      elf_section_data (sec)->this_hdr.contents = contents;
    1110  	      symtab_hdr->contents = (unsigned char *) isymbuf;
    1111  
    1112  	      /* Fix the relocation's type.  */
    1113  	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
    1114  					   R_CRX_REL16);
    1115  
    1116  	      /* Delete two bytes of data.  */
    1117  	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
    1118  						   irel->r_offset + 2, 2))
    1119  		goto error_return;
    1120  
    1121  	      /* That will change things, so, we should relax again.
    1122  		 Note that this is not required, and it may be slow.  */
    1123  	      *again = true;
    1124  	    }
    1125  	}
    1126  
    1127        /* Try to turn a 16bit pc-relative branch into an
    1128  	 8bit pc-relative branch.  */
    1129        if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
    1130  	{
    1131  	  bfd_vma value = symval;
    1132  
    1133  	  /* Deal with pc-relative gunk.  */
    1134  	  value -= (sec->output_section->vma + sec->output_offset);
    1135  	  value -= irel->r_offset;
    1136  	  value += irel->r_addend;
    1137  
    1138  	  /* See if the value will fit in 8 bits, note the high value is
    1139  	     0xfc + 2 as the target will be two bytes closer if we are
    1140  	     able to relax.  */
    1141  	  if ((long) value < 0xfe && (long) value > -0x100)
    1142  	    {
    1143  	      unsigned short code;
    1144  
    1145  	      /* Get the opcode.  */
    1146  	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
    1147  
    1148  	      /* Verify it's a 'bcond' opcode.  */
    1149  	      if ((code & 0xf0ff) != 0x707e)
    1150  		continue;
    1151  
    1152  	      /* Note that we've changed the relocs, section contents, etc.  */
    1153  	      elf_section_data (sec)->relocs = internal_relocs;
    1154  	      elf_section_data (sec)->this_hdr.contents = contents;
    1155  	      symtab_hdr->contents = (unsigned char *) isymbuf;
    1156  
    1157  	      /* Fix the relocation's type.  */
    1158  	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
    1159  					   R_CRX_REL8);
    1160  
    1161  	      /* Delete two bytes of data.  */
    1162  	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
    1163  						   irel->r_offset + 2, 2))
    1164  		goto error_return;
    1165  
    1166  	      /* That will change things, so, we should relax again.
    1167  		 Note that this is not required, and it may be slow.  */
    1168  	      *again = true;
    1169  	    }
    1170  	}
    1171  
    1172        /* Try to turn a 24bit pc-relative cmp&branch into
    1173  	 an 8bit pc-relative cmp&branch.  */
    1174        if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
    1175  	{
    1176  	  bfd_vma value = symval;
    1177  
    1178  	  /* Deal with pc-relative gunk.  */
    1179  	  value -= (sec->output_section->vma + sec->output_offset);
    1180  	  value -= irel->r_offset;
    1181  	  value += irel->r_addend;
    1182  
    1183  	  /* See if the value will fit in 8 bits, note the high value is
    1184  	     0x7e + 2 as the target will be two bytes closer if we are
    1185  	     able to relax.  */
    1186  	  if ((long) value < 0x100 && (long) value > -0x100)
    1187  	    {
    1188  	      unsigned short code;
    1189  
    1190  	      /* Get the opcode.  */
    1191  	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
    1192  
    1193  	      /* Verify it's a 'cmp&branch' opcode.  */
    1194  	      if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
    1195  	       && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
    1196  	       && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
    1197  	       /* Or a Co-processor branch ('bcop').  */
    1198  	       && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
    1199  		continue;
    1200  
    1201  	      /* Note that we've changed the relocs, section contents, etc.  */
    1202  	      elf_section_data (sec)->relocs = internal_relocs;
    1203  	      elf_section_data (sec)->this_hdr.contents = contents;
    1204  	      symtab_hdr->contents = (unsigned char *) isymbuf;
    1205  
    1206  	      /* Fix the opcode.  */
    1207  	      bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
    1208  
    1209  	      /* Fix the relocation's type.  */
    1210  	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
    1211  					   R_CRX_REL8_CMP);
    1212  
    1213  	      /* Delete two bytes of data.  */
    1214  	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
    1215  						   irel->r_offset + 4, 2))
    1216  		goto error_return;
    1217  
    1218  	      /* That will change things, so, we should relax again.
    1219  		 Note that this is not required, and it may be slow.  */
    1220  	      *again = true;
    1221  	    }
    1222  	}
    1223  
    1224        /* Try to turn a 32bit immediate address into
    1225  	 a 16bit immediate address.  */
    1226        if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
    1227  	{
    1228  	  bfd_vma value = symval;
    1229  
    1230  	  /* See if the value will fit in 16 bits.  */
    1231  	  if ((long) value < 0x7fff && (long) value > -0x8000)
    1232  	    {
    1233  	      unsigned short code;
    1234  
    1235  	      /* Get the opcode.  */
    1236  	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
    1237  
    1238  	      /* Verify it's a 'arithmetic double'.  */
    1239  	      if ((code & 0xf0f0) != 0x20f0)
    1240  		continue;
    1241  
    1242  	      /* Note that we've changed the relocs, section contents, etc.  */
    1243  	      elf_section_data (sec)->relocs = internal_relocs;
    1244  	      elf_section_data (sec)->this_hdr.contents = contents;
    1245  	      symtab_hdr->contents = (unsigned char *) isymbuf;
    1246  
    1247  	      /* Fix the opcode.  */
    1248  	      bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
    1249  
    1250  	      /* Fix the relocation's type.  */
    1251  	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
    1252  					   R_CRX_IMM16);
    1253  
    1254  	      /* Delete two bytes of data.  */
    1255  	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
    1256  						   irel->r_offset + 2, 2))
    1257  		goto error_return;
    1258  
    1259  	      /* That will change things, so, we should relax again.
    1260  		 Note that this is not required, and it may be slow.  */
    1261  	      *again = true;
    1262  	    }
    1263  	}
    1264      }
    1265  
    1266    if (isymbuf != NULL
    1267        && symtab_hdr->contents != (unsigned char *) isymbuf)
    1268      {
    1269        if (! link_info->keep_memory)
    1270  	free (isymbuf);
    1271        else
    1272  	{
    1273  	  /* Cache the symbols for elf_link_input_bfd.  */
    1274  	  symtab_hdr->contents = (unsigned char *) isymbuf;
    1275  	}
    1276      }
    1277  
    1278    if (contents != NULL
    1279        && elf_section_data (sec)->this_hdr.contents != contents)
    1280      {
    1281        if (! link_info->keep_memory)
    1282  	free (contents);
    1283        else
    1284  	{
    1285  	  /* Cache the section contents for elf_link_input_bfd.  */
    1286  	  elf_section_data (sec)->this_hdr.contents = contents;
    1287  	}
    1288      }
    1289  
    1290    if (elf_section_data (sec)->relocs != internal_relocs)
    1291      free (internal_relocs);
    1292  
    1293    return true;
    1294  
    1295   error_return:
    1296    if (symtab_hdr->contents != (unsigned char *) isymbuf)
    1297      free (isymbuf);
    1298    if (elf_section_data (sec)->this_hdr.contents != contents)
    1299      free (contents);
    1300    if (elf_section_data (sec)->relocs != internal_relocs)
    1301      free (internal_relocs);
    1302  
    1303    return false;
    1304  }
    1305  
    1306  /* Definitions for setting CRX target vector.  */
    1307  #define TARGET_LITTLE_SYM		crx_elf32_vec
    1308  #define TARGET_LITTLE_NAME		"elf32-crx"
    1309  #define ELF_ARCH			bfd_arch_crx
    1310  #define ELF_MACHINE_CODE		EM_CRX
    1311  #define ELF_MAXPAGESIZE			0x1
    1312  #define elf_symbol_leading_char		'_'
    1313  
    1314  #define bfd_elf32_bfd_reloc_type_lookup	elf_crx_reloc_type_lookup
    1315  #define bfd_elf32_bfd_reloc_name_lookup \
    1316  					elf_crx_reloc_name_lookup
    1317  #define elf_info_to_howto		elf_crx_info_to_howto
    1318  #define elf_info_to_howto_rel		NULL
    1319  #define elf_backend_relocate_section	elf32_crx_relocate_section
    1320  #define bfd_elf32_bfd_relax_section	elf32_crx_relax_section
    1321  #define bfd_elf32_bfd_get_relocated_section_contents \
    1322  				elf32_crx_get_relocated_section_contents
    1323  #define elf_backend_can_gc_sections     1
    1324  #define elf_backend_rela_normal		1
    1325  
    1326  #include "elf32-target.h"