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