1/* BFD back-end for National Semiconductor's CRX ELF
2   Copyright (C) 2004-2022 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 3 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,
20   MA 02110-1301, USA.  */
21
22#include "sysdep.h"
23#include "bfd.h"
24#include "bfdlink.h"
25#include "libbfd.h"
26#include "elf-bfd.h"
27#include "elf/crx.h"
28
29static reloc_howto_type *elf_crx_reloc_type_lookup
30  (bfd *, bfd_reloc_code_real_type);
31static bool elf_crx_info_to_howto
32  (bfd *, arelent *, Elf_Internal_Rela *);
33static bool elf32_crx_relax_delete_bytes
34  (struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
35static bfd_reloc_status_type crx_elf_final_link_relocate
36  (reloc_howto_type *, bfd *, bfd *, asection *,
37   bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
38   struct bfd_link_info *, asection *, int);
39static int elf32_crx_relocate_section
40  (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
41   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
42static bool elf32_crx_relax_section
43  (bfd *, asection *, struct bfd_link_info *, bool *);
44static bfd_byte * elf32_crx_get_relocated_section_contents
45  (bfd *, struct bfd_link_info *, struct bfd_link_order *,
46   bfd_byte *, bool, asymbol **);
47
48/* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
49
50struct crx_reloc_map
51{
52  bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
53  unsigned short crx_reloc_type;	   /* CRX relocation type.  */
54};
55
56static const struct crx_reloc_map crx_reloc_map[R_CRX_MAX] =
57{
58  {BFD_RELOC_NONE,	    R_CRX_NONE},
59  {BFD_RELOC_CRX_REL4,	    R_CRX_REL4},
60  {BFD_RELOC_CRX_REL8,	    R_CRX_REL8},
61  {BFD_RELOC_CRX_REL8_CMP,  R_CRX_REL8_CMP},
62  {BFD_RELOC_CRX_REL16,	    R_CRX_REL16},
63  {BFD_RELOC_CRX_REL24,	    R_CRX_REL24},
64  {BFD_RELOC_CRX_REL32,	    R_CRX_REL32},
65  {BFD_RELOC_CRX_REGREL12,  R_CRX_REGREL12},
66  {BFD_RELOC_CRX_REGREL22,  R_CRX_REGREL22},
67  {BFD_RELOC_CRX_REGREL28,  R_CRX_REGREL28},
68  {BFD_RELOC_CRX_REGREL32,  R_CRX_REGREL32},
69  {BFD_RELOC_CRX_ABS16,	    R_CRX_ABS16},
70  {BFD_RELOC_CRX_ABS32,	    R_CRX_ABS32},
71  {BFD_RELOC_CRX_NUM8,	    R_CRX_NUM8},
72  {BFD_RELOC_CRX_NUM16,	    R_CRX_NUM16},
73  {BFD_RELOC_CRX_NUM32,	    R_CRX_NUM32},
74  {BFD_RELOC_CRX_IMM16,	    R_CRX_IMM16},
75  {BFD_RELOC_CRX_IMM32,	    R_CRX_IMM32},
76  {BFD_RELOC_CRX_SWITCH8,   R_CRX_SWITCH8},
77  {BFD_RELOC_CRX_SWITCH16,  R_CRX_SWITCH16},
78  {BFD_RELOC_CRX_SWITCH32,  R_CRX_SWITCH32}
79};
80
81static reloc_howto_type crx_elf_howto_table[] =
82{
83  HOWTO (R_CRX_NONE,		/* type */
84	 0,			/* rightshift */
85	 0,			/* size */
86	 0,			/* bitsize */
87	 false,			/* pc_relative */
88	 0,			/* bitpos */
89	 complain_overflow_dont,/* complain_on_overflow */
90	 bfd_elf_generic_reloc,	/* special_function */
91	 "R_CRX_NONE",		/* name */
92	 false,			/* partial_inplace */
93	 0,			/* src_mask */
94	 0,			/* dst_mask */
95	 false),		/* pcrel_offset */
96
97  HOWTO (R_CRX_REL4,		/* type */
98	 1,			/* rightshift */
99	 1,			/* size */
100	 4,			/* bitsize */
101	 true,			/* pc_relative */
102	 0,			/* bitpos */
103	 complain_overflow_bitfield,/* complain_on_overflow */
104	 bfd_elf_generic_reloc,	/* special_function */
105	 "R_CRX_REL4",		/* name */
106	 false,			/* partial_inplace */
107	 0x0,			/* src_mask */
108	 0xf,			/* dst_mask */
109	 false),		/* pcrel_offset */
110
111  HOWTO (R_CRX_REL8,		/* type */
112	 1,			/* rightshift */
113	 1,			/* size */
114	 8,			/* bitsize */
115	 true,			/* pc_relative */
116	 0,			/* bitpos */
117	 complain_overflow_bitfield,/* complain_on_overflow */
118	 bfd_elf_generic_reloc,	/* special_function */
119	 "R_CRX_REL8",		/* name */
120	 false,			/* partial_inplace */
121	 0x0,			/* src_mask */
122	 0xff,			/* dst_mask */
123	 false),		/* pcrel_offset */
124
125  HOWTO (R_CRX_REL8_CMP,	/* type */
126	 1,			/* rightshift */
127	 1,			/* size */
128	 8,			/* bitsize */
129	 true,			/* pc_relative */
130	 0,			/* bitpos */
131	 complain_overflow_bitfield,/* complain_on_overflow */
132	 bfd_elf_generic_reloc,	/* special_function */
133	 "R_CRX_REL8_CMP",	/* name */
134	 false,			/* partial_inplace */
135	 0x0,			/* src_mask */
136	 0xff,			/* dst_mask */
137	 false),		/* pcrel_offset */
138
139  HOWTO (R_CRX_REL16,		/* type */
140	 1,			/* rightshift */
141	 2,			/* size */
142	 16,			/* bitsize */
143	 true,			/* pc_relative */
144	 0,			/* bitpos */
145	 complain_overflow_bitfield,/* complain_on_overflow */
146	 bfd_elf_generic_reloc,	/* special_function */
147	 "R_CRX_REL16",		/* name */
148	 false,			/* partial_inplace */
149	 0x0,			/* src_mask */
150	 0xffff,		/* dst_mask */
151	 false),		/* pcrel_offset */
152
153  HOWTO (R_CRX_REL24,		/* type */
154	 1,			/* rightshift */
155	 4,			/* size */
156	 24,			/* bitsize */
157	 true,			/* pc_relative */
158	 0,			/* bitpos */
159	 complain_overflow_bitfield,/* complain_on_overflow */
160	 bfd_elf_generic_reloc,	/* special_function */
161	 "R_CRX_REL24",		/* name */
162	 false,			/* partial_inplace */
163	 0x0,			/* src_mask */
164	 0xffffff,		/* dst_mask */
165	 false),		/* pcrel_offset */
166
167  HOWTO (R_CRX_REL32,		/* type */
168	 1,			/* rightshift */
169	 4,			/* size */
170	 32,			/* bitsize */
171	 true,			/* pc_relative */
172	 0,			/* bitpos */
173	 complain_overflow_bitfield,/* complain_on_overflow */
174	 bfd_elf_generic_reloc,	/* special_function */
175	 "R_CRX_REL32",		/* name */
176	 false,			/* partial_inplace */
177	 0x0,			/* src_mask */
178	 0xffffffff,		/* dst_mask */
179	 false),		/* pcrel_offset */
180
181  HOWTO (R_CRX_REGREL12,	/* type */
182	 0,			/* rightshift */
183	 2,			/* size */
184	 12,			/* bitsize */
185	 false,			/* pc_relative */
186	 0,			/* bitpos */
187	 complain_overflow_bitfield,/* complain_on_overflow */
188	 bfd_elf_generic_reloc,	/* special_function */
189	 "R_CRX_REGREL12",	/* name */
190	 false,			/* partial_inplace */
191	 0x0,			/* src_mask */
192	 0xfff,			/* dst_mask */
193	 false),		/* pcrel_offset */
194
195  HOWTO (R_CRX_REGREL22,	/* type */
196	 0,			/* rightshift */
197	 4,			/* size */
198	 22,			/* bitsize */
199	 false,			/* pc_relative */
200	 0,			/* bitpos */
201	 complain_overflow_bitfield,/* complain_on_overflow */
202	 bfd_elf_generic_reloc,	/* special_function */
203	 "R_CRX_REGREL22",	/* name */
204	 false,			/* partial_inplace */
205	 0x0,			/* src_mask */
206	 0x3fffff,		/* dst_mask */
207	 false),		/* pcrel_offset */
208
209  HOWTO (R_CRX_REGREL28,	/* type */
210	 0,			/* rightshift */
211	 4,			/* size */
212	 28,			/* bitsize */
213	 false,			/* pc_relative */
214	 0,			/* bitpos */
215	 complain_overflow_bitfield,/* complain_on_overflow */
216	 bfd_elf_generic_reloc,	/* special_function */
217	 "R_CRX_REGREL28",	/* name */
218	 false,			/* partial_inplace */
219	 0x0,			/* src_mask */
220	 0xfffffff,		/* dst_mask */
221	 false),		/* pcrel_offset */
222
223  HOWTO (R_CRX_REGREL32,	/* type */
224	 0,			/* rightshift */
225	 4,			/* size */
226	 32,			/* bitsize */
227	 false,			/* pc_relative */
228	 0,			/* bitpos */
229	 complain_overflow_bitfield,/* complain_on_overflow */
230	 bfd_elf_generic_reloc,	/* special_function */
231	 "R_CRX_REGREL32",	/* name */
232	 false,			/* partial_inplace */
233	 0x0,			/* src_mask */
234	 0xffffffff,		/* dst_mask */
235	 false),		/* pcrel_offset */
236
237  HOWTO (R_CRX_ABS16,		/* type */
238	 0,			/* rightshift */
239	 2,			/* size */
240	 16,			/* bitsize */
241	 false,			/* pc_relative */
242	 0,			/* bitpos */
243	 complain_overflow_bitfield,/* complain_on_overflow */
244	 bfd_elf_generic_reloc,	/* special_function */
245	 "R_CRX_ABS16",		/* name */
246	 false,			/* partial_inplace */
247	 0x0,			/* src_mask */
248	 0xffff,		/* dst_mask */
249	 false),		/* pcrel_offset */
250
251  HOWTO (R_CRX_ABS32,		/* type */
252	 0,			/* rightshift */
253	 4,			/* size */
254	 32,			/* bitsize */
255	 false,			/* pc_relative */
256	 0,			/* bitpos */
257	 complain_overflow_bitfield,/* complain_on_overflow */
258	 bfd_elf_generic_reloc,	/* special_function */
259	 "R_CRX_ABS32",		/* name */
260	 false,			/* partial_inplace */
261	 0x0,			/* src_mask */
262	 0xffffffff,		/* dst_mask */
263	 false),		/* pcrel_offset */
264
265  HOWTO (R_CRX_NUM8,		/* type */
266	 0,			/* rightshift */
267	 1,			/* size */
268	 8,			/* bitsize */
269	 false,			/* pc_relative */
270	 0,			/* bitpos */
271	 complain_overflow_bitfield,/* complain_on_overflow */
272	 bfd_elf_generic_reloc,	/* special_function */
273	 "R_CRX_NUM8",		/* name */
274	 false,			/* partial_inplace */
275	 0x0,			/* src_mask */
276	 0xff,			/* dst_mask */
277	 false),		/* pcrel_offset */
278
279  HOWTO (R_CRX_NUM16,		/* type */
280	 0,			/* rightshift */
281	 2,			/* size */
282	 16,			/* bitsize */
283	 false,			/* pc_relative */
284	 0,			/* bitpos */
285	 complain_overflow_bitfield,/* complain_on_overflow */
286	 bfd_elf_generic_reloc,	/* special_function */
287	 "R_CRX_NUM16",		/* name */
288	 false,			/* partial_inplace */
289	 0x0,			/* src_mask */
290	 0xffff,		/* dst_mask */
291	 false),		/* pcrel_offset */
292
293  HOWTO (R_CRX_NUM32,		/* type */
294	 0,			/* rightshift */
295	 4,			/* size */
296	 32,			/* bitsize */
297	 false,			/* pc_relative */
298	 0,			/* bitpos */
299	 complain_overflow_bitfield,/* complain_on_overflow */
300	 bfd_elf_generic_reloc,	/* special_function */
301	 "R_CRX_NUM32",		/* name */
302	 false,			/* partial_inplace */
303	 0x0,			/* src_mask */
304	 0xffffffff,		/* dst_mask */
305	 false),		/* pcrel_offset */
306
307  HOWTO (R_CRX_IMM16,		/* type */
308	 0,			/* rightshift */
309	 2,			/* size */
310	 16,			/* bitsize */
311	 false,			/* pc_relative */
312	 0,			/* bitpos */
313	 complain_overflow_bitfield,/* complain_on_overflow */
314	 bfd_elf_generic_reloc,	/* special_function */
315	 "R_CRX_IMM16",		/* name */
316	 false,			/* partial_inplace */
317	 0x0,			/* src_mask */
318	 0xffff,		/* dst_mask */
319	 false),		/* pcrel_offset */
320
321  HOWTO (R_CRX_IMM32,		/* type */
322	 0,			/* rightshift */
323	 4,			/* size */
324	 32,			/* bitsize */
325	 false,			/* pc_relative */
326	 0,			/* bitpos */
327	 complain_overflow_bitfield,/* complain_on_overflow */
328	 bfd_elf_generic_reloc,	/* special_function */
329	 "R_CRX_IMM32",		/* name */
330	 false,			/* partial_inplace */
331	 0x0,			/* src_mask */
332	 0xffffffff,		/* dst_mask */
333	 false),		/* pcrel_offset */
334
335  /* An 8 bit switch table entry.  This is generated for an expression
336     such as ``.byte L1 - L2''.  The offset holds the difference
337     between the reloc address and L2.  */
338  HOWTO (R_CRX_SWITCH8,		/* type */
339	 0,			/* rightshift */
340	 1,			/* size */
341	 8,			/* bitsize */
342	 false,			/* pc_relative */
343	 0,			/* bitpos */
344	 complain_overflow_unsigned, /* complain_on_overflow */
345	 bfd_elf_generic_reloc,	/* special_function */
346	 "R_CRX_SWITCH8",	/* name */
347	 false,			/* partial_inplace */
348	 0x0,			/* src_mask */
349	 0xff,			/* dst_mask */
350	 true),			/* pcrel_offset */
351
352  /* A 16 bit switch table entry.  This is generated for an expression
353     such as ``.word L1 - L2''.  The offset holds the difference
354     between the reloc address and L2.  */
355  HOWTO (R_CRX_SWITCH16,	/* type */
356	 0,			/* rightshift */
357	 2,			/* size */
358	 16,			/* bitsize */
359	 false,			/* pc_relative */
360	 0,			/* bitpos */
361	 complain_overflow_unsigned, /* complain_on_overflow */
362	 bfd_elf_generic_reloc,	/* special_function */
363	 "R_CRX_SWITCH16",	/* name */
364	 false,			/* partial_inplace */
365	 0x0,			/* src_mask */
366	 0xffff,		/* dst_mask */
367	 true),			/* pcrel_offset */
368
369  /* A 32 bit switch table entry.  This is generated for an expression
370     such as ``.long L1 - L2''.  The offset holds the difference
371     between the reloc address and L2.  */
372  HOWTO (R_CRX_SWITCH32,	/* type */
373	 0,			/* rightshift */
374	 4,			/* size */
375	 32,			/* bitsize */
376	 false,			/* pc_relative */
377	 0,			/* bitpos */
378	 complain_overflow_unsigned, /* complain_on_overflow */
379	 bfd_elf_generic_reloc,	/* special_function */
380	 "R_CRX_SWITCH32",	/* name */
381	 false,			/* partial_inplace */
382	 0x0,			/* src_mask */
383	 0xffffffff,		/* dst_mask */
384	 true)			/* pcrel_offset */
385};
386
387/* Retrieve a howto ptr using a BFD reloc_code.  */
388
389static reloc_howto_type *
390elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
391			   bfd_reloc_code_real_type code)
392{
393  unsigned int i;
394
395  for (i = 0; i < R_CRX_MAX; i++)
396    if (code == crx_reloc_map[i].bfd_reloc_enum)
397      return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type];
398
399  printf ("This relocation Type is not supported -0x%x\n", code);
400  return 0;
401}
402
403static reloc_howto_type *
404elf_crx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
405			   const char *r_name)
406{
407  unsigned int i;
408
409  for (i = 0;
410       i < sizeof (crx_elf_howto_table) / sizeof (crx_elf_howto_table[0]);
411       i++)
412    if (crx_elf_howto_table[i].name != NULL
413	&& strcasecmp (crx_elf_howto_table[i].name, r_name) == 0)
414      return &crx_elf_howto_table[i];
415
416  return NULL;
417}
418
419/* Retrieve a howto ptr using an internal relocation entry.  */
420
421static bool
422elf_crx_info_to_howto (bfd *abfd, arelent *cache_ptr,
423		       Elf_Internal_Rela *dst)
424{
425  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
426  if (r_type >= R_CRX_MAX)
427    {
428      /* xgettext:c-format */
429      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
430			  abfd, r_type);
431      bfd_set_error (bfd_error_bad_value);
432      return false;
433    }
434  cache_ptr->howto = &crx_elf_howto_table[r_type];
435  return true;
436}
437
438/* Perform a relocation as part of a final link.  */
439
440static bfd_reloc_status_type
441crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
442			     bfd *output_bfd ATTRIBUTE_UNUSED,
443			     asection *input_section, bfd_byte *contents,
444			     bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
445			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
446			     asection *sec ATTRIBUTE_UNUSED,
447			     int is_local ATTRIBUTE_UNUSED)
448{
449  unsigned short r_type = howto->type;
450  bfd_byte *hit_data = contents + offset;
451  bfd_vma reloc_bits, check;
452
453  switch (r_type)
454    {
455     case R_CRX_IMM16:
456     case R_CRX_IMM32:
457     case R_CRX_ABS16:
458     case R_CRX_ABS32:
459     case R_CRX_REL8_CMP:
460     case R_CRX_REL16:
461     case R_CRX_REL24:
462     case R_CRX_REL32:
463     case R_CRX_REGREL12:
464     case R_CRX_REGREL22:
465     case R_CRX_REGREL28:
466     case R_CRX_REGREL32:
467       /* 'hit_data' is relative to the start of the instruction, not the
468	  relocation offset. Advance it to account for the exact offset.  */
469       hit_data += 2;
470       break;
471
472     case R_CRX_REL4:
473       /* This relocation type is used only in 'Branch if Equal to 0'
474	  instructions and requires special handling.  */
475       Rvalue -= 1;
476       break;
477
478     case R_CRX_NONE:
479       return bfd_reloc_ok;
480       break;
481
482     case R_CRX_SWITCH8:
483     case R_CRX_SWITCH16:
484     case R_CRX_SWITCH32:
485       /* We only care about the addend, where the difference between
486	  expressions is kept.  */
487       Rvalue = 0;
488
489     default:
490       break;
491    }
492
493  if (howto->pc_relative)
494    {
495      /* Subtract the address of the section containing the location.  */
496      Rvalue -= (input_section->output_section->vma
497		 + input_section->output_offset);
498      /* Subtract the position of the location within the section.  */
499      Rvalue -= offset;
500    }
501
502  /* Add in supplied addend.  */
503  Rvalue += addend;
504
505  /* Complain if the bitfield overflows, whether it is considered
506     as signed or unsigned.  */
507  check = Rvalue >> howto->rightshift;
508
509  reloc_bits = ((bfd_vma) 1 << (howto->bitsize - 1) << 1) - 1;
510
511  if ((check & ~reloc_bits) != 0
512      && (check & ~reloc_bits) != ((bfd_vma) -1 & ~reloc_bits))
513    {
514      /* The above right shift is incorrect for a signed
515	 value.  See if turning on the upper bits fixes the
516	 overflow.  */
517      if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
518	{
519	  check |= (bfd_vma) -1 & ~((bfd_vma) -1 >> howto->rightshift);
520	  if ((check & ~reloc_bits) != ((bfd_vma) -1 & ~reloc_bits))
521	    return bfd_reloc_overflow;
522	}
523      else
524	return bfd_reloc_overflow;
525    }
526
527  /* Drop unwanted bits from the value we are relocating to.  */
528  Rvalue >>= howto->rightshift;
529
530  /* Apply dst_mask to select only relocatable part of the insn.  */
531  Rvalue &= howto->dst_mask;
532
533  switch (bfd_get_reloc_size (howto))
534    {
535     case 1:
536       if (r_type == R_CRX_REL4)
537	 {
538	   Rvalue <<= 4;
539	   Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
540	 }
541
542       bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
543       break;
544
545     case 2:
546       if (r_type == R_CRX_REGREL12)
547	 Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
548
549       bfd_put_16 (input_bfd, Rvalue, hit_data);
550       break;
551
552     case 4:
553       if (r_type == R_CRX_REL24
554	   || r_type == R_CRX_REGREL22
555	   || r_type == R_CRX_REGREL28)
556	 Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
557		      bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
558
559       if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32)
560	 /* Relocation on DATA is purely little-endian, that is, for a
561	    multi-byte datum, the lowest address in memory contains the
562	    little end of the datum, that is, the least significant byte.
563	    Therefore we use BFD's byte Putting functions.  */
564	 bfd_put_32 (input_bfd, Rvalue, hit_data);
565       else
566	 /* Relocation on INSTRUCTIONS is different : Instructions are
567	    word-addressable, that is, each word itself is arranged according
568	    to little-endian convention, whereas the words are arranged with
569	    respect to one another in BIG ENDIAN fashion.
570	    When there is an immediate value that spans a word boundary, it is
571	    split in a big-endian way with respect to the words.  */
572	 {
573	   bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
574	   bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
575	 }
576     break;
577
578     default:
579       return bfd_reloc_notsupported;
580    }
581
582  return bfd_reloc_ok;
583}
584
585/* Delete some bytes from a section while relaxing.  */
586
587static bool
588elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
589			      asection *sec, bfd_vma addr, int count)
590{
591  Elf_Internal_Shdr *symtab_hdr;
592  unsigned int sec_shndx;
593  bfd_byte *contents;
594  Elf_Internal_Rela *irel, *irelend;
595  bfd_vma toaddr;
596  Elf_Internal_Sym *isym;
597  Elf_Internal_Sym *isymend;
598  struct elf_link_hash_entry **sym_hashes;
599  struct elf_link_hash_entry **end_hashes;
600  struct elf_link_hash_entry **start_hashes;
601  unsigned int symcount;
602
603  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
604
605  contents = elf_section_data (sec)->this_hdr.contents;
606
607  toaddr = sec->size;
608
609  irel = elf_section_data (sec)->relocs;
610  irelend = irel + sec->reloc_count;
611
612  /* Actually delete the bytes.  */
613  memmove (contents + addr, contents + addr + count,
614	   (size_t) (toaddr - addr - count));
615  sec->size -= count;
616
617  /* Adjust all the relocs.  */
618  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
619    {
620      /* Get the new reloc address.  */
621      if ((irel->r_offset > addr
622	   && irel->r_offset < toaddr))
623	irel->r_offset -= count;
624    }
625
626  /* Adjust the local symbols defined in this section.  */
627  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
628  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
629  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
630    {
631      if (isym->st_shndx == sec_shndx
632	  && isym->st_value > addr
633	  && isym->st_value < toaddr)
634	{
635	  /* Adjust the addend of SWITCH relocations in this section,
636	     which reference this local symbol.  */
637	  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
638	    {
639	      unsigned long r_symndx;
640	      Elf_Internal_Sym *rsym;
641	      bfd_vma addsym, subsym;
642
643	      /* Skip if not a SWITCH relocation.  */
644	      if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
645		  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
646		  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
647		  continue;
648
649	      r_symndx = ELF32_R_SYM (irel->r_info);
650	      rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
651
652	      /* Skip if not the local adjusted symbol.  */
653	      if (rsym != isym)
654		continue;
655
656	      addsym = isym->st_value;
657	      subsym = addsym - irel->r_addend;
658
659	      /* Fix the addend only when -->> (addsym > addr >= subsym).  */
660	      if (subsym <= addr)
661		irel->r_addend -= count;
662	      else
663		continue;
664	    }
665
666	  isym->st_value -= count;
667	}
668    }
669
670  /* Now adjust the global symbols defined in this section.  */
671  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
672	      - symtab_hdr->sh_info);
673  sym_hashes = start_hashes = elf_sym_hashes (abfd);
674  end_hashes = sym_hashes + symcount;
675
676  for (; sym_hashes < end_hashes; sym_hashes++)
677    {
678      struct elf_link_hash_entry *sym_hash = *sym_hashes;
679
680      /* The '--wrap SYMBOL' option is causing a pain when the object file,
681	 containing the definition of __wrap_SYMBOL, includes a direct
682	 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
683	 the same symbol (which is __wrap_SYMBOL), but still exist as two
684	 different symbols in 'sym_hashes', we don't want to adjust
685	 the global symbol __wrap_SYMBOL twice.
686	 This check is only relevant when symbols are being wrapped.  */
687      if (link_info->wrap_hash != NULL)
688	{
689	  struct elf_link_hash_entry **cur_sym_hashes;
690
691	  /* Loop only over the symbols whom been already checked.  */
692	  for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
693	       cur_sym_hashes++)
694	    {
695	      /* If the current symbol is identical to 'sym_hash', that means
696		 the symbol was already adjusted (or at least checked).  */
697	      if (*cur_sym_hashes == sym_hash)
698		break;
699	    }
700	  /* Don't adjust the symbol again.  */
701	  if (cur_sym_hashes < sym_hashes)
702	    continue;
703	}
704
705      if ((sym_hash->root.type == bfd_link_hash_defined
706	   || sym_hash->root.type == bfd_link_hash_defweak)
707	  && sym_hash->root.u.def.section == sec
708	  && sym_hash->root.u.def.value > addr
709	  && sym_hash->root.u.def.value < toaddr)
710	sym_hash->root.u.def.value -= count;
711    }
712
713  return true;
714}
715
716/* This is a version of bfd_generic_get_relocated_section_contents
717   which uses elf32_crx_relocate_section.  */
718
719static bfd_byte *
720elf32_crx_get_relocated_section_contents (bfd *output_bfd,
721					  struct bfd_link_info *link_info,
722					  struct bfd_link_order *link_order,
723					  bfd_byte *data,
724					  bool relocatable,
725					  asymbol **symbols)
726{
727  Elf_Internal_Shdr *symtab_hdr;
728  asection *input_section = link_order->u.indirect.section;
729  bfd *input_bfd = input_section->owner;
730  asection **sections = NULL;
731  Elf_Internal_Rela *internal_relocs = NULL;
732  Elf_Internal_Sym *isymbuf = NULL;
733
734  /* We only need to handle the case of relaxing, or of having a
735     particular set of section contents, specially.  */
736  if (relocatable
737      || elf_section_data (input_section)->this_hdr.contents == NULL)
738    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
739						       link_order, data,
740						       relocatable,
741						       symbols);
742
743  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
744
745  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
746	  (size_t) input_section->size);
747
748  if ((input_section->flags & SEC_RELOC) != 0
749      && input_section->reloc_count > 0)
750    {
751      Elf_Internal_Sym *isym;
752      Elf_Internal_Sym *isymend;
753      asection **secpp;
754      bfd_size_type amt;
755
756      internal_relocs = (_bfd_elf_link_read_relocs
757			 (input_bfd, input_section, NULL,
758			  (Elf_Internal_Rela *) NULL, false));
759      if (internal_relocs == NULL)
760	goto error_return;
761
762      if (symtab_hdr->sh_info != 0)
763	{
764	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
765	  if (isymbuf == NULL)
766	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
767					    symtab_hdr->sh_info, 0,
768					    NULL, NULL, NULL);
769	  if (isymbuf == NULL)
770	    goto error_return;
771	}
772
773      amt = symtab_hdr->sh_info;
774      amt *= sizeof (asection *);
775      sections = bfd_malloc (amt);
776      if (sections == NULL && amt != 0)
777	goto error_return;
778
779      isymend = isymbuf + symtab_hdr->sh_info;
780      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
781	{
782	  asection *isec;
783
784	  if (isym->st_shndx == SHN_UNDEF)
785	    isec = bfd_und_section_ptr;
786	  else if (isym->st_shndx == SHN_ABS)
787	    isec = bfd_abs_section_ptr;
788	  else if (isym->st_shndx == SHN_COMMON)
789	    isec = bfd_com_section_ptr;
790	  else
791	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
792
793	  *secpp = isec;
794	}
795
796      if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
797				     input_section, data, internal_relocs,
798				     isymbuf, sections))
799	goto error_return;
800
801      free (sections);
802      if (symtab_hdr->contents != (unsigned char *) isymbuf)
803	free (isymbuf);
804      if (elf_section_data (input_section)->relocs != internal_relocs)
805	free (internal_relocs);
806    }
807
808  return data;
809
810 error_return:
811  free (sections);
812  if (symtab_hdr->contents != (unsigned char *) isymbuf)
813    free (isymbuf);
814  if (elf_section_data (input_section)->relocs != internal_relocs)
815    free (internal_relocs);
816  return NULL;
817}
818
819/* Relocate a CRX ELF section.  */
820
821static int
822elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
823			    bfd *input_bfd, asection *input_section,
824			    bfd_byte *contents, Elf_Internal_Rela *relocs,
825			    Elf_Internal_Sym *local_syms,
826			    asection **local_sections)
827{
828  Elf_Internal_Shdr *symtab_hdr;
829  struct elf_link_hash_entry **sym_hashes;
830  Elf_Internal_Rela *rel, *relend;
831
832  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
833  sym_hashes = elf_sym_hashes (input_bfd);
834
835  rel = relocs;
836  relend = relocs + input_section->reloc_count;
837  for (; rel < relend; rel++)
838    {
839      int r_type;
840      reloc_howto_type *howto;
841      unsigned long r_symndx;
842      Elf_Internal_Sym *sym;
843      asection *sec;
844      struct elf_link_hash_entry *h;
845      bfd_vma relocation;
846      bfd_reloc_status_type r;
847
848      r_symndx = ELF32_R_SYM (rel->r_info);
849      r_type = ELF32_R_TYPE (rel->r_info);
850      howto = crx_elf_howto_table + (r_type);
851
852      h = NULL;
853      sym = NULL;
854      sec = NULL;
855      if (r_symndx < symtab_hdr->sh_info)
856	{
857	  sym = local_syms + r_symndx;
858	  sec = local_sections[r_symndx];
859	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
860	}
861      else
862	{
863	  bool unresolved_reloc, warned, ignored;
864
865	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
866				   r_symndx, symtab_hdr, sym_hashes,
867				   h, sec, relocation,
868				   unresolved_reloc, warned, ignored);
869	}
870
871      if (sec != NULL && discarded_section (sec))
872	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
873					 rel, 1, relend, howto, 0, contents);
874
875      if (bfd_link_relocatable (info))
876	continue;
877
878      r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
879					input_section,
880					contents, rel->r_offset,
881					relocation, rel->r_addend,
882					info, sec, h == NULL);
883
884      if (r != bfd_reloc_ok)
885	{
886	  const char *name;
887	  const char *msg = (const char *) 0;
888
889	  if (h != NULL)
890	    name = h->root.root.string;
891	  else
892	    {
893	      name = (bfd_elf_string_from_elf_section
894		      (input_bfd, symtab_hdr->sh_link, sym->st_name));
895	      if (name == NULL || *name == '\0')
896		name = bfd_section_name (sec);
897	    }
898
899	  switch (r)
900	    {
901	     case bfd_reloc_overflow:
902	       (*info->callbacks->reloc_overflow)
903		 (info, (h ? &h->root : NULL), name, howto->name,
904		  (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
905	       break;
906
907	     case bfd_reloc_undefined:
908	       (*info->callbacks->undefined_symbol)
909		 (info, name, input_bfd, input_section, rel->r_offset, true);
910	       break;
911
912	     case bfd_reloc_outofrange:
913	       msg = _("internal error: out of range error");
914	       goto common_error;
915
916	     case bfd_reloc_notsupported:
917	       msg = _("internal error: unsupported relocation error");
918	       goto common_error;
919
920	     case bfd_reloc_dangerous:
921	       msg = _("internal error: dangerous error");
922	       goto common_error;
923
924	     default:
925	       msg = _("internal error: unknown error");
926	       /* Fall through.  */
927
928	     common_error:
929	       (*info->callbacks->warning) (info, msg, name, input_bfd,
930					    input_section, rel->r_offset);
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 bool
951elf32_crx_relax_section (bfd *abfd, asection *sec,
952			 struct bfd_link_info *link_info, bool *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 (bfd_link_relocatable (link_info)
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, 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 (elf_section_data (sec)->relocs != internal_relocs)
1281    free (internal_relocs);
1282
1283  return true;
1284
1285 error_return:
1286  if (symtab_hdr->contents != (unsigned char *) isymbuf)
1287    free (isymbuf);
1288  if (elf_section_data (sec)->this_hdr.contents != contents)
1289    free (contents);
1290  if (elf_section_data (sec)->relocs != internal_relocs)
1291    free (internal_relocs);
1292
1293  return false;
1294}
1295
1296/* Definitions for setting CRX target vector.  */
1297#define TARGET_LITTLE_SYM		crx_elf32_vec
1298#define TARGET_LITTLE_NAME		"elf32-crx"
1299#define ELF_ARCH			bfd_arch_crx
1300#define ELF_MACHINE_CODE		EM_CRX
1301#define ELF_MAXPAGESIZE			0x1
1302#define elf_symbol_leading_char		'_'
1303
1304#define bfd_elf32_bfd_reloc_type_lookup	elf_crx_reloc_type_lookup
1305#define bfd_elf32_bfd_reloc_name_lookup \
1306					elf_crx_reloc_name_lookup
1307#define elf_info_to_howto		elf_crx_info_to_howto
1308#define elf_info_to_howto_rel		NULL
1309#define elf_backend_relocate_section	elf32_crx_relocate_section
1310#define bfd_elf32_bfd_relax_section	elf32_crx_relax_section
1311#define bfd_elf32_bfd_get_relocated_section_contents \
1312				elf32_crx_get_relocated_section_contents
1313#define elf_backend_can_gc_sections     1
1314#define elf_backend_rela_normal		1
1315
1316#include "elf32-target.h"
1317