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