1 /* BFD back-end for National Semiconductor's CRX ELF
2    Copyright 2004 Free Software Foundation, Inc.
3    Written by Tomer Levi, NSC, Israel.
4 
5    This file is part of BFD, the Binary File Descriptor library.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20 
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "bfdlink.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/crx.h"
27 
28 static reloc_howto_type *elf_crx_reloc_type_lookup
29   (bfd *, bfd_reloc_code_real_type);
30 static void elf_crx_info_to_howto
31   (bfd *, arelent *, Elf_Internal_Rela *);
32 static bfd_boolean elf32_crx_relax_delete_bytes
33   (struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
34 static bfd_reloc_status_type crx_elf_final_link_relocate
35   (reloc_howto_type *, bfd *, bfd *, asection *,
36    bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
37    struct bfd_link_info *, asection *, int);
38 static bfd_boolean elf32_crx_relocate_section
39   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
40    Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
41 static asection * elf32_crx_gc_mark_hook
42   (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
43    struct elf_link_hash_entry *, Elf_Internal_Sym *);
44 static bfd_boolean elf32_crx_gc_sweep_hook
45   (bfd *, struct bfd_link_info *, asection *,
46    const Elf_Internal_Rela *);
47 static bfd_boolean elf32_crx_relax_section
48   (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
49 static bfd_byte * elf32_crx_get_relocated_section_contents
50   (bfd *, struct bfd_link_info *, struct bfd_link_order *,
51    bfd_byte *, bfd_boolean, asymbol **);
52 
53 /* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
54 
55 struct crx_reloc_map
56 {
57   bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
58   unsigned short crx_reloc_type;	   /* CRX relocation type.  */
59 };
60 
61 static const struct crx_reloc_map crx_reloc_map[R_CRX_MAX] =
62 {
63   {BFD_RELOC_NONE,	    R_CRX_NONE},
64   {BFD_RELOC_CRX_REL4,	    R_CRX_REL4},
65   {BFD_RELOC_CRX_REL8,	    R_CRX_REL8},
66   {BFD_RELOC_CRX_REL8_CMP,  R_CRX_REL8_CMP},
67   {BFD_RELOC_CRX_REL16,	    R_CRX_REL16},
68   {BFD_RELOC_CRX_REL24,	    R_CRX_REL24},
69   {BFD_RELOC_CRX_REL32,	    R_CRX_REL32},
70   {BFD_RELOC_CRX_REGREL12,  R_CRX_REGREL12},
71   {BFD_RELOC_CRX_REGREL22,  R_CRX_REGREL22},
72   {BFD_RELOC_CRX_REGREL28,  R_CRX_REGREL28},
73   {BFD_RELOC_CRX_REGREL32,  R_CRX_REGREL32},
74   {BFD_RELOC_CRX_ABS16,	    R_CRX_ABS16},
75   {BFD_RELOC_CRX_ABS32,	    R_CRX_ABS32},
76   {BFD_RELOC_CRX_NUM8,	    R_CRX_NUM8},
77   {BFD_RELOC_CRX_NUM16,	    R_CRX_NUM16},
78   {BFD_RELOC_CRX_NUM32,	    R_CRX_NUM32},
79   {BFD_RELOC_CRX_IMM16,	    R_CRX_IMM16},
80   {BFD_RELOC_CRX_IMM32,	    R_CRX_IMM32},
81   {BFD_RELOC_CRX_SWITCH8,   R_CRX_SWITCH8},
82   {BFD_RELOC_CRX_SWITCH16,  R_CRX_SWITCH16},
83   {BFD_RELOC_CRX_SWITCH32,  R_CRX_SWITCH32}
84 };
85 
86 static reloc_howto_type crx_elf_howto_table[] =
87 {
88   HOWTO (R_CRX_NONE,		/* type */
89 	 0,			/* rightshift */
90 	 2,			/* size */
91 	 32,			/* bitsize */
92 	 FALSE,			/* pc_relative */
93 	 0,			/* bitpos */
94 	 complain_overflow_dont,/* complain_on_overflow */
95 	 bfd_elf_generic_reloc,	/* special_function */
96 	 "R_CRX_NONE",		/* name */
97 	 FALSE,			/* partial_inplace */
98 	 0,			/* src_mask */
99 	 0,			/* dst_mask */
100 	 FALSE),		/* pcrel_offset */
101 
102   HOWTO (R_CRX_REL4,		/* type */
103 	 1,			/* rightshift */
104 	 0,			/* size */
105 	 4,			/* bitsize */
106 	 TRUE,			/* pc_relative */
107 	 0,			/* bitpos */
108 	 complain_overflow_bitfield,/* complain_on_overflow */
109 	 bfd_elf_generic_reloc,	/* special_function */
110 	 "R_CRX_REL4",		/* name */
111 	 FALSE,			/* partial_inplace */
112 	 0xf,			/* src_mask */
113 	 0xf,			/* dst_mask */
114 	 FALSE),		/* pcrel_offset */
115 
116   HOWTO (R_CRX_REL8,		/* type */
117 	 1,			/* rightshift */
118 	 0,			/* size */
119 	 8,			/* bitsize */
120 	 TRUE,			/* pc_relative */
121 	 0,			/* bitpos */
122 	 complain_overflow_bitfield,/* complain_on_overflow */
123 	 bfd_elf_generic_reloc,	/* special_function */
124 	 "R_CRX_REL8",		/* name */
125 	 FALSE,			/* partial_inplace */
126 	 0xff,			/* src_mask */
127 	 0xff,			/* dst_mask */
128 	 FALSE),		/* pcrel_offset */
129 
130   HOWTO (R_CRX_REL8_CMP,	/* type */
131 	 1,			/* rightshift */
132 	 0,			/* size */
133 	 8,			/* bitsize */
134 	 TRUE,			/* pc_relative */
135 	 0,			/* bitpos */
136 	 complain_overflow_bitfield,/* complain_on_overflow */
137 	 bfd_elf_generic_reloc,	/* special_function */
138 	 "R_CRX_REL8_CMP",	/* name */
139 	 FALSE,			/* partial_inplace */
140 	 0xff,			/* src_mask */
141 	 0xff,			/* dst_mask */
142 	 FALSE),		/* pcrel_offset */
143 
144   HOWTO (R_CRX_REL16,		/* type */
145 	 1,			/* rightshift */
146 	 1,			/* size */
147 	 16,			/* bitsize */
148 	 TRUE,			/* pc_relative */
149 	 0,			/* bitpos */
150 	 complain_overflow_bitfield,/* complain_on_overflow */
151 	 bfd_elf_generic_reloc,	/* special_function */
152 	 "R_CRX_REL16",		/* name */
153 	 FALSE,			/* partial_inplace */
154 	 0xffff,		/* src_mask */
155 	 0xffff,		/* dst_mask */
156 	 FALSE),		/* pcrel_offset */
157 
158   HOWTO (R_CRX_REL24,		/* type */
159 	 1,			/* rightshift */
160 	 2,			/* size */
161 	 24,			/* bitsize */
162 	 TRUE,			/* pc_relative */
163 	 0,			/* bitpos */
164 	 complain_overflow_bitfield,/* complain_on_overflow */
165 	 bfd_elf_generic_reloc,	/* special_function */
166 	 "R_CRX_REL24",		/* name */
167 	 FALSE,			/* partial_inplace */
168 	 0xffffff,		/* src_mask */
169 	 0xffffff,		/* dst_mask */
170 	 FALSE),		/* pcrel_offset */
171 
172   HOWTO (R_CRX_REL32,		/* type */
173 	 1,			/* rightshift */
174 	 2,			/* size */
175 	 32,			/* bitsize */
176 	 TRUE,			/* pc_relative */
177 	 0,			/* bitpos */
178 	 complain_overflow_bitfield,/* complain_on_overflow */
179 	 bfd_elf_generic_reloc,	/* special_function */
180 	 "R_CRX_REL32",		/* name */
181 	 FALSE,			/* partial_inplace */
182 	 0xffffffff,		/* src_mask */
183 	 0xffffffff,		/* dst_mask */
184 	 FALSE),		/* pcrel_offset */
185 
186   HOWTO (R_CRX_REGREL12,	/* type */
187 	 0,			/* rightshift */
188 	 1,			/* size */
189 	 12,			/* bitsize */
190 	 FALSE,			/* pc_relative */
191 	 0,			/* bitpos */
192 	 complain_overflow_bitfield,/* complain_on_overflow */
193 	 bfd_elf_generic_reloc,	/* special_function */
194 	 "R_CRX_REGREL12",	/* name */
195 	 FALSE,			/* partial_inplace */
196 	 0xfff,			/* src_mask */
197 	 0xfff,			/* dst_mask */
198 	 FALSE),		/* pcrel_offset */
199 
200   HOWTO (R_CRX_REGREL22,	/* type */
201 	 0,			/* rightshift */
202 	 2,			/* size */
203 	 22,			/* bitsize */
204 	 FALSE,			/* pc_relative */
205 	 0,			/* bitpos */
206 	 complain_overflow_bitfield,/* complain_on_overflow */
207 	 bfd_elf_generic_reloc,	/* special_function */
208 	 "R_CRX_REGREL22",	/* name */
209 	 FALSE,			/* partial_inplace */
210 	 0x3fffff,		/* src_mask */
211 	 0x3fffff,		/* dst_mask */
212 	 FALSE),		/* pcrel_offset */
213 
214   HOWTO (R_CRX_REGREL28,	/* type */
215 	 0,			/* rightshift */
216 	 2,			/* size */
217 	 28,			/* bitsize */
218 	 FALSE,			/* pc_relative */
219 	 0,			/* bitpos */
220 	 complain_overflow_bitfield,/* complain_on_overflow */
221 	 bfd_elf_generic_reloc,	/* special_function */
222 	 "R_CRX_REGREL28",	/* name */
223 	 FALSE,			/* partial_inplace */
224 	 0xfffffff,		/* src_mask */
225 	 0xfffffff,		/* dst_mask */
226 	 FALSE),		/* pcrel_offset */
227 
228   HOWTO (R_CRX_REGREL32,	/* type */
229 	 0,			/* rightshift */
230 	 2,			/* size */
231 	 32,			/* bitsize */
232 	 FALSE,			/* pc_relative */
233 	 0,			/* bitpos */
234 	 complain_overflow_bitfield,/* complain_on_overflow */
235 	 bfd_elf_generic_reloc,	/* special_function */
236 	 "R_CRX_REGREL32",	/* name */
237 	 FALSE,			/* partial_inplace */
238 	 0xffffffff,		/* src_mask */
239 	 0xffffffff,		/* dst_mask */
240 	 FALSE),		/* pcrel_offset */
241 
242   HOWTO (R_CRX_ABS16,		/* type */
243 	 0,			/* rightshift */
244 	 1,			/* size */
245 	 16,			/* bitsize */
246 	 FALSE,			/* pc_relative */
247 	 0,			/* bitpos */
248 	 complain_overflow_bitfield,/* complain_on_overflow */
249 	 bfd_elf_generic_reloc,	/* special_function */
250 	 "R_CRX_ABS16",		/* name */
251 	 FALSE,			/* partial_inplace */
252 	 0xffff,		/* src_mask */
253 	 0xffff,		/* dst_mask */
254 	 FALSE),		/* pcrel_offset */
255 
256   HOWTO (R_CRX_ABS32,		/* type */
257 	 0,			/* rightshift */
258 	 2,			/* size */
259 	 32,			/* bitsize */
260 	 FALSE,			/* pc_relative */
261 	 0,			/* bitpos */
262 	 complain_overflow_bitfield,/* complain_on_overflow */
263 	 bfd_elf_generic_reloc,	/* special_function */
264 	 "R_CRX_ABS32",		/* name */
265 	 FALSE,			/* partial_inplace */
266 	 0xffffffff,		/* src_mask */
267 	 0xffffffff,		/* dst_mask */
268 	 FALSE),		/* pcrel_offset */
269 
270   HOWTO (R_CRX_NUM8,		/* type */
271 	 0,			/* rightshift */
272 	 0,			/* size */
273 	 8,			/* bitsize */
274 	 FALSE,			/* pc_relative */
275 	 0,			/* bitpos */
276 	 complain_overflow_bitfield,/* complain_on_overflow */
277 	 bfd_elf_generic_reloc,	/* special_function */
278 	 "R_CRX_NUM8",		/* name */
279 	 FALSE,			/* partial_inplace */
280 	 0xff,	  		/* src_mask */
281 	 0xff,			/* dst_mask */
282 	 FALSE),		/* pcrel_offset */
283 
284   HOWTO (R_CRX_NUM16,		/* type */
285 	 0,			/* rightshift */
286 	 1,			/* size */
287 	 16,			/* bitsize */
288 	 FALSE,			/* pc_relative */
289 	 0,			/* bitpos */
290 	 complain_overflow_bitfield,/* complain_on_overflow */
291 	 bfd_elf_generic_reloc,	/* special_function */
292 	 "R_CRX_NUM16",		/* name */
293 	 FALSE,			/* partial_inplace */
294 	 0xffff,  		/* src_mask */
295 	 0xffff,		/* dst_mask */
296 	 FALSE),		/* pcrel_offset */
297 
298   HOWTO (R_CRX_NUM32,		/* type */
299 	 0,			/* rightshift */
300 	 2,			/* size */
301 	 32,			/* bitsize */
302 	 FALSE,			/* pc_relative */
303 	 0,			/* bitpos */
304 	 complain_overflow_bitfield,/* complain_on_overflow */
305 	 bfd_elf_generic_reloc,	/* special_function */
306 	 "R_CRX_NUM32",		/* name */
307 	 FALSE,			/* partial_inplace */
308 	 0xffffffff,  		/* src_mask */
309 	 0xffffffff,		/* dst_mask */
310 	 FALSE),		/* pcrel_offset */
311 
312   HOWTO (R_CRX_IMM16,		/* type */
313 	 0,			/* rightshift */
314 	 1,			/* size */
315 	 16,			/* bitsize */
316 	 FALSE,			/* pc_relative */
317 	 0,			/* bitpos */
318 	 complain_overflow_bitfield,/* complain_on_overflow */
319 	 bfd_elf_generic_reloc,	/* special_function */
320 	 "R_CRX_IMM16",		/* name */
321 	 FALSE,			/* partial_inplace */
322 	 0xffff,  		/* src_mask */
323 	 0xffff,		/* dst_mask */
324 	 FALSE),		/* pcrel_offset */
325 
326   HOWTO (R_CRX_IMM32,		/* type */
327 	 0,			/* rightshift */
328 	 2,			/* size */
329 	 32,			/* bitsize */
330 	 FALSE,			/* pc_relative */
331 	 0,			/* bitpos */
332 	 complain_overflow_bitfield,/* complain_on_overflow */
333 	 bfd_elf_generic_reloc,	/* special_function */
334 	 "R_CRX_IMM32",		/* name */
335 	 FALSE,			/* partial_inplace */
336 	 0xffffffff,  		/* src_mask */
337 	 0xffffffff,		/* dst_mask */
338 	 FALSE),		/* pcrel_offset */
339 
340   /* An 8 bit switch table entry.  This is generated for an expression
341      such as ``.byte L1 - L2''.  The offset holds the difference
342      between the reloc address and L2.  */
343   HOWTO (R_CRX_SWITCH8,		/* type */
344 	 0,			/* rightshift */
345 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
346 	 8,			/* bitsize */
347 	 FALSE,			/* pc_relative */
348 	 0,			/* bitpos */
349 	 complain_overflow_unsigned, /* complain_on_overflow */
350 	 bfd_elf_generic_reloc,	/* special_function */
351 	 "R_CRX_SWITCH8",	/* name */
352 	 FALSE,			/* partial_inplace */
353 	 0xff,			/* src_mask */
354 	 0xff,			/* dst_mask */
355 	 TRUE),			/* pcrel_offset */
356 
357   /* A 16 bit switch table entry.  This is generated for an expression
358      such as ``.word L1 - L2''.  The offset holds the difference
359      between the reloc address and L2.  */
360   HOWTO (R_CRX_SWITCH16,	/* type */
361 	 0,			/* rightshift */
362 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
363 	 16,			/* bitsize */
364 	 FALSE,			/* pc_relative */
365 	 0,			/* bitpos */
366 	 complain_overflow_unsigned, /* complain_on_overflow */
367 	 bfd_elf_generic_reloc,	/* special_function */
368 	 "R_CRX_SWITCH16",	/* name */
369 	 FALSE,			/* partial_inplace */
370 	 0xffff,		/* src_mask */
371 	 0xffff,		/* dst_mask */
372 	 TRUE),			/* pcrel_offset */
373 
374   /* A 32 bit switch table entry.  This is generated for an expression
375      such as ``.long L1 - L2''.  The offset holds the difference
376      between the reloc address and L2.  */
377   HOWTO (R_CRX_SWITCH32,	/* type */
378 	 0,			/* rightshift */
379 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
380 	 32,			/* bitsize */
381 	 FALSE,			/* pc_relative */
382 	 0,			/* bitpos */
383 	 complain_overflow_unsigned, /* complain_on_overflow */
384 	 bfd_elf_generic_reloc,	/* special_function */
385 	 "R_CRX_SWITCH32",	/* name */
386 	 FALSE,			/* partial_inplace */
387 	 0xffffffff,		/* src_mask */
388 	 0xffffffff,		/* dst_mask */
389 	 TRUE)			/* pcrel_offset */
390 };
391 
392 /* Retrieve a howto ptr using a BFD reloc_code.  */
393 
394 static reloc_howto_type *
elf_crx_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)395 elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
396 			   bfd_reloc_code_real_type code)
397 {
398   unsigned int i;
399 
400   for (i = 0; i < R_CRX_MAX; i++)
401     if (code == crx_reloc_map[i].bfd_reloc_enum)
402       return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type];
403 
404   printf ("This relocation Type is not supported -0x%x\n", code);
405   return 0;
406 }
407 
408 /* Retrieve a howto ptr using an internal relocation entry.  */
409 
410 static void
elf_crx_info_to_howto(bfd * abfd ATTRIBUTE_UNUSED,arelent * cache_ptr,Elf_Internal_Rela * dst)411 elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
412 		       Elf_Internal_Rela *dst)
413 {
414   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
415   BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
416   cache_ptr->howto = &crx_elf_howto_table[r_type];
417 }
418 
419 /* Perform a relocation as part of a final link.  */
420 
421 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)422 crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
423 			     bfd *output_bfd ATTRIBUTE_UNUSED,
424 			     asection *input_section, bfd_byte *contents,
425 			     bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
426 			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
427 			     asection *sec ATTRIBUTE_UNUSED,
428 			     int is_local ATTRIBUTE_UNUSED)
429 {
430   unsigned short r_type = howto->type;
431   bfd_byte *hit_data = contents + offset;
432   bfd_vma reloc_bits, check;
433 
434   switch (r_type)
435     {
436      case R_CRX_IMM16:
437      case R_CRX_IMM32:
438      case R_CRX_ABS16:
439      case R_CRX_ABS32:
440      case R_CRX_REL8_CMP:
441      case R_CRX_REL16:
442      case R_CRX_REL24:
443      case R_CRX_REL32:
444      case R_CRX_REGREL12:
445      case R_CRX_REGREL22:
446      case R_CRX_REGREL28:
447      case R_CRX_REGREL32:
448        /* 'hit_data' is relative to the start of the instruction, not the
449 	  relocation offset. Advance it to account for the exact offset.  */
450        hit_data += 2;
451        break;
452 
453      case R_CRX_REL4:
454        /* This relocation type is used only in 'Branch if Equal to 0'
455 	  instructions and requires special handling.  */
456        Rvalue -= 1;
457        break;
458 
459      case R_CRX_NONE:
460        return bfd_reloc_ok;
461        break;
462 
463      case R_CRX_SWITCH8:
464      case R_CRX_SWITCH16:
465      case R_CRX_SWITCH32:
466        /* We only care about the addend, where the difference between
467 	  expressions is kept.  */
468        Rvalue = 0;
469 
470      default:
471        break;
472     }
473 
474   if (howto->pc_relative)
475     {
476       /* Subtract the address of the section containing the location.  */
477       Rvalue -= (input_section->output_section->vma
478 		 + input_section->output_offset);
479       /* Subtract the position of the location within the section.  */
480       Rvalue -= offset;
481     }
482 
483   /* Add in supplied addend.  */
484   Rvalue += addend;
485 
486   /* Complain if the bitfield overflows, whether it is considered
487      as signed or unsigned.  */
488   check = Rvalue >> howto->rightshift;
489 
490   /* Assumes two's complement.  This expression avoids
491      overflow if howto->bitsize is the number of bits in
492      bfd_vma.  */
493   reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
494 
495   if (((bfd_vma) check & ~reloc_bits) != 0
496       && (((bfd_vma) check & ~reloc_bits)
497 	  != (-(bfd_vma) 1 & ~reloc_bits)))
498     {
499       /* The above right shift is incorrect for a signed
500 	 value.  See if turning on the upper bits fixes the
501 	 overflow.  */
502       if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
503 	{
504 	  check |= ((bfd_vma) - 1
505 		    & ~((bfd_vma) - 1
506 			>> howto->rightshift));
507 	  if (((bfd_vma) check & ~reloc_bits)
508 	      != (-(bfd_vma) 1 & ~reloc_bits))
509 	    return bfd_reloc_overflow;
510 	}
511       else
512 	return bfd_reloc_overflow;
513     }
514 
515   /* Drop unwanted bits from the value we are relocating to.  */
516   Rvalue >>= (bfd_vma) howto->rightshift;
517 
518   /* Apply dst_mask to select only relocatable part of the insn.  */
519   Rvalue &= howto->dst_mask;
520 
521   switch (howto->size)
522     {
523      case 0:
524        if (r_type == R_CRX_REL4)
525 	 {
526 	   Rvalue <<= 4;
527 	   Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
528 	 }
529 
530        bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
531        break;
532 
533      case 1:
534        if (r_type == R_CRX_REGREL12)
535 	 Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
536 
537        bfd_put_16 (input_bfd, Rvalue, hit_data);
538        break;
539 
540      case 2:
541        if (r_type == R_CRX_REL24
542 	   || r_type == R_CRX_REGREL22
543 	   || r_type == R_CRX_REGREL28)
544 	 Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
545 		      bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
546 
547        if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32)
548 	 /* Relocation on DATA is purely little-endian, that is, for a
549 	    multi-byte datum, the lowest address in memory contains the
550 	    little end of the datum, that is, the least significant byte.
551 	    Therefore we use BFD's byte Putting functions.  */
552 	 bfd_put_32 (input_bfd, Rvalue, hit_data);
553        else
554 	 /* Relocation on INSTRUCTIONS is different : Instructions are
555 	    word-addressable, that is, each word itself is arranged according
556 	    to little-endian convention, whereas the words are arranged with
557 	    respect to one another in BIG ENDIAN fashion.
558 	    When there is an immediate value that spans a word boundary, it is
559 	    split in a big-endian way with respect to the words.  */
560 	 {
561 	   bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
562 	   bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
563 	 }
564      break;
565 
566      default:
567        return bfd_reloc_notsupported;
568     }
569 
570   return bfd_reloc_ok;
571 }
572 
573 /* Delete some bytes from a section while relaxing.  */
574 
575 static bfd_boolean
elf32_crx_relax_delete_bytes(struct bfd_link_info * link_info,bfd * abfd,asection * sec,bfd_vma addr,int count)576 elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
577 			      asection *sec, bfd_vma addr, int count)
578 {
579   Elf_Internal_Shdr *symtab_hdr;
580   unsigned int sec_shndx;
581   bfd_byte *contents;
582   Elf_Internal_Rela *irel, *irelend;
583   Elf_Internal_Rela *irelalign;
584   bfd_vma toaddr;
585   Elf_Internal_Sym *isym;
586   Elf_Internal_Sym *isymend;
587   struct elf_link_hash_entry **sym_hashes;
588   struct elf_link_hash_entry **end_hashes;
589   struct elf_link_hash_entry **start_hashes;
590   unsigned int symcount;
591 
592   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
593 
594   contents = elf_section_data (sec)->this_hdr.contents;
595 
596   /* The deletion must stop at the next ALIGN reloc for an aligment
597      power larger than the number of bytes we are deleting.  */
598 
599   irelalign = NULL;
600   toaddr = sec->size;
601 
602   irel = elf_section_data (sec)->relocs;
603   irelend = irel + sec->reloc_count;
604 
605   /* Actually delete the bytes.  */
606   memmove (contents + addr, contents + addr + count,
607 	   (size_t) (toaddr - addr - count));
608   sec->size -= count;
609 
610   /* Adjust all the relocs.  */
611   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
612     {
613       /* Get the new reloc address.  */
614       if ((irel->r_offset > addr
615 	   && irel->r_offset < toaddr))
616 	irel->r_offset -= count;
617     }
618 
619   /* Adjust the local symbols defined in this section.  */
620   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
621   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
622   for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
623     {
624       if (isym->st_shndx == sec_shndx
625 	  && isym->st_value > addr
626 	  && isym->st_value < toaddr)
627 	{
628 	  /* Adjust the addend of SWITCH relocations in this section,
629 	     which reference this local symbol.  */
630 	  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
631 	    {
632 	      unsigned long r_symndx;
633 	      Elf_Internal_Sym *rsym;
634 	      bfd_vma addsym, subsym;
635 
636 	      /* Skip if not a SWITCH relocation.  */
637 	      if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
638 		  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
639 		  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
640 		  continue;
641 
642 	      r_symndx = ELF32_R_SYM (irel->r_info);
643 	      rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
644 
645 	      /* Skip if not the local adjusted symbol.  */
646 	      if (rsym != isym)
647 		continue;
648 
649 	      addsym = isym->st_value;
650 	      subsym = addsym - irel->r_addend;
651 
652 	      /* Fix the addend only when -->> (addsym > addr >= subsym).  */
653 	      if (subsym <= addr)
654 		irel->r_addend -= count;
655 	      else
656 		continue;
657 	    }
658 
659 	  isym->st_value -= count;
660 	}
661     }
662 
663   /* Now adjust the global symbols defined in this section.  */
664   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
665 	      - symtab_hdr->sh_info);
666   sym_hashes = start_hashes = elf_sym_hashes (abfd);
667   end_hashes = sym_hashes + symcount;
668 
669   for (; sym_hashes < end_hashes; sym_hashes++)
670     {
671       struct elf_link_hash_entry *sym_hash = *sym_hashes;
672 
673       /* The '--wrap SYMBOL' option is causing a pain when the object file,
674 	 containing the definition of __wrap_SYMBOL, includes a direct
675 	 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
676 	 the same symbol (which is __wrap_SYMBOL), but still exist as two
677 	 different symbols in 'sym_hashes', we don't want to adjust
678 	 the global symbol __wrap_SYMBOL twice.
679 	 This check is only relevant when symbols are being wrapped.  */
680       if (link_info->wrap_hash != NULL)
681 	{
682 	  struct elf_link_hash_entry **cur_sym_hashes;
683 
684 	  /* Loop only over the symbols whom been already checked.  */
685 	  for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
686 	       cur_sym_hashes++)
687 	    {
688 	      /* If the current symbol is identical to 'sym_hash', that means
689 		 the symbol was already adjusted (or at least checked).  */
690 	      if (*cur_sym_hashes == sym_hash)
691 		break;
692 	    }
693 	  /* Don't adjust the symbol again.  */
694 	  if (cur_sym_hashes < sym_hashes)
695 	    continue;
696 	}
697 
698       if ((sym_hash->root.type == bfd_link_hash_defined
699 	   || sym_hash->root.type == bfd_link_hash_defweak)
700 	  && sym_hash->root.u.def.section == sec
701 	  && sym_hash->root.u.def.value > addr
702 	  && sym_hash->root.u.def.value < toaddr)
703 	sym_hash->root.u.def.value -= count;
704     }
705 
706   return TRUE;
707 }
708 
709 /* This is a version of bfd_generic_get_relocated_section_contents
710    which uses elf32_crx_relocate_section.  */
711 
712 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)713 elf32_crx_get_relocated_section_contents (bfd *output_bfd,
714 					  struct bfd_link_info *link_info,
715 					  struct bfd_link_order *link_order,
716 					  bfd_byte *data,
717 					  bfd_boolean relocatable,
718 					  asymbol **symbols)
719 {
720   Elf_Internal_Shdr *symtab_hdr;
721   asection *input_section = link_order->u.indirect.section;
722   bfd *input_bfd = input_section->owner;
723   asection **sections = NULL;
724   Elf_Internal_Rela *internal_relocs = NULL;
725   Elf_Internal_Sym *isymbuf = NULL;
726 
727   /* We only need to handle the case of relaxing, or of having a
728      particular set of section contents, specially.  */
729   if (relocatable
730       || elf_section_data (input_section)->this_hdr.contents == NULL)
731     return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
732 						       link_order, data,
733 						       relocatable,
734 						       symbols);
735 
736   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
737 
738   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
739 	  (size_t) input_section->size);
740 
741   if ((input_section->flags & SEC_RELOC) != 0
742       && input_section->reloc_count > 0)
743     {
744       Elf_Internal_Sym *isym;
745       Elf_Internal_Sym *isymend;
746       asection **secpp;
747       bfd_size_type amt;
748 
749       internal_relocs = (_bfd_elf_link_read_relocs
750 			 (input_bfd, input_section, (PTR) NULL,
751 			  (Elf_Internal_Rela *) NULL, FALSE));
752       if (internal_relocs == NULL)
753 	goto error_return;
754 
755       if (symtab_hdr->sh_info != 0)
756 	{
757 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
758 	  if (isymbuf == NULL)
759 	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
760 					    symtab_hdr->sh_info, 0,
761 					    NULL, NULL, NULL);
762 	  if (isymbuf == NULL)
763 	    goto error_return;
764 	}
765 
766       amt = symtab_hdr->sh_info;
767       amt *= sizeof (asection *);
768       sections = bfd_malloc (amt);
769       if (sections == NULL && amt != 0)
770 	goto error_return;
771 
772       isymend = isymbuf + symtab_hdr->sh_info;
773       for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
774 	{
775 	  asection *isec;
776 
777 	  if (isym->st_shndx == SHN_UNDEF)
778 	    isec = bfd_und_section_ptr;
779 	  else if (isym->st_shndx == SHN_ABS)
780 	    isec = bfd_abs_section_ptr;
781 	  else if (isym->st_shndx == SHN_COMMON)
782 	    isec = bfd_com_section_ptr;
783 	  else
784 	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
785 
786 	  *secpp = isec;
787 	}
788 
789       if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
790 				     input_section, data, internal_relocs,
791 				     isymbuf, sections))
792 	goto error_return;
793 
794       if (sections != NULL)
795 	free (sections);
796       if (isymbuf != NULL
797 	  && symtab_hdr->contents != (unsigned char *) isymbuf)
798 	free (isymbuf);
799       if (elf_section_data (input_section)->relocs != internal_relocs)
800 	free (internal_relocs);
801     }
802 
803   return data;
804 
805  error_return:
806   if (sections != NULL)
807     free (sections);
808   if (isymbuf != NULL
809       && symtab_hdr->contents != (unsigned char *) isymbuf)
810     free (isymbuf);
811   if (internal_relocs != NULL
812       && elf_section_data (input_section)->relocs != internal_relocs)
813     free (internal_relocs);
814   return NULL;
815 }
816 
817 /* Relocate a CRX ELF section.  */
818 
819 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)820 elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
821 			    bfd *input_bfd, asection *input_section,
822 			    bfd_byte *contents, Elf_Internal_Rela *relocs,
823 			    Elf_Internal_Sym *local_syms,
824 			    asection **local_sections)
825 {
826   Elf_Internal_Shdr *symtab_hdr;
827   struct elf_link_hash_entry **sym_hashes;
828   Elf_Internal_Rela *rel, *relend;
829 
830   if (info->relocatable)
831     return TRUE;
832 
833   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
834   sym_hashes = elf_sym_hashes (input_bfd);
835 
836   rel = relocs;
837   relend = relocs + input_section->reloc_count;
838   for (; rel < relend; rel++)
839     {
840       int r_type;
841       reloc_howto_type *howto;
842       unsigned long r_symndx;
843       Elf_Internal_Sym *sym;
844       asection *sec;
845       struct elf_link_hash_entry *h;
846       bfd_vma relocation;
847       bfd_reloc_status_type r;
848 
849       r_symndx = ELF32_R_SYM (rel->r_info);
850       r_type = ELF32_R_TYPE (rel->r_info);
851       howto = crx_elf_howto_table + (r_type);
852 
853       h = NULL;
854       sym = NULL;
855       sec = NULL;
856       if (r_symndx < symtab_hdr->sh_info)
857 	{
858 	  sym = local_syms + r_symndx;
859 	  sec = local_sections[r_symndx];
860 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
861 	}
862       else
863 	{
864 	  bfd_boolean unresolved_reloc, warned;
865 
866 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
867 				   r_symndx, symtab_hdr, sym_hashes,
868 				   h, sec, relocation,
869 				   unresolved_reloc, warned);
870 	}
871 
872       r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
873 					input_section,
874 					contents, rel->r_offset,
875 					relocation, rel->r_addend,
876 					info, sec, h == NULL);
877 
878       if (r != bfd_reloc_ok)
879 	{
880 	  const char *name;
881 	  const char *msg = (const char *) 0;
882 
883 	  if (h != NULL)
884 	    name = h->root.root.string;
885 	  else
886 	    {
887 	      name = (bfd_elf_string_from_elf_section
888 		      (input_bfd, symtab_hdr->sh_link, sym->st_name));
889 	      if (name == NULL || *name == '\0')
890 		name = bfd_section_name (input_bfd, sec);
891 	    }
892 
893 	  switch (r)
894 	    {
895 	     case bfd_reloc_overflow:
896 	       if (!((*info->callbacks->reloc_overflow)
897 		     (info, (h ? &h->root : NULL), name, howto->name,
898 		      (bfd_vma) 0, input_bfd, input_section,
899 		      rel->r_offset)))
900 		 return FALSE;
901 	       break;
902 
903 	     case bfd_reloc_undefined:
904 	       if (!((*info->callbacks->undefined_symbol)
905 		     (info, name, input_bfd, input_section,
906 		      rel->r_offset, TRUE)))
907 		 return FALSE;
908 	       break;
909 
910 	     case bfd_reloc_outofrange:
911 	       msg = _("internal error: out of range error");
912 	       goto common_error;
913 
914 	     case bfd_reloc_notsupported:
915 	       msg = _("internal error: unsupported relocation error");
916 	       goto common_error;
917 
918 	     case bfd_reloc_dangerous:
919 	       msg = _("internal error: dangerous error");
920 	       goto common_error;
921 
922 	     default:
923 	       msg = _("internal error: unknown error");
924 	       /* Fall through.  */
925 
926 	     common_error:
927 	       if (!((*info->callbacks->warning)
928 		     (info, msg, name, input_bfd, input_section,
929 		      rel->r_offset)))
930 		 return FALSE;
931 	       break;
932 	    }
933 	}
934     }
935 
936   return TRUE;
937 }
938 
939 /* This function handles relaxing for the CRX.
940 
941    There's quite a few relaxing opportunites available on the CRX:
942 
943 	* bal/bcond:32 -> bal/bcond:16				   2 bytes
944 	* bcond:16 -> bcond:8					   2 bytes
945 	* cmpbcond:24 -> cmpbcond:8				   2 bytes
946 	* arithmetic imm32 -> arithmetic imm16			   2 bytes
947 
948    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
949 
950 static bfd_boolean
elf32_crx_relax_section(bfd * abfd,asection * sec,struct bfd_link_info * link_info,bfd_boolean * again)951 elf32_crx_relax_section (bfd *abfd, asection *sec,
952 			 struct bfd_link_info *link_info, bfd_boolean *again)
953 {
954   Elf_Internal_Shdr *symtab_hdr;
955   Elf_Internal_Rela *internal_relocs;
956   Elf_Internal_Rela *irel, *irelend;
957   bfd_byte *contents = NULL;
958   Elf_Internal_Sym *isymbuf = NULL;
959 
960   /* Assume nothing changes.  */
961   *again = FALSE;
962 
963   /* We don't have to do anything for a relocatable link, if
964      this section does not have relocs, or if this is not a
965      code section.  */
966   if (link_info->relocatable
967       || (sec->flags & SEC_RELOC) == 0
968       || sec->reloc_count == 0
969       || (sec->flags & SEC_CODE) == 0)
970     return TRUE;
971 
972   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
973 
974   /* Get a copy of the native relocations.  */
975   internal_relocs = (_bfd_elf_link_read_relocs
976 		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
977 		      link_info->keep_memory));
978   if (internal_relocs == NULL)
979     goto error_return;
980 
981   /* Walk through them looking for relaxing opportunities.  */
982   irelend = internal_relocs + sec->reloc_count;
983   for (irel = internal_relocs; irel < irelend; irel++)
984     {
985       bfd_vma symval;
986 
987       /* If this isn't something that can be relaxed, then ignore
988 	 this reloc.  */
989       if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
990 	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
991 	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
992 	  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
993 	continue;
994 
995       /* Get the section contents if we haven't done so already.  */
996       if (contents == NULL)
997 	{
998 	  /* Get cached copy if it exists.  */
999 	  if (elf_section_data (sec)->this_hdr.contents != NULL)
1000 	    contents = elf_section_data (sec)->this_hdr.contents;
1001 	  /* Go get them off disk.  */
1002 	  else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1003 	    goto error_return;
1004 	}
1005 
1006       /* Read this BFD's local symbols if we haven't done so already.  */
1007       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1008 	{
1009 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1010 	  if (isymbuf == NULL)
1011 	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1012 					    symtab_hdr->sh_info, 0,
1013 					    NULL, NULL, NULL);
1014 	  if (isymbuf == NULL)
1015 	    goto error_return;
1016 	}
1017 
1018       /* Get the value of the symbol referred to by the reloc.  */
1019       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1020 	{
1021 	  /* A local symbol.  */
1022 	  Elf_Internal_Sym *isym;
1023 	  asection *sym_sec;
1024 
1025 	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
1026 	  if (isym->st_shndx == SHN_UNDEF)
1027 	    sym_sec = bfd_und_section_ptr;
1028 	  else if (isym->st_shndx == SHN_ABS)
1029 	    sym_sec = bfd_abs_section_ptr;
1030 	  else if (isym->st_shndx == SHN_COMMON)
1031 	    sym_sec = bfd_com_section_ptr;
1032 	  else
1033 	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1034 	  symval = (isym->st_value
1035 		    + sym_sec->output_section->vma
1036 		    + sym_sec->output_offset);
1037 	}
1038       else
1039 	{
1040 	  unsigned long indx;
1041 	  struct elf_link_hash_entry *h;
1042 
1043 	  /* An external symbol.  */
1044 	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1045 	  h = elf_sym_hashes (abfd)[indx];
1046 	  BFD_ASSERT (h != NULL);
1047 
1048 	  if (h->root.type != bfd_link_hash_defined
1049 	      && h->root.type != bfd_link_hash_defweak)
1050 	    /* This appears to be a reference to an undefined
1051 	       symbol.  Just ignore it--it will be caught by the
1052 	       regular reloc processing.  */
1053 	    continue;
1054 
1055 	  symval = (h->root.u.def.value
1056 		    + h->root.u.def.section->output_section->vma
1057 		    + h->root.u.def.section->output_offset);
1058 	}
1059 
1060       /* For simplicity of coding, we are going to modify the section
1061 	 contents, the section relocs, and the BFD symbol table.  We
1062 	 must tell the rest of the code not to free up this
1063 	 information.  It would be possible to instead create a table
1064 	 of changes which have to be made, as is done in coff-mips.c;
1065 	 that would be more work, but would require less memory when
1066 	 the linker is run.  */
1067 
1068       /* Try to turn a 32bit pc-relative branch/call into
1069 	 a 16bit pc-relative branch/call.  */
1070       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
1071 	{
1072 	  bfd_vma value = symval;
1073 
1074 	  /* Deal with pc-relative gunk.  */
1075 	  value -= (sec->output_section->vma + sec->output_offset);
1076 	  value -= irel->r_offset;
1077 	  value += irel->r_addend;
1078 
1079 	  /* See if the value will fit in 16 bits, note the high value is
1080 	     0xfffe + 2 as the target will be two bytes closer if we are
1081 	     able to relax.  */
1082 	  if ((long) value < 0x10000 && (long) value > -0x10002)
1083 	    {
1084 	      unsigned short code;
1085 
1086 	      /* Get the opcode.  */
1087 	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1088 
1089 	      /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
1090 	      if ((code & 0xfff0) == 0x3170)
1091 		bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1092 	      else if ((code & 0xf0ff) == 0x707f)
1093 		bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
1094 	      else
1095 		continue;
1096 
1097 	      /* Note that we've changed the relocs, section contents, etc.  */
1098 	      elf_section_data (sec)->relocs = internal_relocs;
1099 	      elf_section_data (sec)->this_hdr.contents = contents;
1100 	      symtab_hdr->contents = (unsigned char *) isymbuf;
1101 
1102 	      /* Fix the relocation's type.  */
1103 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1104 					   R_CRX_REL16);
1105 
1106 	      /* Delete two bytes of data.  */
1107 	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1108 						   irel->r_offset + 2, 2))
1109 		goto error_return;
1110 
1111 	      /* That will change things, so, we should relax again.
1112 		 Note that this is not required, and it may be slow.  */
1113 	      *again = TRUE;
1114 	    }
1115 	}
1116 
1117       /* Try to turn a 16bit pc-relative branch into an
1118 	 8bit pc-relative branch.  */
1119       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
1120 	{
1121 	  bfd_vma value = symval;
1122 
1123 	  /* Deal with pc-relative gunk.  */
1124 	  value -= (sec->output_section->vma + sec->output_offset);
1125 	  value -= irel->r_offset;
1126 	  value += irel->r_addend;
1127 
1128 	  /* See if the value will fit in 8 bits, note the high value is
1129 	     0xfc + 2 as the target will be two bytes closer if we are
1130 	     able to relax.  */
1131 	  if ((long) value < 0xfe && (long) value > -0x100)
1132 	    {
1133 	      unsigned short code;
1134 
1135 	      /* Get the opcode.  */
1136 	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1137 
1138 	      /* Verify it's a 'bcond' opcode.  */
1139 	      if ((code & 0xf0ff) != 0x707e)
1140 		continue;
1141 
1142 	      /* Note that we've changed the relocs, section contents, etc.  */
1143 	      elf_section_data (sec)->relocs = internal_relocs;
1144 	      elf_section_data (sec)->this_hdr.contents = contents;
1145 	      symtab_hdr->contents = (unsigned char *) isymbuf;
1146 
1147 	      /* Fix the relocation's type.  */
1148 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1149 					   R_CRX_REL8);
1150 
1151 	      /* Delete two bytes of data.  */
1152 	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1153 						   irel->r_offset + 2, 2))
1154 		goto error_return;
1155 
1156 	      /* That will change things, so, we should relax again.
1157 		 Note that this is not required, and it may be slow.  */
1158 	      *again = TRUE;
1159 	    }
1160 	}
1161 
1162       /* Try to turn a 24bit pc-relative cmp&branch into
1163 	 an 8bit pc-relative cmp&branch.  */
1164       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1165 	{
1166 	  bfd_vma value = symval;
1167 
1168 	  /* Deal with pc-relative gunk.  */
1169 	  value -= (sec->output_section->vma + sec->output_offset);
1170 	  value -= irel->r_offset;
1171 	  value += irel->r_addend;
1172 
1173 	  /* See if the value will fit in 8 bits, note the high value is
1174 	     0x7e + 2 as the target will be two bytes closer if we are
1175 	     able to relax.  */
1176 	  if ((long) value < 0x100 && (long) value > -0x100)
1177 	    {
1178 	      unsigned short code;
1179 
1180 	      /* Get the opcode.  */
1181 	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1182 
1183 	      /* Verify it's a 'cmp&branch' opcode.  */
1184 	      if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1185 	       && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1186 	       && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
1187 	       /* Or a Co-processor branch ('bcop').  */
1188 	       && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
1189 		continue;
1190 
1191 	      /* Note that we've changed the relocs, section contents, etc.  */
1192 	      elf_section_data (sec)->relocs = internal_relocs;
1193 	      elf_section_data (sec)->this_hdr.contents = contents;
1194 	      symtab_hdr->contents = (unsigned char *) isymbuf;
1195 
1196 	      /* Fix the opcode.  */
1197 	      bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1198 
1199 	      /* Fix the relocation's type.  */
1200 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1201 					   R_CRX_REL8_CMP);
1202 
1203 	      /* Delete two bytes of data.  */
1204 	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1205 						   irel->r_offset + 4, 2))
1206 		goto error_return;
1207 
1208 	      /* That will change things, so, we should relax again.
1209 		 Note that this is not required, and it may be slow.  */
1210 	      *again = TRUE;
1211 	    }
1212 	}
1213 
1214       /* Try to turn a 32bit immediate address into
1215 	 a 16bit immediate address.  */
1216       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1217 	{
1218 	  bfd_vma value = symval;
1219 
1220 	  /* See if the value will fit in 16 bits.  */
1221 	  if ((long) value < 0x7fff && (long) value > -0x8000)
1222 	    {
1223 	      unsigned short code;
1224 
1225 	      /* Get the opcode.  */
1226 	      code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1227 
1228 	      /* Verify it's a 'arithmetic double'.  */
1229 	      if ((code & 0xf0f0) != 0x20f0)
1230 		continue;
1231 
1232 	      /* Note that we've changed the relocs, section contents, etc.  */
1233 	      elf_section_data (sec)->relocs = internal_relocs;
1234 	      elf_section_data (sec)->this_hdr.contents = contents;
1235 	      symtab_hdr->contents = (unsigned char *) isymbuf;
1236 
1237 	      /* Fix the opcode.  */
1238 	      bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1239 
1240 	      /* Fix the relocation's type.  */
1241 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1242 					   R_CRX_IMM16);
1243 
1244 	      /* Delete two bytes of data.  */
1245 	      if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1246 						   irel->r_offset + 2, 2))
1247 		goto error_return;
1248 
1249 	      /* That will change things, so, we should relax again.
1250 		 Note that this is not required, and it may be slow.  */
1251 	      *again = TRUE;
1252 	    }
1253 	}
1254     }
1255 
1256   if (isymbuf != NULL
1257       && symtab_hdr->contents != (unsigned char *) isymbuf)
1258     {
1259       if (! link_info->keep_memory)
1260 	free (isymbuf);
1261       else
1262 	{
1263 	  /* Cache the symbols for elf_link_input_bfd.  */
1264 	  symtab_hdr->contents = (unsigned char *) isymbuf;
1265 	}
1266     }
1267 
1268   if (contents != NULL
1269       && elf_section_data (sec)->this_hdr.contents != contents)
1270     {
1271       if (! link_info->keep_memory)
1272 	free (contents);
1273       else
1274 	{
1275 	  /* Cache the section contents for elf_link_input_bfd.  */
1276 	  elf_section_data (sec)->this_hdr.contents = contents;
1277 	}
1278     }
1279 
1280   if (internal_relocs != NULL
1281       && elf_section_data (sec)->relocs != internal_relocs)
1282     free (internal_relocs);
1283 
1284   return TRUE;
1285 
1286  error_return:
1287   if (isymbuf != NULL
1288       && symtab_hdr->contents != (unsigned char *) isymbuf)
1289     free (isymbuf);
1290   if (contents != NULL
1291       && elf_section_data (sec)->this_hdr.contents != contents)
1292     free (contents);
1293   if (internal_relocs != NULL
1294       && elf_section_data (sec)->relocs != internal_relocs)
1295     free (internal_relocs);
1296 
1297   return FALSE;
1298 }
1299 
1300 static asection *
elf32_crx_gc_mark_hook(asection * sec,struct bfd_link_info * info ATTRIBUTE_UNUSED,Elf_Internal_Rela * rel ATTRIBUTE_UNUSED,struct elf_link_hash_entry * h,Elf_Internal_Sym * sym)1301 elf32_crx_gc_mark_hook (asection *sec,
1302 			struct bfd_link_info *info ATTRIBUTE_UNUSED,
1303 			Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1304 			struct elf_link_hash_entry *h,
1305 			Elf_Internal_Sym *sym)
1306 {
1307   if (h == NULL)
1308     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1309 
1310   switch (h->root.type)
1311     {
1312     case bfd_link_hash_defined:
1313     case bfd_link_hash_defweak:
1314       return h->root.u.def.section;
1315 
1316     case bfd_link_hash_common:
1317       return h->root.u.c.p->section;
1318 
1319     default:
1320       return NULL;
1321     }
1322 }
1323 
1324 /* Update the got entry reference counts for the section being removed.  */
1325 
1326 static bfd_boolean
elf32_crx_gc_sweep_hook(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * sec ATTRIBUTE_UNUSED,const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)1327 elf32_crx_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1328 			 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1329 			 asection *sec ATTRIBUTE_UNUSED,
1330 			 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1331 {
1332   /* We don't support garbage collection of GOT and PLT relocs yet.  */
1333   return TRUE;
1334 }
1335 
1336 /* Definitions for setting CRX target vector.  */
1337 #define TARGET_LITTLE_SYM		bfd_elf32_crx_vec
1338 #define TARGET_LITTLE_NAME		"elf32-crx"
1339 #define ELF_ARCH			bfd_arch_crx
1340 #define ELF_MACHINE_CODE		EM_CRX
1341 #define ELF_MAXPAGESIZE			0x1
1342 #define elf_symbol_leading_char		'_'
1343 
1344 #define bfd_elf32_bfd_reloc_type_lookup	elf_crx_reloc_type_lookup
1345 #define elf_info_to_howto		elf_crx_info_to_howto
1346 #define elf_info_to_howto_rel		0
1347 #define elf_backend_relocate_section	elf32_crx_relocate_section
1348 #define bfd_elf32_bfd_relax_section	elf32_crx_relax_section
1349 #define bfd_elf32_bfd_get_relocated_section_contents \
1350 				elf32_crx_get_relocated_section_contents
1351 #define elf_backend_gc_mark_hook        elf32_crx_gc_mark_hook
1352 #define elf_backend_gc_sweep_hook       elf32_crx_gc_sweep_hook
1353 #define elf_backend_can_gc_sections     1
1354 #define elf_backend_rela_normal		1
1355 
1356 #include "elf32-target.h"
1357