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