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