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