Back to index

cell-binutils  2.17cvs20070401
elf32-crx.c
Go to the documentation of this file.
00001 /* BFD back-end for National Semiconductor's CRX ELF
00002    Copyright 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
00003    Written by Tomer Levi, NSC, Israel.
00004 
00005    This file is part of BFD, the Binary File Descriptor library.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #include "bfd.h"
00022 #include "sysdep.h"
00023 #include "bfdlink.h"
00024 #include "libbfd.h"
00025 #include "elf-bfd.h"
00026 #include "elf/crx.h"
00027 
00028 static reloc_howto_type *elf_crx_reloc_type_lookup
00029   (bfd *, bfd_reloc_code_real_type);
00030 static void elf_crx_info_to_howto
00031   (bfd *, arelent *, Elf_Internal_Rela *);
00032 static bfd_boolean elf32_crx_relax_delete_bytes
00033   (struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
00034 static bfd_reloc_status_type crx_elf_final_link_relocate
00035   (reloc_howto_type *, bfd *, bfd *, asection *,
00036    bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
00037    struct bfd_link_info *, asection *, int);
00038 static bfd_boolean elf32_crx_relocate_section
00039   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00040    Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
00041 static bfd_boolean elf32_crx_relax_section
00042   (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
00043 static bfd_byte * elf32_crx_get_relocated_section_contents
00044   (bfd *, struct bfd_link_info *, struct bfd_link_order *,
00045    bfd_byte *, bfd_boolean, asymbol **);
00046 
00047 /* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
00048 
00049 struct crx_reloc_map
00050 {
00051   bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
00052   unsigned short crx_reloc_type;      /* CRX relocation type.  */
00053 };
00054 
00055 static const struct crx_reloc_map crx_reloc_map[R_CRX_MAX] =
00056 {
00057   {BFD_RELOC_NONE,       R_CRX_NONE},
00058   {BFD_RELOC_CRX_REL4,          R_CRX_REL4},
00059   {BFD_RELOC_CRX_REL8,          R_CRX_REL8},
00060   {BFD_RELOC_CRX_REL8_CMP,  R_CRX_REL8_CMP},
00061   {BFD_RELOC_CRX_REL16,         R_CRX_REL16},
00062   {BFD_RELOC_CRX_REL24,         R_CRX_REL24},
00063   {BFD_RELOC_CRX_REL32,         R_CRX_REL32},
00064   {BFD_RELOC_CRX_REGREL12,  R_CRX_REGREL12},
00065   {BFD_RELOC_CRX_REGREL22,  R_CRX_REGREL22},
00066   {BFD_RELOC_CRX_REGREL28,  R_CRX_REGREL28},
00067   {BFD_RELOC_CRX_REGREL32,  R_CRX_REGREL32},
00068   {BFD_RELOC_CRX_ABS16,         R_CRX_ABS16},
00069   {BFD_RELOC_CRX_ABS32,         R_CRX_ABS32},
00070   {BFD_RELOC_CRX_NUM8,          R_CRX_NUM8},
00071   {BFD_RELOC_CRX_NUM16,         R_CRX_NUM16},
00072   {BFD_RELOC_CRX_NUM32,         R_CRX_NUM32},
00073   {BFD_RELOC_CRX_IMM16,         R_CRX_IMM16},
00074   {BFD_RELOC_CRX_IMM32,         R_CRX_IMM32},
00075   {BFD_RELOC_CRX_SWITCH8,   R_CRX_SWITCH8},
00076   {BFD_RELOC_CRX_SWITCH16,  R_CRX_SWITCH16},
00077   {BFD_RELOC_CRX_SWITCH32,  R_CRX_SWITCH32}
00078 };
00079 
00080 static reloc_howto_type crx_elf_howto_table[] =
00081 {
00082   HOWTO (R_CRX_NONE,        /* type */
00083         0,                  /* rightshift */
00084         2,                  /* size */
00085         32,                 /* bitsize */
00086         FALSE,                     /* pc_relative */
00087         0,                  /* bitpos */
00088         complain_overflow_dont,/* complain_on_overflow */
00089         bfd_elf_generic_reloc,     /* special_function */
00090         "R_CRX_NONE",              /* name */
00091         FALSE,                     /* partial_inplace */
00092         0,                  /* src_mask */
00093         0,                  /* dst_mask */
00094         FALSE),             /* pcrel_offset */
00095 
00096   HOWTO (R_CRX_REL4,        /* type */
00097         1,                  /* rightshift */
00098         0,                  /* size */
00099         4,                  /* bitsize */
00100         TRUE,               /* pc_relative */
00101         0,                  /* bitpos */
00102         complain_overflow_bitfield,/* complain_on_overflow */
00103         bfd_elf_generic_reloc,     /* special_function */
00104         "R_CRX_REL4",              /* name */
00105         FALSE,                     /* partial_inplace */
00106         0xf,                /* src_mask */
00107         0xf,                /* dst_mask */
00108         FALSE),             /* pcrel_offset */
00109 
00110   HOWTO (R_CRX_REL8,        /* type */
00111         1,                  /* rightshift */
00112         0,                  /* size */
00113         8,                  /* bitsize */
00114         TRUE,               /* pc_relative */
00115         0,                  /* bitpos */
00116         complain_overflow_bitfield,/* complain_on_overflow */
00117         bfd_elf_generic_reloc,     /* special_function */
00118         "R_CRX_REL8",              /* name */
00119         FALSE,                     /* partial_inplace */
00120         0xff,               /* src_mask */
00121         0xff,               /* dst_mask */
00122         FALSE),             /* pcrel_offset */
00123 
00124   HOWTO (R_CRX_REL8_CMP,    /* type */
00125         1,                  /* rightshift */
00126         0,                  /* size */
00127         8,                  /* bitsize */
00128         TRUE,               /* pc_relative */
00129         0,                  /* bitpos */
00130         complain_overflow_bitfield,/* complain_on_overflow */
00131         bfd_elf_generic_reloc,     /* special_function */
00132         "R_CRX_REL8_CMP",   /* name */
00133         FALSE,                     /* partial_inplace */
00134         0xff,               /* src_mask */
00135         0xff,               /* dst_mask */
00136         FALSE),             /* pcrel_offset */
00137 
00138   HOWTO (R_CRX_REL16,              /* type */
00139         1,                  /* rightshift */
00140         1,                  /* size */
00141         16,                 /* bitsize */
00142         TRUE,               /* pc_relative */
00143         0,                  /* bitpos */
00144         complain_overflow_bitfield,/* complain_on_overflow */
00145         bfd_elf_generic_reloc,     /* special_function */
00146         "R_CRX_REL16",             /* name */
00147         FALSE,                     /* partial_inplace */
00148         0xffff,             /* src_mask */
00149         0xffff,             /* dst_mask */
00150         FALSE),             /* pcrel_offset */
00151 
00152   HOWTO (R_CRX_REL24,              /* type */
00153         1,                  /* rightshift */
00154         2,                  /* size */
00155         24,                 /* bitsize */
00156         TRUE,               /* pc_relative */
00157         0,                  /* bitpos */
00158         complain_overflow_bitfield,/* complain_on_overflow */
00159         bfd_elf_generic_reloc,     /* special_function */
00160         "R_CRX_REL24",             /* name */
00161         FALSE,                     /* partial_inplace */
00162         0xffffff,           /* src_mask */
00163         0xffffff,           /* dst_mask */
00164         FALSE),             /* pcrel_offset */
00165 
00166   HOWTO (R_CRX_REL32,              /* type */
00167         1,                  /* rightshift */
00168         2,                  /* size */
00169         32,                 /* bitsize */
00170         TRUE,               /* pc_relative */
00171         0,                  /* bitpos */
00172         complain_overflow_bitfield,/* complain_on_overflow */
00173         bfd_elf_generic_reloc,     /* special_function */
00174         "R_CRX_REL32",             /* name */
00175         FALSE,                     /* partial_inplace */
00176         0xffffffff,         /* src_mask */
00177         0xffffffff,         /* dst_mask */
00178         FALSE),             /* pcrel_offset */
00179 
00180   HOWTO (R_CRX_REGREL12,    /* type */
00181         0,                  /* rightshift */
00182         1,                  /* size */
00183         12,                 /* bitsize */
00184         FALSE,                     /* pc_relative */
00185         0,                  /* bitpos */
00186         complain_overflow_bitfield,/* complain_on_overflow */
00187         bfd_elf_generic_reloc,     /* special_function */
00188         "R_CRX_REGREL12",   /* name */
00189         FALSE,                     /* partial_inplace */
00190         0xfff,                     /* src_mask */
00191         0xfff,                     /* dst_mask */
00192         FALSE),             /* pcrel_offset */
00193 
00194   HOWTO (R_CRX_REGREL22,    /* type */
00195         0,                  /* rightshift */
00196         2,                  /* size */
00197         22,                 /* bitsize */
00198         FALSE,                     /* pc_relative */
00199         0,                  /* bitpos */
00200         complain_overflow_bitfield,/* complain_on_overflow */
00201         bfd_elf_generic_reloc,     /* special_function */
00202         "R_CRX_REGREL22",   /* name */
00203         FALSE,                     /* partial_inplace */
00204         0x3fffff,           /* src_mask */
00205         0x3fffff,           /* dst_mask */
00206         FALSE),             /* pcrel_offset */
00207 
00208   HOWTO (R_CRX_REGREL28,    /* type */
00209         0,                  /* rightshift */
00210         2,                  /* size */
00211         28,                 /* bitsize */
00212         FALSE,                     /* pc_relative */
00213         0,                  /* bitpos */
00214         complain_overflow_bitfield,/* complain_on_overflow */
00215         bfd_elf_generic_reloc,     /* special_function */
00216         "R_CRX_REGREL28",   /* name */
00217         FALSE,                     /* partial_inplace */
00218         0xfffffff,          /* src_mask */
00219         0xfffffff,          /* dst_mask */
00220         FALSE),             /* pcrel_offset */
00221 
00222   HOWTO (R_CRX_REGREL32,    /* type */
00223         0,                  /* rightshift */
00224         2,                  /* size */
00225         32,                 /* bitsize */
00226         FALSE,                     /* pc_relative */
00227         0,                  /* bitpos */
00228         complain_overflow_bitfield,/* complain_on_overflow */
00229         bfd_elf_generic_reloc,     /* special_function */
00230         "R_CRX_REGREL32",   /* name */
00231         FALSE,                     /* partial_inplace */
00232         0xffffffff,         /* src_mask */
00233         0xffffffff,         /* dst_mask */
00234         FALSE),             /* pcrel_offset */
00235 
00236   HOWTO (R_CRX_ABS16,              /* type */
00237         0,                  /* rightshift */
00238         1,                  /* size */
00239         16,                 /* bitsize */
00240         FALSE,                     /* pc_relative */
00241         0,                  /* bitpos */
00242         complain_overflow_bitfield,/* complain_on_overflow */
00243         bfd_elf_generic_reloc,     /* special_function */
00244         "R_CRX_ABS16",             /* name */
00245         FALSE,                     /* partial_inplace */
00246         0xffff,             /* src_mask */
00247         0xffff,             /* dst_mask */
00248         FALSE),             /* pcrel_offset */
00249 
00250   HOWTO (R_CRX_ABS32,              /* type */
00251         0,                  /* rightshift */
00252         2,                  /* size */
00253         32,                 /* bitsize */
00254         FALSE,                     /* pc_relative */
00255         0,                  /* bitpos */
00256         complain_overflow_bitfield,/* complain_on_overflow */
00257         bfd_elf_generic_reloc,     /* special_function */
00258         "R_CRX_ABS32",             /* name */
00259         FALSE,                     /* partial_inplace */
00260         0xffffffff,         /* src_mask */
00261         0xffffffff,         /* dst_mask */
00262         FALSE),             /* pcrel_offset */
00263 
00264   HOWTO (R_CRX_NUM8,        /* type */
00265         0,                  /* rightshift */
00266         0,                  /* size */
00267         8,                  /* bitsize */
00268         FALSE,                     /* pc_relative */
00269         0,                  /* bitpos */
00270         complain_overflow_bitfield,/* complain_on_overflow */
00271         bfd_elf_generic_reloc,     /* special_function */
00272         "R_CRX_NUM8",              /* name */
00273         FALSE,                     /* partial_inplace */
00274         0xff,               /* src_mask */
00275         0xff,               /* dst_mask */
00276         FALSE),             /* pcrel_offset */
00277 
00278   HOWTO (R_CRX_NUM16,              /* type */
00279         0,                  /* rightshift */
00280         1,                  /* size */
00281         16,                 /* bitsize */
00282         FALSE,                     /* pc_relative */
00283         0,                  /* bitpos */
00284         complain_overflow_bitfield,/* complain_on_overflow */
00285         bfd_elf_generic_reloc,     /* special_function */
00286         "R_CRX_NUM16",             /* name */
00287         FALSE,                     /* partial_inplace */
00288         0xffff,             /* src_mask */
00289         0xffff,             /* dst_mask */
00290         FALSE),             /* pcrel_offset */
00291 
00292   HOWTO (R_CRX_NUM32,              /* type */
00293         0,                  /* rightshift */
00294         2,                  /* size */
00295         32,                 /* bitsize */
00296         FALSE,                     /* pc_relative */
00297         0,                  /* bitpos */
00298         complain_overflow_bitfield,/* complain_on_overflow */
00299         bfd_elf_generic_reloc,     /* special_function */
00300         "R_CRX_NUM32",             /* name */
00301         FALSE,                     /* partial_inplace */
00302         0xffffffff,                /* src_mask */
00303         0xffffffff,         /* dst_mask */
00304         FALSE),             /* pcrel_offset */
00305 
00306   HOWTO (R_CRX_IMM16,              /* type */
00307         0,                  /* rightshift */
00308         1,                  /* size */
00309         16,                 /* bitsize */
00310         FALSE,                     /* pc_relative */
00311         0,                  /* bitpos */
00312         complain_overflow_bitfield,/* complain_on_overflow */
00313         bfd_elf_generic_reloc,     /* special_function */
00314         "R_CRX_IMM16",             /* name */
00315         FALSE,                     /* partial_inplace */
00316         0xffff,             /* src_mask */
00317         0xffff,             /* dst_mask */
00318         FALSE),             /* pcrel_offset */
00319 
00320   HOWTO (R_CRX_IMM32,              /* type */
00321         0,                  /* rightshift */
00322         2,                  /* size */
00323         32,                 /* bitsize */
00324         FALSE,                     /* pc_relative */
00325         0,                  /* bitpos */
00326         complain_overflow_bitfield,/* complain_on_overflow */
00327         bfd_elf_generic_reloc,     /* special_function */
00328         "R_CRX_IMM32",             /* name */
00329         FALSE,                     /* partial_inplace */
00330         0xffffffff,                /* src_mask */
00331         0xffffffff,         /* dst_mask */
00332         FALSE),             /* pcrel_offset */
00333  
00334   /* An 8 bit switch table entry.  This is generated for an expression
00335      such as ``.byte L1 - L2''.  The offset holds the difference
00336      between the reloc address and L2.  */
00337   HOWTO (R_CRX_SWITCH8,            /* type */
00338         0,                  /* rightshift */
00339         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00340         8,                  /* bitsize */
00341         FALSE,                     /* pc_relative */
00342         0,                  /* bitpos */
00343         complain_overflow_unsigned, /* complain_on_overflow */
00344         bfd_elf_generic_reloc,     /* special_function */
00345         "R_CRX_SWITCH8",    /* name */
00346         FALSE,                     /* partial_inplace */
00347         0xff,               /* src_mask */
00348         0xff,               /* dst_mask */
00349         TRUE),                     /* pcrel_offset */
00350 
00351   /* A 16 bit switch table entry.  This is generated for an expression
00352      such as ``.word L1 - L2''.  The offset holds the difference
00353      between the reloc address and L2.  */
00354   HOWTO (R_CRX_SWITCH16,    /* type */
00355         0,                  /* rightshift */
00356         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00357         16,                 /* bitsize */
00358         FALSE,                     /* pc_relative */
00359         0,                  /* bitpos */
00360         complain_overflow_unsigned, /* complain_on_overflow */
00361         bfd_elf_generic_reloc,     /* special_function */
00362         "R_CRX_SWITCH16",   /* name */
00363         FALSE,                     /* partial_inplace */
00364         0xffff,             /* src_mask */
00365         0xffff,             /* dst_mask */
00366         TRUE),                     /* pcrel_offset */
00367 
00368   /* A 32 bit switch table entry.  This is generated for an expression
00369      such as ``.long L1 - L2''.  The offset holds the difference
00370      between the reloc address and L2.  */
00371   HOWTO (R_CRX_SWITCH32,    /* type */
00372         0,                  /* rightshift */
00373         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00374         32,                 /* bitsize */
00375         FALSE,                     /* pc_relative */
00376         0,                  /* bitpos */
00377         complain_overflow_unsigned, /* complain_on_overflow */
00378         bfd_elf_generic_reloc,     /* special_function */
00379         "R_CRX_SWITCH32",   /* name */
00380         FALSE,                     /* partial_inplace */
00381         0xffffffff,         /* src_mask */
00382         0xffffffff,         /* dst_mask */
00383         TRUE)               /* pcrel_offset */
00384 };
00385 
00386 /* Retrieve a howto ptr using a BFD reloc_code.  */
00387 
00388 static reloc_howto_type *
00389 elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00390                         bfd_reloc_code_real_type code)
00391 {
00392   unsigned int i;
00393 
00394   for (i = 0; i < R_CRX_MAX; i++)
00395     if (code == crx_reloc_map[i].bfd_reloc_enum)
00396       return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type];
00397 
00398   printf ("This relocation Type is not supported -0x%x\n", code);
00399   return 0;
00400 }
00401 
00402 static reloc_howto_type *
00403 elf_crx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00404                         const char *r_name)
00405 {
00406   unsigned int i;
00407 
00408   for (i = 0;
00409        i < sizeof (crx_elf_howto_table) / sizeof (crx_elf_howto_table[0]);
00410        i++)
00411     if (crx_elf_howto_table[i].name != NULL
00412        && strcasecmp (crx_elf_howto_table[i].name, r_name) == 0)
00413       return &crx_elf_howto_table[i];
00414 
00415   return NULL;
00416 }
00417 
00418 /* Retrieve a howto ptr using an internal relocation entry.  */
00419 
00420 static void
00421 elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
00422                      Elf_Internal_Rela *dst)
00423 {
00424   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
00425   BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
00426   cache_ptr->howto = &crx_elf_howto_table[r_type];
00427 }
00428 
00429 /* Perform a relocation as part of a final link.  */
00430 
00431 static bfd_reloc_status_type
00432 crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
00433                           bfd *output_bfd ATTRIBUTE_UNUSED,
00434                           asection *input_section, bfd_byte *contents,
00435                           bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
00436                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
00437                           asection *sec ATTRIBUTE_UNUSED,
00438                           int is_local ATTRIBUTE_UNUSED)
00439 {
00440   unsigned short r_type = howto->type;
00441   bfd_byte *hit_data = contents + offset;
00442   bfd_vma reloc_bits, check;
00443 
00444   switch (r_type)
00445     {
00446      case R_CRX_IMM16:
00447      case R_CRX_IMM32:
00448      case R_CRX_ABS16:
00449      case R_CRX_ABS32:
00450      case R_CRX_REL8_CMP:
00451      case R_CRX_REL16:
00452      case R_CRX_REL24:
00453      case R_CRX_REL32:
00454      case R_CRX_REGREL12:
00455      case R_CRX_REGREL22:
00456      case R_CRX_REGREL28:
00457      case R_CRX_REGREL32:
00458        /* 'hit_data' is relative to the start of the instruction, not the
00459          relocation offset. Advance it to account for the exact offset.  */
00460        hit_data += 2;
00461        break;
00462 
00463      case R_CRX_REL4:
00464        /* This relocation type is used only in 'Branch if Equal to 0'
00465          instructions and requires special handling.  */
00466        Rvalue -= 1;
00467        break;
00468 
00469      case R_CRX_NONE:
00470        return bfd_reloc_ok;
00471        break;
00472 
00473      case R_CRX_SWITCH8:
00474      case R_CRX_SWITCH16:
00475      case R_CRX_SWITCH32:
00476        /* We only care about the addend, where the difference between 
00477          expressions is kept.  */
00478        Rvalue = 0;
00479        
00480      default:
00481        break;
00482     }
00483 
00484   if (howto->pc_relative)
00485     {
00486       /* Subtract the address of the section containing the location.  */
00487       Rvalue -= (input_section->output_section->vma
00488                + input_section->output_offset);
00489       /* Subtract the position of the location within the section.  */
00490       Rvalue -= offset;
00491     }
00492 
00493   /* Add in supplied addend.  */
00494   Rvalue += addend;
00495 
00496   /* Complain if the bitfield overflows, whether it is considered
00497      as signed or unsigned.  */
00498   check = Rvalue >> howto->rightshift;
00499 
00500   /* Assumes two's complement.  This expression avoids
00501      overflow if howto->bitsize is the number of bits in
00502      bfd_vma.  */
00503   reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00504 
00505   if (((bfd_vma) check & ~reloc_bits) != 0
00506       && (((bfd_vma) check & ~reloc_bits)
00507          != (-(bfd_vma) 1 & ~reloc_bits)))
00508     {
00509       /* The above right shift is incorrect for a signed
00510         value.  See if turning on the upper bits fixes the
00511         overflow.  */
00512       if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
00513        {
00514          check |= ((bfd_vma) - 1
00515                   & ~((bfd_vma) - 1
00516                      >> howto->rightshift));
00517          if (((bfd_vma) check & ~reloc_bits)
00518              != (-(bfd_vma) 1 & ~reloc_bits))
00519            return bfd_reloc_overflow;
00520        }
00521       else
00522        return bfd_reloc_overflow;
00523     }
00524 
00525   /* Drop unwanted bits from the value we are relocating to.  */
00526   Rvalue >>= (bfd_vma) howto->rightshift;
00527 
00528   /* Apply dst_mask to select only relocatable part of the insn.  */
00529   Rvalue &= howto->dst_mask;
00530 
00531   switch (howto->size)
00532     {
00533      case 0:
00534        if (r_type == R_CRX_REL4)
00535         {
00536           Rvalue <<= 4;
00537           Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
00538         }
00539 
00540        bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
00541        break;
00542 
00543      case 1:
00544        if (r_type == R_CRX_REGREL12)
00545         Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
00546 
00547        bfd_put_16 (input_bfd, Rvalue, hit_data);
00548        break;
00549 
00550      case 2:
00551        if (r_type == R_CRX_REL24
00552           || r_type == R_CRX_REGREL22
00553           || r_type == R_CRX_REGREL28)
00554         Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
00555                     bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
00556 
00557        if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32)
00558         /* Relocation on DATA is purely little-endian, that is, for a
00559            multi-byte datum, the lowest address in memory contains the
00560            little end of the datum, that is, the least significant byte.
00561            Therefore we use BFD's byte Putting functions.  */
00562         bfd_put_32 (input_bfd, Rvalue, hit_data);
00563        else
00564         /* Relocation on INSTRUCTIONS is different : Instructions are
00565            word-addressable, that is, each word itself is arranged according
00566            to little-endian convention, whereas the words are arranged with
00567            respect to one another in BIG ENDIAN fashion.
00568            When there is an immediate value that spans a word boundary, it is
00569            split in a big-endian way with respect to the words.  */
00570         {
00571           bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
00572           bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
00573         }
00574      break;
00575 
00576      default:
00577        return bfd_reloc_notsupported;
00578     }
00579 
00580   return bfd_reloc_ok;
00581 }
00582 
00583 /* Delete some bytes from a section while relaxing.  */
00584 
00585 static bfd_boolean
00586 elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd, 
00587                            asection *sec, bfd_vma addr, int count)
00588 {
00589   Elf_Internal_Shdr *symtab_hdr;
00590   unsigned int sec_shndx;
00591   bfd_byte *contents;
00592   Elf_Internal_Rela *irel, *irelend;
00593   Elf_Internal_Rela *irelalign;
00594   bfd_vma toaddr;
00595   Elf_Internal_Sym *isym;
00596   Elf_Internal_Sym *isymend;
00597   struct elf_link_hash_entry **sym_hashes;
00598   struct elf_link_hash_entry **end_hashes;
00599   struct elf_link_hash_entry **start_hashes;
00600   unsigned int symcount;
00601 
00602   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
00603 
00604   contents = elf_section_data (sec)->this_hdr.contents;
00605 
00606   /* The deletion must stop at the next ALIGN reloc for an aligment
00607      power larger than the number of bytes we are deleting.  */
00608 
00609   irelalign = NULL;
00610   toaddr = sec->size;
00611 
00612   irel = elf_section_data (sec)->relocs;
00613   irelend = irel + sec->reloc_count;
00614 
00615   /* Actually delete the bytes.  */
00616   memmove (contents + addr, contents + addr + count,
00617           (size_t) (toaddr - addr - count));
00618   sec->size -= count;
00619 
00620   /* Adjust all the relocs.  */
00621   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
00622     {
00623       /* Get the new reloc address.  */
00624       if ((irel->r_offset > addr
00625           && irel->r_offset < toaddr))
00626        irel->r_offset -= count;
00627     }
00628 
00629   /* Adjust the local symbols defined in this section.  */
00630   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00631   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
00632   for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
00633     {
00634       if (isym->st_shndx == sec_shndx
00635          && isym->st_value > addr
00636          && isym->st_value < toaddr)
00637        {
00638          /* Adjust the addend of SWITCH relocations in this section, 
00639             which reference this local symbol.  */
00640          for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
00641            {
00642              unsigned long r_symndx;
00643              Elf_Internal_Sym *rsym;
00644              bfd_vma addsym, subsym;
00645 
00646              /* Skip if not a SWITCH relocation.  */
00647              if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
00648                 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
00649                 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
00650                 continue;
00651 
00652              r_symndx = ELF32_R_SYM (irel->r_info);
00653              rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
00654 
00655              /* Skip if not the local adjusted symbol.  */
00656              if (rsym != isym)
00657               continue;
00658 
00659              addsym = isym->st_value;
00660              subsym = addsym - irel->r_addend;
00661 
00662              /* Fix the addend only when -->> (addsym > addr >= subsym).  */
00663              if (subsym <= addr)
00664               irel->r_addend -= count;
00665              else
00666               continue;
00667            }
00668 
00669          isym->st_value -= count;
00670        }
00671     }
00672 
00673   /* Now adjust the global symbols defined in this section.  */
00674   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
00675              - symtab_hdr->sh_info);
00676   sym_hashes = start_hashes = elf_sym_hashes (abfd);
00677   end_hashes = sym_hashes + symcount;
00678 
00679   for (; sym_hashes < end_hashes; sym_hashes++)
00680     {
00681       struct elf_link_hash_entry *sym_hash = *sym_hashes;
00682 
00683       /* The '--wrap SYMBOL' option is causing a pain when the object file, 
00684         containing the definition of __wrap_SYMBOL, includes a direct 
00685         call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference 
00686         the same symbol (which is __wrap_SYMBOL), but still exist as two 
00687         different symbols in 'sym_hashes', we don't want to adjust 
00688         the global symbol __wrap_SYMBOL twice.  
00689         This check is only relevant when symbols are being wrapped.  */
00690       if (link_info->wrap_hash != NULL)
00691        {
00692          struct elf_link_hash_entry **cur_sym_hashes;
00693          
00694          /* Loop only over the symbols whom been already checked.  */
00695          for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes; 
00696               cur_sym_hashes++)
00697            {
00698              /* If the current symbol is identical to 'sym_hash', that means 
00699                the symbol was already adjusted (or at least checked).  */
00700              if (*cur_sym_hashes == sym_hash)
00701               break;
00702            }
00703          /* Don't adjust the symbol again.  */
00704          if (cur_sym_hashes < sym_hashes)
00705            continue;
00706        }
00707 
00708       if ((sym_hash->root.type == bfd_link_hash_defined
00709           || sym_hash->root.type == bfd_link_hash_defweak)
00710          && sym_hash->root.u.def.section == sec
00711          && sym_hash->root.u.def.value > addr
00712          && sym_hash->root.u.def.value < toaddr)
00713        sym_hash->root.u.def.value -= count;
00714     }
00715 
00716   return TRUE;
00717 }
00718 
00719 /* This is a version of bfd_generic_get_relocated_section_contents
00720    which uses elf32_crx_relocate_section.  */
00721 
00722 static bfd_byte *
00723 elf32_crx_get_relocated_section_contents (bfd *output_bfd,
00724                                      struct bfd_link_info *link_info,
00725                                      struct bfd_link_order *link_order,
00726                                      bfd_byte *data,
00727                                      bfd_boolean relocatable,
00728                                      asymbol **symbols)
00729 {
00730   Elf_Internal_Shdr *symtab_hdr;
00731   asection *input_section = link_order->u.indirect.section;
00732   bfd *input_bfd = input_section->owner;
00733   asection **sections = NULL;
00734   Elf_Internal_Rela *internal_relocs = NULL;
00735   Elf_Internal_Sym *isymbuf = NULL;
00736 
00737   /* We only need to handle the case of relaxing, or of having a
00738      particular set of section contents, specially.  */
00739   if (relocatable
00740       || elf_section_data (input_section)->this_hdr.contents == NULL)
00741     return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
00742                                                  link_order, data,
00743                                                  relocatable,
00744                                                  symbols);
00745 
00746   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00747 
00748   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
00749          (size_t) input_section->size);
00750 
00751   if ((input_section->flags & SEC_RELOC) != 0
00752       && input_section->reloc_count > 0)
00753     {
00754       Elf_Internal_Sym *isym;
00755       Elf_Internal_Sym *isymend;
00756       asection **secpp;
00757       bfd_size_type amt;
00758 
00759       internal_relocs = (_bfd_elf_link_read_relocs
00760                       (input_bfd, input_section, (PTR) NULL,
00761                        (Elf_Internal_Rela *) NULL, FALSE));
00762       if (internal_relocs == NULL)
00763        goto error_return;
00764 
00765       if (symtab_hdr->sh_info != 0)
00766        {
00767          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
00768          if (isymbuf == NULL)
00769            isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
00770                                        symtab_hdr->sh_info, 0,
00771                                        NULL, NULL, NULL);
00772          if (isymbuf == NULL)
00773            goto error_return;
00774        }
00775 
00776       amt = symtab_hdr->sh_info;
00777       amt *= sizeof (asection *);
00778       sections = bfd_malloc (amt);
00779       if (sections == NULL && amt != 0)
00780        goto error_return;
00781 
00782       isymend = isymbuf + symtab_hdr->sh_info;
00783       for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
00784        {
00785          asection *isec;
00786 
00787          if (isym->st_shndx == SHN_UNDEF)
00788            isec = bfd_und_section_ptr;
00789          else if (isym->st_shndx == SHN_ABS)
00790            isec = bfd_abs_section_ptr;
00791          else if (isym->st_shndx == SHN_COMMON)
00792            isec = bfd_com_section_ptr;
00793          else
00794            isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
00795 
00796          *secpp = isec;
00797        }
00798 
00799       if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
00800                                  input_section, data, internal_relocs,
00801                                  isymbuf, sections))
00802        goto error_return;
00803 
00804       if (sections != NULL)
00805        free (sections);
00806       if (isymbuf != NULL
00807          && symtab_hdr->contents != (unsigned char *) isymbuf)
00808        free (isymbuf);
00809       if (elf_section_data (input_section)->relocs != internal_relocs)
00810        free (internal_relocs);
00811     }
00812 
00813   return data;
00814 
00815  error_return:
00816   if (sections != NULL)
00817     free (sections);
00818   if (isymbuf != NULL
00819       && symtab_hdr->contents != (unsigned char *) isymbuf)
00820     free (isymbuf);
00821   if (internal_relocs != NULL
00822       && elf_section_data (input_section)->relocs != internal_relocs)
00823     free (internal_relocs);
00824   return NULL;
00825 }
00826 
00827 /* Relocate a CRX ELF section.  */
00828 
00829 static bfd_boolean
00830 elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
00831                          bfd *input_bfd, asection *input_section,
00832                          bfd_byte *contents, Elf_Internal_Rela *relocs,
00833                          Elf_Internal_Sym *local_syms,
00834                          asection **local_sections)
00835 {
00836   Elf_Internal_Shdr *symtab_hdr;
00837   struct elf_link_hash_entry **sym_hashes;
00838   Elf_Internal_Rela *rel, *relend;
00839 
00840   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00841   sym_hashes = elf_sym_hashes (input_bfd);
00842 
00843   rel = relocs;
00844   relend = relocs + input_section->reloc_count;
00845   for (; rel < relend; rel++)
00846     {
00847       int r_type;
00848       reloc_howto_type *howto;
00849       unsigned long r_symndx;
00850       Elf_Internal_Sym *sym;
00851       asection *sec;
00852       struct elf_link_hash_entry *h;
00853       bfd_vma relocation;
00854       bfd_reloc_status_type r;
00855 
00856       r_symndx = ELF32_R_SYM (rel->r_info);
00857       r_type = ELF32_R_TYPE (rel->r_info);
00858       howto = crx_elf_howto_table + (r_type);
00859 
00860       h = NULL;
00861       sym = NULL;
00862       sec = NULL;
00863       if (r_symndx < symtab_hdr->sh_info)
00864        {
00865          sym = local_syms + r_symndx;
00866          sec = local_sections[r_symndx];
00867          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
00868        }
00869       else
00870        {
00871          bfd_boolean unresolved_reloc, warned;
00872 
00873          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00874                                r_symndx, symtab_hdr, sym_hashes,
00875                                h, sec, relocation,
00876                                unresolved_reloc, warned);
00877        }
00878 
00879       if (sec != NULL && elf_discarded_section (sec))
00880        {
00881          /* For relocs against symbols from removed linkonce sections,
00882             or sections discarded by a linker script, we just want the
00883             section contents zeroed.  Avoid any special processing.  */
00884          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
00885          rel->r_info = 0;
00886          rel->r_addend = 0;
00887          continue;
00888        }
00889 
00890       if (info->relocatable)
00891        continue;
00892 
00893       r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
00894                                    input_section,
00895                                    contents, rel->r_offset,
00896                                    relocation, rel->r_addend,
00897                                    info, sec, h == NULL);
00898 
00899       if (r != bfd_reloc_ok)
00900        {
00901          const char *name;
00902          const char *msg = (const char *) 0;
00903 
00904          if (h != NULL)
00905            name = h->root.root.string;
00906          else
00907            {
00908              name = (bfd_elf_string_from_elf_section
00909                     (input_bfd, symtab_hdr->sh_link, sym->st_name));
00910              if (name == NULL || *name == '\0')
00911               name = bfd_section_name (input_bfd, sec);
00912            }
00913 
00914          switch (r)
00915            {
00916             case bfd_reloc_overflow:
00917               if (!((*info->callbacks->reloc_overflow)
00918                    (info, (h ? &h->root : NULL), name, howto->name,
00919                     (bfd_vma) 0, input_bfd, input_section,
00920                     rel->r_offset)))
00921                return FALSE;
00922               break;
00923 
00924             case bfd_reloc_undefined:
00925               if (!((*info->callbacks->undefined_symbol)
00926                    (info, name, input_bfd, input_section,
00927                     rel->r_offset, TRUE)))
00928                return FALSE;
00929               break;
00930 
00931             case bfd_reloc_outofrange:
00932               msg = _("internal error: out of range error");
00933               goto common_error;
00934 
00935             case bfd_reloc_notsupported:
00936               msg = _("internal error: unsupported relocation error");
00937               goto common_error;
00938 
00939             case bfd_reloc_dangerous:
00940               msg = _("internal error: dangerous error");
00941               goto common_error;
00942 
00943             default:
00944               msg = _("internal error: unknown error");
00945               /* Fall through.  */
00946 
00947             common_error:
00948               if (!((*info->callbacks->warning)
00949                    (info, msg, name, input_bfd, input_section,
00950                     rel->r_offset)))
00951                return FALSE;
00952               break;
00953            }
00954        }
00955     }
00956 
00957   return TRUE;
00958 }
00959 
00960 /* This function handles relaxing for the CRX.
00961 
00962    There's quite a few relaxing opportunites available on the CRX:
00963 
00964        * bal/bcond:32 -> bal/bcond:16                             2 bytes
00965        * bcond:16 -> bcond:8                                      2 bytes
00966        * cmpbcond:24 -> cmpbcond:8                         2 bytes
00967        * arithmetic imm32 -> arithmetic imm16                     2 bytes
00968 
00969    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
00970 
00971 static bfd_boolean
00972 elf32_crx_relax_section (bfd *abfd, asection *sec,
00973                       struct bfd_link_info *link_info, bfd_boolean *again)
00974 {
00975   Elf_Internal_Shdr *symtab_hdr;
00976   Elf_Internal_Rela *internal_relocs;
00977   Elf_Internal_Rela *irel, *irelend;
00978   bfd_byte *contents = NULL;
00979   Elf_Internal_Sym *isymbuf = NULL;
00980 
00981   /* Assume nothing changes.  */
00982   *again = FALSE;
00983 
00984   /* We don't have to do anything for a relocatable link, if
00985      this section does not have relocs, or if this is not a
00986      code section.  */
00987   if (link_info->relocatable
00988       || (sec->flags & SEC_RELOC) == 0
00989       || sec->reloc_count == 0
00990       || (sec->flags & SEC_CODE) == 0)
00991     return TRUE;
00992 
00993   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00994 
00995   /* Get a copy of the native relocations.  */
00996   internal_relocs = (_bfd_elf_link_read_relocs
00997                    (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
00998                     link_info->keep_memory));
00999   if (internal_relocs == NULL)
01000     goto error_return;
01001 
01002   /* Walk through them looking for relaxing opportunities.  */
01003   irelend = internal_relocs + sec->reloc_count;
01004   for (irel = internal_relocs; irel < irelend; irel++)
01005     {
01006       bfd_vma symval;
01007 
01008       /* If this isn't something that can be relaxed, then ignore
01009         this reloc.  */
01010       if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
01011          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
01012          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
01013          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
01014        continue;
01015 
01016       /* Get the section contents if we haven't done so already.  */
01017       if (contents == NULL)
01018        {
01019          /* Get cached copy if it exists.  */
01020          if (elf_section_data (sec)->this_hdr.contents != NULL)
01021            contents = elf_section_data (sec)->this_hdr.contents;
01022          /* Go get them off disk.  */
01023          else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
01024            goto error_return;
01025        }
01026 
01027       /* Read this BFD's local symbols if we haven't done so already.  */
01028       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
01029        {
01030          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
01031          if (isymbuf == NULL)
01032            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
01033                                        symtab_hdr->sh_info, 0,
01034                                        NULL, NULL, NULL);
01035          if (isymbuf == NULL)
01036            goto error_return;
01037        }
01038 
01039       /* Get the value of the symbol referred to by the reloc.  */
01040       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
01041        {
01042          /* A local symbol.  */
01043          Elf_Internal_Sym *isym;
01044          asection *sym_sec;
01045 
01046          isym = isymbuf + ELF32_R_SYM (irel->r_info);
01047          if (isym->st_shndx == SHN_UNDEF)
01048            sym_sec = bfd_und_section_ptr;
01049          else if (isym->st_shndx == SHN_ABS)
01050            sym_sec = bfd_abs_section_ptr;
01051          else if (isym->st_shndx == SHN_COMMON)
01052            sym_sec = bfd_com_section_ptr;
01053          else
01054            sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
01055          symval = (isym->st_value
01056                   + sym_sec->output_section->vma
01057                   + sym_sec->output_offset);
01058        }
01059       else
01060        {
01061          unsigned long indx;
01062          struct elf_link_hash_entry *h;
01063 
01064          /* An external symbol.  */
01065          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
01066          h = elf_sym_hashes (abfd)[indx];
01067          BFD_ASSERT (h != NULL);
01068 
01069          if (h->root.type != bfd_link_hash_defined
01070              && h->root.type != bfd_link_hash_defweak)
01071            /* This appears to be a reference to an undefined
01072               symbol.  Just ignore it--it will be caught by the
01073               regular reloc processing.  */
01074            continue;
01075 
01076          symval = (h->root.u.def.value
01077                   + h->root.u.def.section->output_section->vma
01078                   + h->root.u.def.section->output_offset);
01079        }
01080 
01081       /* For simplicity of coding, we are going to modify the section
01082         contents, the section relocs, and the BFD symbol table.  We
01083         must tell the rest of the code not to free up this
01084         information.  It would be possible to instead create a table
01085         of changes which have to be made, as is done in coff-mips.c;
01086         that would be more work, but would require less memory when
01087         the linker is run.  */
01088 
01089       /* Try to turn a 32bit pc-relative branch/call into
01090         a 16bit pc-relative branch/call.  */
01091       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
01092        {
01093          bfd_vma value = symval;
01094 
01095          /* Deal with pc-relative gunk.  */
01096          value -= (sec->output_section->vma + sec->output_offset);
01097          value -= irel->r_offset;
01098          value += irel->r_addend;
01099 
01100          /* See if the value will fit in 16 bits, note the high value is
01101             0xfffe + 2 as the target will be two bytes closer if we are
01102             able to relax.  */
01103          if ((long) value < 0x10000 && (long) value > -0x10002)
01104            {
01105              unsigned short code;
01106 
01107              /* Get the opcode.  */
01108              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
01109 
01110              /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
01111              if ((code & 0xfff0) == 0x3170)
01112               bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
01113              else if ((code & 0xf0ff) == 0x707f)
01114               bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
01115              else
01116               continue;
01117 
01118              /* Note that we've changed the relocs, section contents, etc.  */
01119              elf_section_data (sec)->relocs = internal_relocs;
01120              elf_section_data (sec)->this_hdr.contents = contents;
01121              symtab_hdr->contents = (unsigned char *) isymbuf;
01122 
01123              /* Fix the relocation's type.  */
01124              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01125                                       R_CRX_REL16);
01126 
01127              /* Delete two bytes of data.  */
01128              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
01129                                              irel->r_offset + 2, 2))
01130               goto error_return;
01131 
01132              /* That will change things, so, we should relax again.
01133                Note that this is not required, and it may be slow.  */
01134              *again = TRUE;
01135            }
01136        }
01137 
01138       /* Try to turn a 16bit pc-relative branch into an
01139         8bit pc-relative branch.  */
01140       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
01141        {
01142          bfd_vma value = symval;
01143 
01144          /* Deal with pc-relative gunk.  */
01145          value -= (sec->output_section->vma + sec->output_offset);
01146          value -= irel->r_offset;
01147          value += irel->r_addend;
01148 
01149          /* See if the value will fit in 8 bits, note the high value is
01150             0xfc + 2 as the target will be two bytes closer if we are
01151             able to relax.  */
01152          if ((long) value < 0xfe && (long) value > -0x100)
01153            {
01154              unsigned short code;
01155 
01156              /* Get the opcode.  */
01157              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
01158 
01159              /* Verify it's a 'bcond' opcode.  */
01160              if ((code & 0xf0ff) != 0x707e)
01161               continue;
01162 
01163              /* Note that we've changed the relocs, section contents, etc.  */
01164              elf_section_data (sec)->relocs = internal_relocs;
01165              elf_section_data (sec)->this_hdr.contents = contents;
01166              symtab_hdr->contents = (unsigned char *) isymbuf;
01167 
01168              /* Fix the relocation's type.  */
01169              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01170                                       R_CRX_REL8);
01171 
01172              /* Delete two bytes of data.  */
01173              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
01174                                              irel->r_offset + 2, 2))
01175               goto error_return;
01176 
01177              /* That will change things, so, we should relax again.
01178                Note that this is not required, and it may be slow.  */
01179              *again = TRUE;
01180            }
01181        }
01182 
01183       /* Try to turn a 24bit pc-relative cmp&branch into
01184         an 8bit pc-relative cmp&branch.  */
01185       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
01186        {
01187          bfd_vma value = symval;
01188 
01189          /* Deal with pc-relative gunk.  */
01190          value -= (sec->output_section->vma + sec->output_offset);
01191          value -= irel->r_offset;
01192          value += irel->r_addend;
01193 
01194          /* See if the value will fit in 8 bits, note the high value is
01195             0x7e + 2 as the target will be two bytes closer if we are
01196             able to relax.  */
01197          if ((long) value < 0x100 && (long) value > -0x100)
01198            {
01199              unsigned short code;
01200 
01201              /* Get the opcode.  */
01202              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
01203 
01204              /* Verify it's a 'cmp&branch' opcode.  */
01205              if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
01206               && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
01207               && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
01208               /* Or a Co-processor branch ('bcop').  */
01209               && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
01210               continue;
01211 
01212              /* Note that we've changed the relocs, section contents, etc.  */
01213              elf_section_data (sec)->relocs = internal_relocs;
01214              elf_section_data (sec)->this_hdr.contents = contents;
01215              symtab_hdr->contents = (unsigned char *) isymbuf;
01216 
01217              /* Fix the opcode.  */
01218              bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
01219 
01220              /* Fix the relocation's type.  */
01221              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01222                                       R_CRX_REL8_CMP);
01223 
01224              /* Delete two bytes of data.  */
01225              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
01226                                              irel->r_offset + 4, 2))
01227               goto error_return;
01228 
01229              /* That will change things, so, we should relax again.
01230                Note that this is not required, and it may be slow.  */
01231              *again = TRUE;
01232            }
01233        }
01234 
01235       /* Try to turn a 32bit immediate address into
01236         a 16bit immediate address.  */
01237       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
01238        {
01239          bfd_vma value = symval;
01240 
01241          /* See if the value will fit in 16 bits.  */
01242          if ((long) value < 0x7fff && (long) value > -0x8000)
01243            {
01244              unsigned short code;
01245 
01246              /* Get the opcode.  */
01247              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
01248 
01249              /* Verify it's a 'arithmetic double'.  */
01250              if ((code & 0xf0f0) != 0x20f0)
01251               continue;
01252 
01253              /* Note that we've changed the relocs, section contents, etc.  */
01254              elf_section_data (sec)->relocs = internal_relocs;
01255              elf_section_data (sec)->this_hdr.contents = contents;
01256              symtab_hdr->contents = (unsigned char *) isymbuf;
01257 
01258              /* Fix the opcode.  */
01259              bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
01260 
01261              /* Fix the relocation's type.  */
01262              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01263                                       R_CRX_IMM16);
01264 
01265              /* Delete two bytes of data.  */
01266              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
01267                                              irel->r_offset + 2, 2))
01268               goto error_return;
01269 
01270              /* That will change things, so, we should relax again.
01271                Note that this is not required, and it may be slow.  */
01272              *again = TRUE;
01273            }
01274        }
01275     }
01276 
01277   if (isymbuf != NULL
01278       && symtab_hdr->contents != (unsigned char *) isymbuf)
01279     {
01280       if (! link_info->keep_memory)
01281        free (isymbuf);
01282       else
01283        {
01284          /* Cache the symbols for elf_link_input_bfd.  */
01285          symtab_hdr->contents = (unsigned char *) isymbuf;
01286        }
01287     }
01288 
01289   if (contents != NULL
01290       && elf_section_data (sec)->this_hdr.contents != contents)
01291     {
01292       if (! link_info->keep_memory)
01293        free (contents);
01294       else
01295        {
01296          /* Cache the section contents for elf_link_input_bfd.  */
01297          elf_section_data (sec)->this_hdr.contents = contents;
01298        }
01299     }
01300 
01301   if (internal_relocs != NULL
01302       && elf_section_data (sec)->relocs != internal_relocs)
01303     free (internal_relocs);
01304 
01305   return TRUE;
01306 
01307  error_return:
01308   if (isymbuf != NULL
01309       && symtab_hdr->contents != (unsigned char *) isymbuf)
01310     free (isymbuf);
01311   if (contents != NULL
01312       && elf_section_data (sec)->this_hdr.contents != contents)
01313     free (contents);
01314   if (internal_relocs != NULL
01315       && elf_section_data (sec)->relocs != internal_relocs)
01316     free (internal_relocs);
01317 
01318   return FALSE;
01319 }
01320 
01321 /* Definitions for setting CRX target vector.  */
01322 #define TARGET_LITTLE_SYM          bfd_elf32_crx_vec
01323 #define TARGET_LITTLE_NAME         "elf32-crx"
01324 #define ELF_ARCH                   bfd_arch_crx
01325 #define ELF_MACHINE_CODE           EM_CRX
01326 #define ELF_MAXPAGESIZE                   0x1
01327 #define elf_symbol_leading_char           '_'
01328 
01329 #define bfd_elf32_bfd_reloc_type_lookup   elf_crx_reloc_type_lookup
01330 #define bfd_elf32_bfd_reloc_name_lookup \
01331                                    elf_crx_reloc_name_lookup
01332 #define elf_info_to_howto          elf_crx_info_to_howto
01333 #define elf_info_to_howto_rel             0
01334 #define elf_backend_relocate_section      elf32_crx_relocate_section
01335 #define bfd_elf32_bfd_relax_section       elf32_crx_relax_section
01336 #define bfd_elf32_bfd_get_relocated_section_contents \
01337                             elf32_crx_get_relocated_section_contents
01338 #define elf_backend_can_gc_sections     1
01339 #define elf_backend_rela_normal           1
01340 
01341 #include "elf32-target.h"