OSDN Git Service

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