x86-64: optimize certain commutative VEX-encoded insns
[external/binutils.git] / bfd / elf32-crx.c
1 /* BFD back-end for National Semiconductor's CRX ELF
2    Copyright (C) 2004-2019 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 bfd_boolean elf_crx_info_to_howto
32   (bfd *, arelent *, Elf_Internal_Rela *);
33 static bfd_boolean 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 bfd_boolean elf32_crx_relocate_section
40   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
41    Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
42 static bfd_boolean elf32_crx_relax_section
43   (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
44 static bfd_byte * elf32_crx_get_relocated_section_contents
45   (bfd *, struct bfd_link_info *, struct bfd_link_order *,
46    bfd_byte *, bfd_boolean, 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          3,                     /* 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          0,                     /* 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          0,                     /* 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          0,                     /* 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          1,                     /* 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          2,                     /* 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          2,                     /* 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          1,                     /* 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          2,                     /* 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          2,                     /* 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          2,                     /* 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          1,                     /* 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          2,                     /* 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          0,                     /* 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          1,                     /* 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          2,                     /* 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          1,                     /* 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          2,                     /* 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          0,                     /* size (0 = byte, 1 = short, 2 = long) */
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          1,                     /* size (0 = byte, 1 = short, 2 = long) */
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          2,                     /* size (0 = byte, 1 = short, 2 = long) */
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 bfd_boolean
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   /* Assumes two's complement.  This expression avoids
510      overflow if howto->bitsize is the number of bits in
511      bfd_vma.  */
512   reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
513
514   if (((bfd_vma) check & ~reloc_bits) != 0
515       && (((bfd_vma) check & ~reloc_bits)
516           != (-(bfd_vma) 1 & ~reloc_bits)))
517     {
518       /* The above right shift is incorrect for a signed
519          value.  See if turning on the upper bits fixes the
520          overflow.  */
521       if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
522         {
523           check |= ((bfd_vma) - 1
524                     & ~((bfd_vma) - 1
525                         >> howto->rightshift));
526           if (((bfd_vma) check & ~reloc_bits)
527               != (-(bfd_vma) 1 & ~reloc_bits))
528             return bfd_reloc_overflow;
529         }
530       else
531         return bfd_reloc_overflow;
532     }
533
534   /* Drop unwanted bits from the value we are relocating to.  */
535   Rvalue >>= (bfd_vma) howto->rightshift;
536
537   /* Apply dst_mask to select only relocatable part of the insn.  */
538   Rvalue &= howto->dst_mask;
539
540   switch (howto->size)
541     {
542      case 0:
543        if (r_type == R_CRX_REL4)
544          {
545            Rvalue <<= 4;
546            Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
547          }
548
549        bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
550        break;
551
552      case 1:
553        if (r_type == R_CRX_REGREL12)
554          Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
555
556        bfd_put_16 (input_bfd, Rvalue, hit_data);
557        break;
558
559      case 2:
560        if (r_type == R_CRX_REL24
561            || r_type == R_CRX_REGREL22
562            || r_type == R_CRX_REGREL28)
563          Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
564                       bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
565
566        if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32)
567          /* Relocation on DATA is purely little-endian, that is, for a
568             multi-byte datum, the lowest address in memory contains the
569             little end of the datum, that is, the least significant byte.
570             Therefore we use BFD's byte Putting functions.  */
571          bfd_put_32 (input_bfd, Rvalue, hit_data);
572        else
573          /* Relocation on INSTRUCTIONS is different : Instructions are
574             word-addressable, that is, each word itself is arranged according
575             to little-endian convention, whereas the words are arranged with
576             respect to one another in BIG ENDIAN fashion.
577             When there is an immediate value that spans a word boundary, it is
578             split in a big-endian way with respect to the words.  */
579          {
580            bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
581            bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
582          }
583      break;
584
585      default:
586        return bfd_reloc_notsupported;
587     }
588
589   return bfd_reloc_ok;
590 }
591
592 /* Delete some bytes from a section while relaxing.  */
593
594 static bfd_boolean
595 elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
596                               asection *sec, bfd_vma addr, int count)
597 {
598   Elf_Internal_Shdr *symtab_hdr;
599   unsigned int sec_shndx;
600   bfd_byte *contents;
601   Elf_Internal_Rela *irel, *irelend;
602   bfd_vma toaddr;
603   Elf_Internal_Sym *isym;
604   Elf_Internal_Sym *isymend;
605   struct elf_link_hash_entry **sym_hashes;
606   struct elf_link_hash_entry **end_hashes;
607   struct elf_link_hash_entry **start_hashes;
608   unsigned int symcount;
609
610   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
611
612   contents = elf_section_data (sec)->this_hdr.contents;
613
614   toaddr = sec->size;
615
616   irel = elf_section_data (sec)->relocs;
617   irelend = irel + sec->reloc_count;
618
619   /* Actually delete the bytes.  */
620   memmove (contents + addr, contents + addr + count,
621            (size_t) (toaddr - addr - count));
622   sec->size -= count;
623
624   /* Adjust all the relocs.  */
625   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
626     {
627       /* Get the new reloc address.  */
628       if ((irel->r_offset > addr
629            && irel->r_offset < toaddr))
630         irel->r_offset -= count;
631     }
632
633   /* Adjust the local symbols defined in this section.  */
634   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
635   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
636   for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
637     {
638       if (isym->st_shndx == sec_shndx
639           && isym->st_value > addr
640           && isym->st_value < toaddr)
641         {
642           /* Adjust the addend of SWITCH relocations in this section,
643              which reference this local symbol.  */
644           for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
645             {
646               unsigned long r_symndx;
647               Elf_Internal_Sym *rsym;
648               bfd_vma addsym, subsym;
649
650               /* Skip if not a SWITCH relocation.  */
651               if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
652                   && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
653                   && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
654                   continue;
655
656               r_symndx = ELF32_R_SYM (irel->r_info);
657               rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
658
659               /* Skip if not the local adjusted symbol.  */
660               if (rsym != isym)
661                 continue;
662
663               addsym = isym->st_value;
664               subsym = addsym - irel->r_addend;
665
666               /* Fix the addend only when -->> (addsym > addr >= subsym).  */
667               if (subsym <= addr)
668                 irel->r_addend -= count;
669               else
670                 continue;
671             }
672
673           isym->st_value -= count;
674         }
675     }
676
677   /* Now adjust the global symbols defined in this section.  */
678   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
679               - symtab_hdr->sh_info);
680   sym_hashes = start_hashes = elf_sym_hashes (abfd);
681   end_hashes = sym_hashes + symcount;
682
683   for (; sym_hashes < end_hashes; sym_hashes++)
684     {
685       struct elf_link_hash_entry *sym_hash = *sym_hashes;
686
687       /* The '--wrap SYMBOL' option is causing a pain when the object file,
688          containing the definition of __wrap_SYMBOL, includes a direct
689          call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
690          the same symbol (which is __wrap_SYMBOL), but still exist as two
691          different symbols in 'sym_hashes', we don't want to adjust
692          the global symbol __wrap_SYMBOL twice.
693          This check is only relevant when symbols are being wrapped.  */
694       if (link_info->wrap_hash != NULL)
695         {
696           struct elf_link_hash_entry **cur_sym_hashes;
697
698           /* Loop only over the symbols whom been already checked.  */
699           for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
700                cur_sym_hashes++)
701             {
702               /* If the current symbol is identical to 'sym_hash', that means
703                  the symbol was already adjusted (or at least checked).  */
704               if (*cur_sym_hashes == sym_hash)
705                 break;
706             }
707           /* Don't adjust the symbol again.  */
708           if (cur_sym_hashes < sym_hashes)
709             continue;
710         }
711
712       if ((sym_hash->root.type == bfd_link_hash_defined
713            || sym_hash->root.type == bfd_link_hash_defweak)
714           && sym_hash->root.u.def.section == sec
715           && sym_hash->root.u.def.value > addr
716           && sym_hash->root.u.def.value < toaddr)
717         sym_hash->root.u.def.value -= count;
718     }
719
720   return TRUE;
721 }
722
723 /* This is a version of bfd_generic_get_relocated_section_contents
724    which uses elf32_crx_relocate_section.  */
725
726 static bfd_byte *
727 elf32_crx_get_relocated_section_contents (bfd *output_bfd,
728                                           struct bfd_link_info *link_info,
729                                           struct bfd_link_order *link_order,
730                                           bfd_byte *data,
731                                           bfd_boolean relocatable,
732                                           asymbol **symbols)
733 {
734   Elf_Internal_Shdr *symtab_hdr;
735   asection *input_section = link_order->u.indirect.section;
736   bfd *input_bfd = input_section->owner;
737   asection **sections = NULL;
738   Elf_Internal_Rela *internal_relocs = NULL;
739   Elf_Internal_Sym *isymbuf = NULL;
740
741   /* We only need to handle the case of relaxing, or of having a
742      particular set of section contents, specially.  */
743   if (relocatable
744       || elf_section_data (input_section)->this_hdr.contents == NULL)
745     return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
746                                                        link_order, data,
747                                                        relocatable,
748                                                        symbols);
749
750   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
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       if (sections != NULL)
809         free (sections);
810       if (isymbuf != NULL
811           && symtab_hdr->contents != (unsigned char *) isymbuf)
812         free (isymbuf);
813       if (elf_section_data (input_section)->relocs != internal_relocs)
814         free (internal_relocs);
815     }
816
817   return data;
818
819  error_return:
820   if (sections != NULL)
821     free (sections);
822   if (isymbuf != NULL
823       && symtab_hdr->contents != (unsigned char *) isymbuf)
824     free (isymbuf);
825   if (internal_relocs != NULL
826       && elf_section_data (input_section)->relocs != internal_relocs)
827     free (internal_relocs);
828   return NULL;
829 }
830
831 /* Relocate a CRX ELF section.  */
832
833 static bfd_boolean
834 elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
835                             bfd *input_bfd, asection *input_section,
836                             bfd_byte *contents, Elf_Internal_Rela *relocs,
837                             Elf_Internal_Sym *local_syms,
838                             asection **local_sections)
839 {
840   Elf_Internal_Shdr *symtab_hdr;
841   struct elf_link_hash_entry **sym_hashes;
842   Elf_Internal_Rela *rel, *relend;
843
844   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
845   sym_hashes = elf_sym_hashes (input_bfd);
846
847   rel = relocs;
848   relend = relocs + input_section->reloc_count;
849   for (; rel < relend; rel++)
850     {
851       int r_type;
852       reloc_howto_type *howto;
853       unsigned long r_symndx;
854       Elf_Internal_Sym *sym;
855       asection *sec;
856       struct elf_link_hash_entry *h;
857       bfd_vma relocation;
858       bfd_reloc_status_type r;
859
860       r_symndx = ELF32_R_SYM (rel->r_info);
861       r_type = ELF32_R_TYPE (rel->r_info);
862       howto = crx_elf_howto_table + (r_type);
863
864       h = NULL;
865       sym = NULL;
866       sec = NULL;
867       if (r_symndx < symtab_hdr->sh_info)
868         {
869           sym = local_syms + r_symndx;
870           sec = local_sections[r_symndx];
871           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
872         }
873       else
874         {
875           bfd_boolean unresolved_reloc, warned, ignored;
876
877           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
878                                    r_symndx, symtab_hdr, sym_hashes,
879                                    h, sec, relocation,
880                                    unresolved_reloc, warned, ignored);
881         }
882
883       if (sec != NULL && discarded_section (sec))
884         RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
885                                          rel, 1, relend, howto, 0, contents);
886
887       if (bfd_link_relocatable (info))
888         continue;
889
890       r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
891                                         input_section,
892                                         contents, rel->r_offset,
893                                         relocation, rel->r_addend,
894                                         info, sec, h == NULL);
895
896       if (r != bfd_reloc_ok)
897         {
898           const char *name;
899           const char *msg = (const char *) 0;
900
901           if (h != NULL)
902             name = h->root.root.string;
903           else
904             {
905               name = (bfd_elf_string_from_elf_section
906                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
907               if (name == NULL || *name == '\0')
908                 name = bfd_section_name (input_bfd, sec);
909             }
910
911           switch (r)
912             {
913              case bfd_reloc_overflow:
914                (*info->callbacks->reloc_overflow)
915                  (info, (h ? &h->root : NULL), name, howto->name,
916                   (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
917                break;
918
919              case bfd_reloc_undefined:
920                (*info->callbacks->undefined_symbol)
921                  (info, name, input_bfd, input_section, rel->r_offset, TRUE);
922                break;
923
924              case bfd_reloc_outofrange:
925                msg = _("internal error: out of range error");
926                goto common_error;
927
928              case bfd_reloc_notsupported:
929                msg = _("internal error: unsupported relocation error");
930                goto common_error;
931
932              case bfd_reloc_dangerous:
933                msg = _("internal error: dangerous error");
934                goto common_error;
935
936              default:
937                msg = _("internal error: unknown error");
938                /* Fall through.  */
939
940              common_error:
941                (*info->callbacks->warning) (info, msg, name, input_bfd,
942                                             input_section, rel->r_offset);
943                break;
944             }
945         }
946     }
947
948   return TRUE;
949 }
950
951 /* This function handles relaxing for the CRX.
952
953    There's quite a few relaxing opportunites available on the CRX:
954
955         * bal/bcond:32 -> bal/bcond:16                             2 bytes
956         * bcond:16 -> bcond:8                                      2 bytes
957         * cmpbcond:24 -> cmpbcond:8                                2 bytes
958         * arithmetic imm32 -> arithmetic imm16                     2 bytes
959
960    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
961
962 static bfd_boolean
963 elf32_crx_relax_section (bfd *abfd, asection *sec,
964                          struct bfd_link_info *link_info, bfd_boolean *again)
965 {
966   Elf_Internal_Shdr *symtab_hdr;
967   Elf_Internal_Rela *internal_relocs;
968   Elf_Internal_Rela *irel, *irelend;
969   bfd_byte *contents = NULL;
970   Elf_Internal_Sym *isymbuf = NULL;
971
972   /* Assume nothing changes.  */
973   *again = FALSE;
974
975   /* We don't have to do anything for a relocatable link, if
976      this section does not have relocs, or if this is not a
977      code section.  */
978   if (bfd_link_relocatable (link_info)
979       || (sec->flags & SEC_RELOC) == 0
980       || sec->reloc_count == 0
981       || (sec->flags & SEC_CODE) == 0)
982     return TRUE;
983
984   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
985
986   /* Get a copy of the native relocations.  */
987   internal_relocs = (_bfd_elf_link_read_relocs
988                      (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
989                       link_info->keep_memory));
990   if (internal_relocs == NULL)
991     goto error_return;
992
993   /* Walk through them looking for relaxing opportunities.  */
994   irelend = internal_relocs + sec->reloc_count;
995   for (irel = internal_relocs; irel < irelend; irel++)
996     {
997       bfd_vma symval;
998
999       /* If this isn't something that can be relaxed, then ignore
1000          this reloc.  */
1001       if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
1002           && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
1003           && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
1004           && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
1005         continue;
1006
1007       /* Get the section contents if we haven't done so already.  */
1008       if (contents == NULL)
1009         {
1010           /* Get cached copy if it exists.  */
1011           if (elf_section_data (sec)->this_hdr.contents != NULL)
1012             contents = elf_section_data (sec)->this_hdr.contents;
1013           /* Go get them off disk.  */
1014           else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1015             goto error_return;
1016         }
1017
1018       /* Read this BFD's local symbols if we haven't done so already.  */
1019       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1020         {
1021           isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1022           if (isymbuf == NULL)
1023             isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1024                                             symtab_hdr->sh_info, 0,
1025                                             NULL, NULL, NULL);
1026           if (isymbuf == NULL)
1027             goto error_return;
1028         }
1029
1030       /* Get the value of the symbol referred to by the reloc.  */
1031       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1032         {
1033           /* A local symbol.  */
1034           Elf_Internal_Sym *isym;
1035           asection *sym_sec;
1036
1037           isym = isymbuf + ELF32_R_SYM (irel->r_info);
1038           if (isym->st_shndx == SHN_UNDEF)
1039             sym_sec = bfd_und_section_ptr;
1040           else if (isym->st_shndx == SHN_ABS)
1041             sym_sec = bfd_abs_section_ptr;
1042           else if (isym->st_shndx == SHN_COMMON)
1043             sym_sec = bfd_com_section_ptr;
1044           else
1045             sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1046           symval = (isym->st_value
1047                     + sym_sec->output_section->vma
1048                     + sym_sec->output_offset);
1049         }
1050       else
1051         {
1052           unsigned long indx;
1053           struct elf_link_hash_entry *h;
1054
1055           /* An external symbol.  */
1056           indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1057           h = elf_sym_hashes (abfd)[indx];
1058           BFD_ASSERT (h != NULL);
1059
1060           if (h->root.type != bfd_link_hash_defined
1061               && h->root.type != bfd_link_hash_defweak)
1062             /* This appears to be a reference to an undefined
1063                symbol.  Just ignore it--it will be caught by the
1064                regular reloc processing.  */
1065             continue;
1066
1067           symval = (h->root.u.def.value
1068                     + h->root.u.def.section->output_section->vma
1069                     + h->root.u.def.section->output_offset);
1070         }
1071
1072       /* For simplicity of coding, we are going to modify the section
1073          contents, the section relocs, and the BFD symbol table.  We
1074          must tell the rest of the code not to free up this
1075          information.  It would be possible to instead create a table
1076          of changes which have to be made, as is done in coff-mips.c;
1077          that would be more work, but would require less memory when
1078          the linker is run.  */
1079
1080       /* Try to turn a 32bit pc-relative branch/call into
1081          a 16bit pc-relative branch/call.  */
1082       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
1083         {
1084           bfd_vma value = symval;
1085
1086           /* Deal with pc-relative gunk.  */
1087           value -= (sec->output_section->vma + sec->output_offset);
1088           value -= irel->r_offset;
1089           value += irel->r_addend;
1090
1091           /* See if the value will fit in 16 bits, note the high value is
1092              0xfffe + 2 as the target will be two bytes closer if we are
1093              able to relax.  */
1094           if ((long) value < 0x10000 && (long) value > -0x10002)
1095             {
1096               unsigned short code;
1097
1098               /* Get the opcode.  */
1099               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1100
1101               /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
1102               if ((code & 0xfff0) == 0x3170)
1103                 bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1104               else if ((code & 0xf0ff) == 0x707f)
1105                 bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
1106               else
1107                 continue;
1108
1109               /* Note that we've changed the relocs, section contents, etc.  */
1110               elf_section_data (sec)->relocs = internal_relocs;
1111               elf_section_data (sec)->this_hdr.contents = contents;
1112               symtab_hdr->contents = (unsigned char *) isymbuf;
1113
1114               /* Fix the relocation's type.  */
1115               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1116                                            R_CRX_REL16);
1117
1118               /* Delete two bytes of data.  */
1119               if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1120                                                    irel->r_offset + 2, 2))
1121                 goto error_return;
1122
1123               /* That will change things, so, we should relax again.
1124                  Note that this is not required, and it may be slow.  */
1125               *again = TRUE;
1126             }
1127         }
1128
1129       /* Try to turn a 16bit pc-relative branch into an
1130          8bit pc-relative branch.  */
1131       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
1132         {
1133           bfd_vma value = symval;
1134
1135           /* Deal with pc-relative gunk.  */
1136           value -= (sec->output_section->vma + sec->output_offset);
1137           value -= irel->r_offset;
1138           value += irel->r_addend;
1139
1140           /* See if the value will fit in 8 bits, note the high value is
1141              0xfc + 2 as the target will be two bytes closer if we are
1142              able to relax.  */
1143           if ((long) value < 0xfe && (long) value > -0x100)
1144             {
1145               unsigned short code;
1146
1147               /* Get the opcode.  */
1148               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1149
1150               /* Verify it's a 'bcond' opcode.  */
1151               if ((code & 0xf0ff) != 0x707e)
1152                 continue;
1153
1154               /* Note that we've changed the relocs, section contents, etc.  */
1155               elf_section_data (sec)->relocs = internal_relocs;
1156               elf_section_data (sec)->this_hdr.contents = contents;
1157               symtab_hdr->contents = (unsigned char *) isymbuf;
1158
1159               /* Fix the relocation's type.  */
1160               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1161                                            R_CRX_REL8);
1162
1163               /* Delete two bytes of data.  */
1164               if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1165                                                    irel->r_offset + 2, 2))
1166                 goto error_return;
1167
1168               /* That will change things, so, we should relax again.
1169                  Note that this is not required, and it may be slow.  */
1170               *again = TRUE;
1171             }
1172         }
1173
1174       /* Try to turn a 24bit pc-relative cmp&branch into
1175          an 8bit pc-relative cmp&branch.  */
1176       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1177         {
1178           bfd_vma value = symval;
1179
1180           /* Deal with pc-relative gunk.  */
1181           value -= (sec->output_section->vma + sec->output_offset);
1182           value -= irel->r_offset;
1183           value += irel->r_addend;
1184
1185           /* See if the value will fit in 8 bits, note the high value is
1186              0x7e + 2 as the target will be two bytes closer if we are
1187              able to relax.  */
1188           if ((long) value < 0x100 && (long) value > -0x100)
1189             {
1190               unsigned short code;
1191
1192               /* Get the opcode.  */
1193               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1194
1195               /* Verify it's a 'cmp&branch' opcode.  */
1196               if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1197                && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1198                && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
1199                /* Or a Co-processor branch ('bcop').  */
1200                && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
1201                 continue;
1202
1203               /* Note that we've changed the relocs, section contents, etc.  */
1204               elf_section_data (sec)->relocs = internal_relocs;
1205               elf_section_data (sec)->this_hdr.contents = contents;
1206               symtab_hdr->contents = (unsigned char *) isymbuf;
1207
1208               /* Fix the opcode.  */
1209               bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1210
1211               /* Fix the relocation's type.  */
1212               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1213                                            R_CRX_REL8_CMP);
1214
1215               /* Delete two bytes of data.  */
1216               if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1217                                                    irel->r_offset + 4, 2))
1218                 goto error_return;
1219
1220               /* That will change things, so, we should relax again.
1221                  Note that this is not required, and it may be slow.  */
1222               *again = TRUE;
1223             }
1224         }
1225
1226       /* Try to turn a 32bit immediate address into
1227          a 16bit immediate address.  */
1228       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1229         {
1230           bfd_vma value = symval;
1231
1232           /* See if the value will fit in 16 bits.  */
1233           if ((long) value < 0x7fff && (long) value > -0x8000)
1234             {
1235               unsigned short code;
1236
1237               /* Get the opcode.  */
1238               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1239
1240               /* Verify it's a 'arithmetic double'.  */
1241               if ((code & 0xf0f0) != 0x20f0)
1242                 continue;
1243
1244               /* Note that we've changed the relocs, section contents, etc.  */
1245               elf_section_data (sec)->relocs = internal_relocs;
1246               elf_section_data (sec)->this_hdr.contents = contents;
1247               symtab_hdr->contents = (unsigned char *) isymbuf;
1248
1249               /* Fix the opcode.  */
1250               bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1251
1252               /* Fix the relocation's type.  */
1253               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1254                                            R_CRX_IMM16);
1255
1256               /* Delete two bytes of data.  */
1257               if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1258                                                    irel->r_offset + 2, 2))
1259                 goto error_return;
1260
1261               /* That will change things, so, we should relax again.
1262                  Note that this is not required, and it may be slow.  */
1263               *again = TRUE;
1264             }
1265         }
1266     }
1267
1268   if (isymbuf != NULL
1269       && symtab_hdr->contents != (unsigned char *) isymbuf)
1270     {
1271       if (! link_info->keep_memory)
1272         free (isymbuf);
1273       else
1274         {
1275           /* Cache the symbols for elf_link_input_bfd.  */
1276           symtab_hdr->contents = (unsigned char *) isymbuf;
1277         }
1278     }
1279
1280   if (contents != NULL
1281       && elf_section_data (sec)->this_hdr.contents != contents)
1282     {
1283       if (! link_info->keep_memory)
1284         free (contents);
1285       else
1286         {
1287           /* Cache the section contents for elf_link_input_bfd.  */
1288           elf_section_data (sec)->this_hdr.contents = contents;
1289         }
1290     }
1291
1292   if (internal_relocs != NULL
1293       && elf_section_data (sec)->relocs != internal_relocs)
1294     free (internal_relocs);
1295
1296   return TRUE;
1297
1298  error_return:
1299   if (isymbuf != NULL
1300       && symtab_hdr->contents != (unsigned char *) isymbuf)
1301     free (isymbuf);
1302   if (contents != NULL
1303       && elf_section_data (sec)->this_hdr.contents != contents)
1304     free (contents);
1305   if (internal_relocs != NULL
1306       && elf_section_data (sec)->relocs != internal_relocs)
1307     free (internal_relocs);
1308
1309   return FALSE;
1310 }
1311
1312 /* Definitions for setting CRX target vector.  */
1313 #define TARGET_LITTLE_SYM               crx_elf32_vec
1314 #define TARGET_LITTLE_NAME              "elf32-crx"
1315 #define ELF_ARCH                        bfd_arch_crx
1316 #define ELF_MACHINE_CODE                EM_CRX
1317 #define ELF_MAXPAGESIZE                 0x1
1318 #define elf_symbol_leading_char         '_'
1319
1320 #define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
1321 #define bfd_elf32_bfd_reloc_name_lookup \
1322                                         elf_crx_reloc_name_lookup
1323 #define elf_info_to_howto               elf_crx_info_to_howto
1324 #define elf_info_to_howto_rel           NULL
1325 #define elf_backend_relocate_section    elf32_crx_relocate_section
1326 #define bfd_elf32_bfd_relax_section     elf32_crx_relax_section
1327 #define bfd_elf32_bfd_get_relocated_section_contents \
1328                                 elf32_crx_get_relocated_section_contents
1329 #define elf_backend_can_gc_sections     1
1330 #define elf_backend_rela_normal         1
1331
1332 #include "elf32-target.h"