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