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
28static reloc_howto_type *elf_crx_reloc_type_lookup
29  (bfd *, bfd_reloc_code_real_type);
30static void elf_crx_info_to_howto
31  (bfd *, arelent *, Elf_Internal_Rela *);
32static bfd_boolean elf32_crx_relax_delete_bytes
33  (bfd *, asection *, bfd_vma, int);
34static 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);
38static bfd_boolean elf32_crx_relocate_section
39  (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
40   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
41static asection * elf32_crx_gc_mark_hook
42  (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
43   struct elf_link_hash_entry *, Elf_Internal_Sym *);
44static bfd_boolean elf32_crx_gc_sweep_hook
45  (bfd *, struct bfd_link_info *, asection *,
46   const Elf_Internal_Rela *);
47static bfd_boolean elf32_crx_relax_section
48  (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
49static 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
55struct 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
61static 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
86static 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
394static reloc_howto_type *
395elf_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
410static void
411elf_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
421static bfd_reloc_status_type
422crx_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
575static bfd_boolean
576elf32_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
686static bfd_byte *
687elf32_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
793static bfd_boolean
794elf32_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
923static bfd_boolean
924elf32_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
1271static asection *
1272elf32_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
1297static bfd_boolean
1298elf32_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"
1328