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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "bfdlink.h"
24#include "libbfd.h"
25#include "elf-bfd.h"
26#include "elf/crx.h"
27
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  (struct bfd_link_info *, 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 (struct bfd_link_info *link_info, bfd *abfd,
577			      asection *sec, 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  struct elf_link_hash_entry **start_hashes;
590  unsigned int symcount;
591
592  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
593
594  contents = elf_section_data (sec)->this_hdr.contents;
595
596  /* The deletion must stop at the next ALIGN reloc for an aligment
597     power larger than the number of bytes we are deleting.  */
598
599  irelalign = NULL;
600  toaddr = sec->size;
601
602  irel = elf_section_data (sec)->relocs;
603  irelend = irel + sec->reloc_count;
604
605  /* Actually delete the bytes.  */
606  memmove (contents + addr, contents + addr + count,
607	   (size_t) (toaddr - addr - count));
608  sec->size -= count;
609
610  /* Adjust all the relocs.  */
611  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
612    {
613      /* Get the new reloc address.  */
614      if ((irel->r_offset > addr
615	   && irel->r_offset < toaddr))
616	irel->r_offset -= count;
617    }
618
619  /* Adjust the local symbols defined in this section.  */
620  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
621  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
622  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
623    {
624      if (isym->st_shndx == sec_shndx
625	  && isym->st_value > addr
626	  && isym->st_value < toaddr)
627	{
628	  /* Adjust the addend of SWITCH relocations in this section,
629	     which reference this local symbol.  */
630	  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
631	    {
632	      unsigned long r_symndx;
633	      Elf_Internal_Sym *rsym;
634	      bfd_vma addsym, subsym;
635
636	      /* Skip if not a SWITCH relocation.  */
637	      if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
638		  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
639		  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
640		  continue;
641
642	      r_symndx = ELF32_R_SYM (irel->r_info);
643	      rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
644
645	      /* Skip if not the local adjusted symbol.  */
646	      if (rsym != isym)
647		continue;
648
649	      addsym = isym->st_value;
650	      subsym = addsym - irel->r_addend;
651
652	      /* Fix the addend only when -->> (addsym > addr >= subsym).  */
653	      if (subsym <= addr)
654		irel->r_addend -= count;
655	      else
656		continue;
657	    }
658
659	  isym->st_value -= count;
660	}
661    }
662
663  /* Now adjust the global symbols defined in this section.  */
664  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
665	      - symtab_hdr->sh_info);
666  sym_hashes = start_hashes = elf_sym_hashes (abfd);
667  end_hashes = sym_hashes + symcount;
668
669  for (; sym_hashes < end_hashes; sym_hashes++)
670    {
671      struct elf_link_hash_entry *sym_hash = *sym_hashes;
672
673      /* The '--wrap SYMBOL' option is causing a pain when the object file,
674	 containing the definition of __wrap_SYMBOL, includes a direct
675	 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
676	 the same symbol (which is __wrap_SYMBOL), but still exist as two
677	 different symbols in 'sym_hashes', we don't want to adjust
678	 the global symbol __wrap_SYMBOL twice.
679	 This check is only relevant when symbols are being wrapped.  */
680      if (link_info->wrap_hash != NULL)
681	{
682	  struct elf_link_hash_entry **cur_sym_hashes;
683
684	  /* Loop only over the symbols whom been already checked.  */
685	  for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
686	       cur_sym_hashes++)
687	    {
688	      /* If the current symbol is identical to 'sym_hash', that means
689		 the symbol was already adjusted (or at least checked).  */
690	      if (*cur_sym_hashes == sym_hash)
691		break;
692	    }
693	  /* Don't adjust the symbol again.  */
694	  if (cur_sym_hashes < sym_hashes)
695	    continue;
696	}
697
698      if ((sym_hash->root.type == bfd_link_hash_defined
699	   || sym_hash->root.type == bfd_link_hash_defweak)
700	  && sym_hash->root.u.def.section == sec
701	  && sym_hash->root.u.def.value > addr
702	  && sym_hash->root.u.def.value < toaddr)
703	sym_hash->root.u.def.value -= count;
704    }
705
706  return TRUE;
707}
708
709/* This is a version of bfd_generic_get_relocated_section_contents
710   which uses elf32_crx_relocate_section.  */
711
712static bfd_byte *
713elf32_crx_get_relocated_section_contents (bfd *output_bfd,
714					  struct bfd_link_info *link_info,
715					  struct bfd_link_order *link_order,
716					  bfd_byte *data,
717					  bfd_boolean relocatable,
718					  asymbol **symbols)
719{
720  Elf_Internal_Shdr *symtab_hdr;
721  asection *input_section = link_order->u.indirect.section;
722  bfd *input_bfd = input_section->owner;
723  asection **sections = NULL;
724  Elf_Internal_Rela *internal_relocs = NULL;
725  Elf_Internal_Sym *isymbuf = NULL;
726
727  /* We only need to handle the case of relaxing, or of having a
728     particular set of section contents, specially.  */
729  if (relocatable
730      || elf_section_data (input_section)->this_hdr.contents == NULL)
731    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
732						       link_order, data,
733						       relocatable,
734						       symbols);
735
736  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
737
738  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
739	  (size_t) input_section->size);
740
741  if ((input_section->flags & SEC_RELOC) != 0
742      && input_section->reloc_count > 0)
743    {
744      Elf_Internal_Sym *isym;
745      Elf_Internal_Sym *isymend;
746      asection **secpp;
747      bfd_size_type amt;
748
749      internal_relocs = (_bfd_elf_link_read_relocs
750			 (input_bfd, input_section, (PTR) NULL,
751			  (Elf_Internal_Rela *) NULL, FALSE));
752      if (internal_relocs == NULL)
753	goto error_return;
754
755      if (symtab_hdr->sh_info != 0)
756	{
757	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
758	  if (isymbuf == NULL)
759	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
760					    symtab_hdr->sh_info, 0,
761					    NULL, NULL, NULL);
762	  if (isymbuf == NULL)
763	    goto error_return;
764	}
765
766      amt = symtab_hdr->sh_info;
767      amt *= sizeof (asection *);
768      sections = bfd_malloc (amt);
769      if (sections == NULL && amt != 0)
770	goto error_return;
771
772      isymend = isymbuf + symtab_hdr->sh_info;
773      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
774	{
775	  asection *isec;
776
777	  if (isym->st_shndx == SHN_UNDEF)
778	    isec = bfd_und_section_ptr;
779	  else if (isym->st_shndx == SHN_ABS)
780	    isec = bfd_abs_section_ptr;
781	  else if (isym->st_shndx == SHN_COMMON)
782	    isec = bfd_com_section_ptr;
783	  else
784	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
785
786	  *secpp = isec;
787	}
788
789      if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
790				     input_section, data, internal_relocs,
791				     isymbuf, sections))
792	goto error_return;
793
794      if (sections != NULL)
795	free (sections);
796      if (isymbuf != NULL
797	  && symtab_hdr->contents != (unsigned char *) isymbuf)
798	free (isymbuf);
799      if (elf_section_data (input_section)->relocs != internal_relocs)
800	free (internal_relocs);
801    }
802
803  return data;
804
805 error_return:
806  if (sections != NULL)
807    free (sections);
808  if (isymbuf != NULL
809      && symtab_hdr->contents != (unsigned char *) isymbuf)
810    free (isymbuf);
811  if (internal_relocs != NULL
812      && elf_section_data (input_section)->relocs != internal_relocs)
813    free (internal_relocs);
814  return NULL;
815}
816
817/* Relocate a CRX ELF section.  */
818
819static bfd_boolean
820elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
821			    bfd *input_bfd, asection *input_section,
822			    bfd_byte *contents, Elf_Internal_Rela *relocs,
823			    Elf_Internal_Sym *local_syms,
824			    asection **local_sections)
825{
826  Elf_Internal_Shdr *symtab_hdr;
827  struct elf_link_hash_entry **sym_hashes;
828  Elf_Internal_Rela *rel, *relend;
829
830  if (info->relocatable)
831    return TRUE;
832
833  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
834  sym_hashes = elf_sym_hashes (input_bfd);
835
836  rel = relocs;
837  relend = relocs + input_section->reloc_count;
838  for (; rel < relend; rel++)
839    {
840      int r_type;
841      reloc_howto_type *howto;
842      unsigned long r_symndx;
843      Elf_Internal_Sym *sym;
844      asection *sec;
845      struct elf_link_hash_entry *h;
846      bfd_vma relocation;
847      bfd_reloc_status_type r;
848
849      r_symndx = ELF32_R_SYM (rel->r_info);
850      r_type = ELF32_R_TYPE (rel->r_info);
851      howto = crx_elf_howto_table + (r_type);
852
853      h = NULL;
854      sym = NULL;
855      sec = NULL;
856      if (r_symndx < symtab_hdr->sh_info)
857	{
858	  sym = local_syms + r_symndx;
859	  sec = local_sections[r_symndx];
860	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
861	}
862      else
863	{
864	  bfd_boolean unresolved_reloc, warned;
865
866	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
867				   r_symndx, symtab_hdr, sym_hashes,
868				   h, sec, relocation,
869				   unresolved_reloc, warned);
870	}
871
872      r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
873					input_section,
874					contents, rel->r_offset,
875					relocation, rel->r_addend,
876					info, sec, h == NULL);
877
878      if (r != bfd_reloc_ok)
879	{
880	  const char *name;
881	  const char *msg = (const char *) 0;
882
883	  if (h != NULL)
884	    name = h->root.root.string;
885	  else
886	    {
887	      name = (bfd_elf_string_from_elf_section
888		      (input_bfd, symtab_hdr->sh_link, sym->st_name));
889	      if (name == NULL || *name == '\0')
890		name = bfd_section_name (input_bfd, sec);
891	    }
892
893	  switch (r)
894	    {
895	     case bfd_reloc_overflow:
896	       if (!((*info->callbacks->reloc_overflow)
897		     (info, (h ? &h->root : NULL), name, howto->name,
898		      (bfd_vma) 0, input_bfd, input_section,
899		      rel->r_offset)))
900		 return FALSE;
901	       break;
902
903	     case bfd_reloc_undefined:
904	       if (!((*info->callbacks->undefined_symbol)
905		     (info, name, input_bfd, input_section,
906		      rel->r_offset, TRUE)))
907		 return FALSE;
908	       break;
909
910	     case bfd_reloc_outofrange:
911	       msg = _("internal error: out of range error");
912	       goto common_error;
913
914	     case bfd_reloc_notsupported:
915	       msg = _("internal error: unsupported relocation error");
916	       goto common_error;
917
918	     case bfd_reloc_dangerous:
919	       msg = _("internal error: dangerous error");
920	       goto common_error;
921
922	     default:
923	       msg = _("internal error: unknown error");
924	       /* Fall through.  */
925
926	     common_error:
927	       if (!((*info->callbacks->warning)
928		     (info, msg, name, input_bfd, input_section,
929		      rel->r_offset)))
930		 return FALSE;
931	       break;
932	    }
933	}
934    }
935
936  return TRUE;
937}
938
939/* This function handles relaxing for the CRX.
940
941   There's quite a few relaxing opportunites available on the CRX:
942
943	* bal/bcond:32 -> bal/bcond:16				   2 bytes
944	* bcond:16 -> bcond:8					   2 bytes
945	* cmpbcond:24 -> cmpbcond:8				   2 bytes
946	* arithmetic imm32 -> arithmetic imm16			   2 bytes
947
948   Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
949
950static bfd_boolean
951elf32_crx_relax_section (bfd *abfd, asection *sec,
952			 struct bfd_link_info *link_info, bfd_boolean *again)
953{
954  Elf_Internal_Shdr *symtab_hdr;
955  Elf_Internal_Rela *internal_relocs;
956  Elf_Internal_Rela *irel, *irelend;
957  bfd_byte *contents = NULL;
958  Elf_Internal_Sym *isymbuf = NULL;
959
960  /* Assume nothing changes.  */
961  *again = FALSE;
962
963  /* We don't have to do anything for a relocatable link, if
964     this section does not have relocs, or if this is not a
965     code section.  */
966  if (link_info->relocatable
967      || (sec->flags & SEC_RELOC) == 0
968      || sec->reloc_count == 0
969      || (sec->flags & SEC_CODE) == 0)
970    return TRUE;
971
972  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
973
974  /* Get a copy of the native relocations.  */
975  internal_relocs = (_bfd_elf_link_read_relocs
976		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
977		      link_info->keep_memory));
978  if (internal_relocs == NULL)
979    goto error_return;
980
981  /* Walk through them looking for relaxing opportunities.  */
982  irelend = internal_relocs + sec->reloc_count;
983  for (irel = internal_relocs; irel < irelend; irel++)
984    {
985      bfd_vma symval;
986
987      /* If this isn't something that can be relaxed, then ignore
988	 this reloc.  */
989      if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
990	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
991	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
992	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
993	continue;
994
995      /* Get the section contents if we haven't done so already.  */
996      if (contents == NULL)
997	{
998	  /* Get cached copy if it exists.  */
999	  if (elf_section_data (sec)->this_hdr.contents != NULL)
1000	    contents = elf_section_data (sec)->this_hdr.contents;
1001	  /* Go get them off disk.  */
1002	  else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1003	    goto error_return;
1004	}
1005
1006      /* Read this BFD's local symbols if we haven't done so already.  */
1007      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1008	{
1009	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1010	  if (isymbuf == NULL)
1011	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1012					    symtab_hdr->sh_info, 0,
1013					    NULL, NULL, NULL);
1014	  if (isymbuf == NULL)
1015	    goto error_return;
1016	}
1017
1018      /* Get the value of the symbol referred to by the reloc.  */
1019      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1020	{
1021	  /* A local symbol.  */
1022	  Elf_Internal_Sym *isym;
1023	  asection *sym_sec;
1024
1025	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
1026	  if (isym->st_shndx == SHN_UNDEF)
1027	    sym_sec = bfd_und_section_ptr;
1028	  else if (isym->st_shndx == SHN_ABS)
1029	    sym_sec = bfd_abs_section_ptr;
1030	  else if (isym->st_shndx == SHN_COMMON)
1031	    sym_sec = bfd_com_section_ptr;
1032	  else
1033	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1034	  symval = (isym->st_value
1035		    + sym_sec->output_section->vma
1036		    + sym_sec->output_offset);
1037	}
1038      else
1039	{
1040	  unsigned long indx;
1041	  struct elf_link_hash_entry *h;
1042
1043	  /* An external symbol.  */
1044	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1045	  h = elf_sym_hashes (abfd)[indx];
1046	  BFD_ASSERT (h != NULL);
1047
1048	  if (h->root.type != bfd_link_hash_defined
1049	      && h->root.type != bfd_link_hash_defweak)
1050	    /* This appears to be a reference to an undefined
1051	       symbol.  Just ignore it--it will be caught by the
1052	       regular reloc processing.  */
1053	    continue;
1054
1055	  symval = (h->root.u.def.value
1056		    + h->root.u.def.section->output_section->vma
1057		    + h->root.u.def.section->output_offset);
1058	}
1059
1060      /* For simplicity of coding, we are going to modify the section
1061	 contents, the section relocs, and the BFD symbol table.  We
1062	 must tell the rest of the code not to free up this
1063	 information.  It would be possible to instead create a table
1064	 of changes which have to be made, as is done in coff-mips.c;
1065	 that would be more work, but would require less memory when
1066	 the linker is run.  */
1067
1068      /* Try to turn a 32bit pc-relative branch/call into
1069	 a 16bit pc-relative branch/call.  */
1070      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
1071	{
1072	  bfd_vma value = symval;
1073
1074	  /* Deal with pc-relative gunk.  */
1075	  value -= (sec->output_section->vma + sec->output_offset);
1076	  value -= irel->r_offset;
1077	  value += irel->r_addend;
1078
1079	  /* See if the value will fit in 16 bits, note the high value is
1080	     0xfffe + 2 as the target will be two bytes closer if we are
1081	     able to relax.  */
1082	  if ((long) value < 0x10000 && (long) value > -0x10002)
1083	    {
1084	      unsigned short code;
1085
1086	      /* Get the opcode.  */
1087	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1088
1089	      /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
1090	      if ((code & 0xfff0) == 0x3170)
1091		bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1092	      else if ((code & 0xf0ff) == 0x707f)
1093		bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
1094	      else
1095		continue;
1096
1097	      /* Note that we've changed the relocs, section contents, etc.  */
1098	      elf_section_data (sec)->relocs = internal_relocs;
1099	      elf_section_data (sec)->this_hdr.contents = contents;
1100	      symtab_hdr->contents = (unsigned char *) isymbuf;
1101
1102	      /* Fix the relocation's type.  */
1103	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1104					   R_CRX_REL16);
1105
1106	      /* Delete two bytes of data.  */
1107	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1108						   irel->r_offset + 2, 2))
1109		goto error_return;
1110
1111	      /* That will change things, so, we should relax again.
1112		 Note that this is not required, and it may be slow.  */
1113	      *again = TRUE;
1114	    }
1115	}
1116
1117      /* Try to turn a 16bit pc-relative branch into an
1118	 8bit pc-relative branch.  */
1119      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
1120	{
1121	  bfd_vma value = symval;
1122
1123	  /* Deal with pc-relative gunk.  */
1124	  value -= (sec->output_section->vma + sec->output_offset);
1125	  value -= irel->r_offset;
1126	  value += irel->r_addend;
1127
1128	  /* See if the value will fit in 8 bits, note the high value is
1129	     0xfc + 2 as the target will be two bytes closer if we are
1130	     able to relax.  */
1131	  if ((long) value < 0xfe && (long) value > -0x100)
1132	    {
1133	      unsigned short code;
1134
1135	      /* Get the opcode.  */
1136	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1137
1138	      /* Verify it's a 'bcond' opcode.  */
1139	      if ((code & 0xf0ff) != 0x707e)
1140		continue;
1141
1142	      /* Note that we've changed the relocs, section contents, etc.  */
1143	      elf_section_data (sec)->relocs = internal_relocs;
1144	      elf_section_data (sec)->this_hdr.contents = contents;
1145	      symtab_hdr->contents = (unsigned char *) isymbuf;
1146
1147	      /* Fix the relocation's type.  */
1148	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1149					   R_CRX_REL8);
1150
1151	      /* Delete two bytes of data.  */
1152	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1153						   irel->r_offset + 2, 2))
1154		goto error_return;
1155
1156	      /* That will change things, so, we should relax again.
1157		 Note that this is not required, and it may be slow.  */
1158	      *again = TRUE;
1159	    }
1160	}
1161
1162      /* Try to turn a 24bit pc-relative cmp&branch into
1163	 an 8bit pc-relative cmp&branch.  */
1164      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1165	{
1166	  bfd_vma value = symval;
1167
1168	  /* Deal with pc-relative gunk.  */
1169	  value -= (sec->output_section->vma + sec->output_offset);
1170	  value -= irel->r_offset;
1171	  value += irel->r_addend;
1172
1173	  /* See if the value will fit in 8 bits, note the high value is
1174	     0x7e + 2 as the target will be two bytes closer if we are
1175	     able to relax.  */
1176	  if ((long) value < 0x100 && (long) value > -0x100)
1177	    {
1178	      unsigned short code;
1179
1180	      /* Get the opcode.  */
1181	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1182
1183	      /* Verify it's a 'cmp&branch' opcode.  */
1184	      if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1185	       && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1186	       && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
1187	       /* Or a Co-processor branch ('bcop').  */
1188	       && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
1189		continue;
1190
1191	      /* Note that we've changed the relocs, section contents, etc.  */
1192	      elf_section_data (sec)->relocs = internal_relocs;
1193	      elf_section_data (sec)->this_hdr.contents = contents;
1194	      symtab_hdr->contents = (unsigned char *) isymbuf;
1195
1196	      /* Fix the opcode.  */
1197	      bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1198
1199	      /* Fix the relocation's type.  */
1200	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1201					   R_CRX_REL8_CMP);
1202
1203	      /* Delete two bytes of data.  */
1204	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1205						   irel->r_offset + 4, 2))
1206		goto error_return;
1207
1208	      /* That will change things, so, we should relax again.
1209		 Note that this is not required, and it may be slow.  */
1210	      *again = TRUE;
1211	    }
1212	}
1213
1214      /* Try to turn a 32bit immediate address into
1215	 a 16bit immediate address.  */
1216      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1217	{
1218	  bfd_vma value = symval;
1219
1220	  /* See if the value will fit in 16 bits.  */
1221	  if ((long) value < 0x7fff && (long) value > -0x8000)
1222	    {
1223	      unsigned short code;
1224
1225	      /* Get the opcode.  */
1226	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1227
1228	      /* Verify it's a 'arithmetic double'.  */
1229	      if ((code & 0xf0f0) != 0x20f0)
1230		continue;
1231
1232	      /* Note that we've changed the relocs, section contents, etc.  */
1233	      elf_section_data (sec)->relocs = internal_relocs;
1234	      elf_section_data (sec)->this_hdr.contents = contents;
1235	      symtab_hdr->contents = (unsigned char *) isymbuf;
1236
1237	      /* Fix the opcode.  */
1238	      bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1239
1240	      /* Fix the relocation's type.  */
1241	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1242					   R_CRX_IMM16);
1243
1244	      /* Delete two bytes of data.  */
1245	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1246						   irel->r_offset + 2, 2))
1247		goto error_return;
1248
1249	      /* That will change things, so, we should relax again.
1250		 Note that this is not required, and it may be slow.  */
1251	      *again = TRUE;
1252	    }
1253	}
1254    }
1255
1256  if (isymbuf != NULL
1257      && symtab_hdr->contents != (unsigned char *) isymbuf)
1258    {
1259      if (! link_info->keep_memory)
1260	free (isymbuf);
1261      else
1262	{
1263	  /* Cache the symbols for elf_link_input_bfd.  */
1264	  symtab_hdr->contents = (unsigned char *) isymbuf;
1265	}
1266    }
1267
1268  if (contents != NULL
1269      && elf_section_data (sec)->this_hdr.contents != contents)
1270    {
1271      if (! link_info->keep_memory)
1272	free (contents);
1273      else
1274	{
1275	  /* Cache the section contents for elf_link_input_bfd.  */
1276	  elf_section_data (sec)->this_hdr.contents = contents;
1277	}
1278    }
1279
1280  if (internal_relocs != NULL
1281      && elf_section_data (sec)->relocs != internal_relocs)
1282    free (internal_relocs);
1283
1284  return TRUE;
1285
1286 error_return:
1287  if (isymbuf != NULL
1288      && symtab_hdr->contents != (unsigned char *) isymbuf)
1289    free (isymbuf);
1290  if (contents != NULL
1291      && elf_section_data (sec)->this_hdr.contents != contents)
1292    free (contents);
1293  if (internal_relocs != NULL
1294      && elf_section_data (sec)->relocs != internal_relocs)
1295    free (internal_relocs);
1296
1297  return FALSE;
1298}
1299
1300static asection *
1301elf32_crx_gc_mark_hook (asection *sec,
1302			struct bfd_link_info *info ATTRIBUTE_UNUSED,
1303			Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1304			struct elf_link_hash_entry *h,
1305			Elf_Internal_Sym *sym)
1306{
1307  if (h == NULL)
1308    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1309
1310  switch (h->root.type)
1311    {
1312    case bfd_link_hash_defined:
1313    case bfd_link_hash_defweak:
1314      return h->root.u.def.section;
1315
1316    case bfd_link_hash_common:
1317      return h->root.u.c.p->section;
1318
1319    default:
1320      return NULL;
1321    }
1322}
1323
1324/* Update the got entry reference counts for the section being removed.  */
1325
1326static bfd_boolean
1327elf32_crx_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1328			 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1329			 asection *sec ATTRIBUTE_UNUSED,
1330			 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1331{
1332  /* We don't support garbage collection of GOT and PLT relocs yet.  */
1333  return TRUE;
1334}
1335
1336/* Definitions for setting CRX target vector.  */
1337#define TARGET_LITTLE_SYM		bfd_elf32_crx_vec
1338#define TARGET_LITTLE_NAME		"elf32-crx"
1339#define ELF_ARCH			bfd_arch_crx
1340#define ELF_MACHINE_CODE		EM_CRX
1341#define ELF_MAXPAGESIZE			0x1
1342#define elf_symbol_leading_char		'_'
1343
1344#define bfd_elf32_bfd_reloc_type_lookup	elf_crx_reloc_type_lookup
1345#define elf_info_to_howto		elf_crx_info_to_howto
1346#define elf_info_to_howto_rel		0
1347#define elf_backend_relocate_section	elf32_crx_relocate_section
1348#define bfd_elf32_bfd_relax_section	elf32_crx_relax_section
1349#define bfd_elf32_bfd_get_relocated_section_contents \
1350				elf32_crx_get_relocated_section_contents
1351#define elf_backend_gc_mark_hook        elf32_crx_gc_mark_hook
1352#define elf_backend_gc_sweep_hook       elf32_crx_gc_sweep_hook
1353#define elf_backend_can_gc_sections     1
1354#define elf_backend_rela_normal		1
1355
1356#include "elf32-target.h"
1357