OSDN Git Service

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