]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elf32-crx.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / elf32-crx.c
CommitLineData
1fe1f39c 1/* BFD back-end for National Semiconductor's CRX ELF
250d07de 2 Copyright (C) 2004-2021 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
c1f138f9
AM
509 reloc_bits = ((bfd_vma) 1 << (howto->bitsize - 1) << 1) - 1;
510
511 if ((check & ~reloc_bits) != 0
512 && (check & ~reloc_bits) != ((bfd_vma) -1 & ~reloc_bits))
1fe1f39c
NC
513 {
514 /* The above right shift is incorrect for a signed
515 value. See if turning on the upper bits fixes the
516 overflow. */
517 if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
518 {
c1f138f9
AM
519 check |= (bfd_vma) -1 & ~((bfd_vma) -1 >> howto->rightshift);
520 if ((check & ~reloc_bits) != ((bfd_vma) -1 & ~reloc_bits))
1fe1f39c
NC
521 return bfd_reloc_overflow;
522 }
523 else
524 return bfd_reloc_overflow;
525 }
526
527 /* Drop unwanted bits from the value we are relocating to. */
c1f138f9 528 Rvalue >>= howto->rightshift;
1fe1f39c
NC
529
530 /* Apply dst_mask to select only relocatable part of the insn. */
531 Rvalue &= howto->dst_mask;
532
533 switch (howto->size)
534 {
535 case 0:
536 if (r_type == R_CRX_REL4)
537 {
538 Rvalue <<= 4;
539 Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
540 }
541
542 bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
543 break;
544
545 case 1:
546 if (r_type == R_CRX_REGREL12)
547 Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
548
549 bfd_put_16 (input_bfd, Rvalue, hit_data);
550 break;
551
552 case 2:
553 if (r_type == R_CRX_REL24
554 || r_type == R_CRX_REGREL22
555 || r_type == R_CRX_REGREL28)
556 Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
557 bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
558
670ec21d 559 if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32)
1fe1f39c
NC
560 /* Relocation on DATA is purely little-endian, that is, for a
561 multi-byte datum, the lowest address in memory contains the
562 little end of the datum, that is, the least significant byte.
563 Therefore we use BFD's byte Putting functions. */
564 bfd_put_32 (input_bfd, Rvalue, hit_data);
565 else
566 /* Relocation on INSTRUCTIONS is different : Instructions are
567 word-addressable, that is, each word itself is arranged according
568 to little-endian convention, whereas the words are arranged with
569 respect to one another in BIG ENDIAN fashion.
570 When there is an immediate value that spans a word boundary, it is
571 split in a big-endian way with respect to the words. */
572 {
573 bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
574 bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
575 }
576 break;
577
578 default:
579 return bfd_reloc_notsupported;
580 }
581
582 return bfd_reloc_ok;
583}
584
585/* Delete some bytes from a section while relaxing. */
586
587static bfd_boolean
68ffbac6 588elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
e3f9830c 589 asection *sec, bfd_vma addr, int count)
1fe1f39c
NC
590{
591 Elf_Internal_Shdr *symtab_hdr;
592 unsigned int sec_shndx;
593 bfd_byte *contents;
594 Elf_Internal_Rela *irel, *irelend;
1fe1f39c
NC
595 bfd_vma toaddr;
596 Elf_Internal_Sym *isym;
597 Elf_Internal_Sym *isymend;
598 struct elf_link_hash_entry **sym_hashes;
599 struct elf_link_hash_entry **end_hashes;
e3f9830c 600 struct elf_link_hash_entry **start_hashes;
1fe1f39c
NC
601 unsigned int symcount;
602
603 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
604
605 contents = elf_section_data (sec)->this_hdr.contents;
606
1fe1f39c
NC
607 toaddr = sec->size;
608
609 irel = elf_section_data (sec)->relocs;
610 irelend = irel + sec->reloc_count;
611
612 /* Actually delete the bytes. */
613 memmove (contents + addr, contents + addr + count,
614 (size_t) (toaddr - addr - count));
615 sec->size -= count;
616
617 /* Adjust all the relocs. */
618 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
619 {
620 /* Get the new reloc address. */
621 if ((irel->r_offset > addr
622 && irel->r_offset < toaddr))
623 irel->r_offset -= count;
624 }
625
626 /* Adjust the local symbols defined in this section. */
627 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
628 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
629 for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
630 {
631 if (isym->st_shndx == sec_shndx
632 && isym->st_value > addr
633 && isym->st_value < toaddr)
670ec21d 634 {
68ffbac6 635 /* Adjust the addend of SWITCH relocations in this section,
670ec21d
NC
636 which reference this local symbol. */
637 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
638 {
639 unsigned long r_symndx;
640 Elf_Internal_Sym *rsym;
641 bfd_vma addsym, subsym;
642
643 /* Skip if not a SWITCH relocation. */
644 if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
645 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
646 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
647 continue;
648
649 r_symndx = ELF32_R_SYM (irel->r_info);
650 rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
651
652 /* Skip if not the local adjusted symbol. */
653 if (rsym != isym)
654 continue;
655
656 addsym = isym->st_value;
657 subsym = addsym - irel->r_addend;
658
659 /* Fix the addend only when -->> (addsym > addr >= subsym). */
660 if (subsym <= addr)
661 irel->r_addend -= count;
662 else
663 continue;
664 }
665
666 isym->st_value -= count;
667 }
1fe1f39c
NC
668 }
669
670 /* Now adjust the global symbols defined in this section. */
671 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
672 - symtab_hdr->sh_info);
e3f9830c 673 sym_hashes = start_hashes = elf_sym_hashes (abfd);
1fe1f39c
NC
674 end_hashes = sym_hashes + symcount;
675
676 for (; sym_hashes < end_hashes; sym_hashes++)
677 {
678 struct elf_link_hash_entry *sym_hash = *sym_hashes;
679
68ffbac6
L
680 /* The '--wrap SYMBOL' option is causing a pain when the object file,
681 containing the definition of __wrap_SYMBOL, includes a direct
682 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
683 the same symbol (which is __wrap_SYMBOL), but still exist as two
684 different symbols in 'sym_hashes', we don't want to adjust
685 the global symbol __wrap_SYMBOL twice.
e3f9830c
TL
686 This check is only relevant when symbols are being wrapped. */
687 if (link_info->wrap_hash != NULL)
688 {
689 struct elf_link_hash_entry **cur_sym_hashes;
68ffbac6 690
e3f9830c 691 /* Loop only over the symbols whom been already checked. */
68ffbac6 692 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
e3f9830c
TL
693 cur_sym_hashes++)
694 {
68ffbac6 695 /* If the current symbol is identical to 'sym_hash', that means
e3f9830c
TL
696 the symbol was already adjusted (or at least checked). */
697 if (*cur_sym_hashes == sym_hash)
698 break;
699 }
700 /* Don't adjust the symbol again. */
701 if (cur_sym_hashes < sym_hashes)
702 continue;
703 }
704
1fe1f39c
NC
705 if ((sym_hash->root.type == bfd_link_hash_defined
706 || sym_hash->root.type == bfd_link_hash_defweak)
707 && sym_hash->root.u.def.section == sec
708 && sym_hash->root.u.def.value > addr
709 && sym_hash->root.u.def.value < toaddr)
710 sym_hash->root.u.def.value -= count;
711 }
712
713 return TRUE;
714}
715
716/* This is a version of bfd_generic_get_relocated_section_contents
717 which uses elf32_crx_relocate_section. */
718
719static bfd_byte *
720elf32_crx_get_relocated_section_contents (bfd *output_bfd,
721 struct bfd_link_info *link_info,
722 struct bfd_link_order *link_order,
723 bfd_byte *data,
724 bfd_boolean relocatable,
725 asymbol **symbols)
726{
727 Elf_Internal_Shdr *symtab_hdr;
728 asection *input_section = link_order->u.indirect.section;
729 bfd *input_bfd = input_section->owner;
730 asection **sections = NULL;
731 Elf_Internal_Rela *internal_relocs = NULL;
732 Elf_Internal_Sym *isymbuf = NULL;
733
734 /* We only need to handle the case of relaxing, or of having a
735 particular set of section contents, specially. */
736 if (relocatable
737 || elf_section_data (input_section)->this_hdr.contents == NULL)
738 return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
739 link_order, data,
740 relocatable,
741 symbols);
742
743 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
744
745 memcpy (data, elf_section_data (input_section)->this_hdr.contents,
746 (size_t) input_section->size);
747
748 if ((input_section->flags & SEC_RELOC) != 0
749 && input_section->reloc_count > 0)
750 {
751 Elf_Internal_Sym *isym;
752 Elf_Internal_Sym *isymend;
753 asection **secpp;
754 bfd_size_type amt;
755
756 internal_relocs = (_bfd_elf_link_read_relocs
2c3fc389 757 (input_bfd, input_section, NULL,
1fe1f39c
NC
758 (Elf_Internal_Rela *) NULL, FALSE));
759 if (internal_relocs == NULL)
760 goto error_return;
761
762 if (symtab_hdr->sh_info != 0)
763 {
764 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
765 if (isymbuf == NULL)
766 isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
767 symtab_hdr->sh_info, 0,
768 NULL, NULL, NULL);
769 if (isymbuf == NULL)
770 goto error_return;
771 }
772
773 amt = symtab_hdr->sh_info;
774 amt *= sizeof (asection *);
775 sections = bfd_malloc (amt);
776 if (sections == NULL && amt != 0)
777 goto error_return;
778
779 isymend = isymbuf + symtab_hdr->sh_info;
780 for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
781 {
782 asection *isec;
783
784 if (isym->st_shndx == SHN_UNDEF)
785 isec = bfd_und_section_ptr;
786 else if (isym->st_shndx == SHN_ABS)
787 isec = bfd_abs_section_ptr;
788 else if (isym->st_shndx == SHN_COMMON)
789 isec = bfd_com_section_ptr;
790 else
791 isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
792
793 *secpp = isec;
794 }
795
796 if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
797 input_section, data, internal_relocs,
798 isymbuf, sections))
799 goto error_return;
800
c9594989
AM
801 free (sections);
802 if (symtab_hdr->contents != (unsigned char *) isymbuf)
1fe1f39c
NC
803 free (isymbuf);
804 if (elf_section_data (input_section)->relocs != internal_relocs)
805 free (internal_relocs);
806 }
807
808 return data;
809
810 error_return:
c9594989
AM
811 free (sections);
812 if (symtab_hdr->contents != (unsigned char *) isymbuf)
1fe1f39c 813 free (isymbuf);
c9594989 814 if (elf_section_data (input_section)->relocs != internal_relocs)
1fe1f39c
NC
815 free (internal_relocs);
816 return NULL;
817}
818
819/* Relocate a CRX ELF section. */
820
821static bfd_boolean
822elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
823 bfd *input_bfd, asection *input_section,
824 bfd_byte *contents, Elf_Internal_Rela *relocs,
825 Elf_Internal_Sym *local_syms,
826 asection **local_sections)
827{
828 Elf_Internal_Shdr *symtab_hdr;
829 struct elf_link_hash_entry **sym_hashes;
830 Elf_Internal_Rela *rel, *relend;
831
1fe1f39c
NC
832 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
833 sym_hashes = elf_sym_hashes (input_bfd);
834
835 rel = relocs;
836 relend = relocs + input_section->reloc_count;
837 for (; rel < relend; rel++)
838 {
839 int r_type;
840 reloc_howto_type *howto;
841 unsigned long r_symndx;
842 Elf_Internal_Sym *sym;
843 asection *sec;
844 struct elf_link_hash_entry *h;
845 bfd_vma relocation;
846 bfd_reloc_status_type r;
847
848 r_symndx = ELF32_R_SYM (rel->r_info);
849 r_type = ELF32_R_TYPE (rel->r_info);
850 howto = crx_elf_howto_table + (r_type);
851
852 h = NULL;
853 sym = NULL;
854 sec = NULL;
855 if (r_symndx < symtab_hdr->sh_info)
856 {
857 sym = local_syms + r_symndx;
858 sec = local_sections[r_symndx];
859 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
860 }
861 else
862 {
62d887d4 863 bfd_boolean unresolved_reloc, warned, ignored;
1fe1f39c
NC
864
865 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
866 r_symndx, symtab_hdr, sym_hashes,
867 h, sec, relocation,
62d887d4 868 unresolved_reloc, warned, ignored);
1fe1f39c
NC
869 }
870
dbaa2011 871 if (sec != NULL && discarded_section (sec))
e4067dbb 872 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
545fd46b 873 rel, 1, relend, howto, 0, contents);
ab96bf03 874
0e1862bb 875 if (bfd_link_relocatable (info))
ab96bf03
AM
876 continue;
877
1fe1f39c
NC
878 r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
879 input_section,
880 contents, rel->r_offset,
881 relocation, rel->r_addend,
882 info, sec, h == NULL);
883
884 if (r != bfd_reloc_ok)
885 {
886 const char *name;
887 const char *msg = (const char *) 0;
888
889 if (h != NULL)
890 name = h->root.root.string;
891 else
892 {
893 name = (bfd_elf_string_from_elf_section
894 (input_bfd, symtab_hdr->sh_link, sym->st_name));
895 if (name == NULL || *name == '\0')
fd361982 896 name = bfd_section_name (sec);
1fe1f39c
NC
897 }
898
899 switch (r)
900 {
901 case bfd_reloc_overflow:
1a72702b
AM
902 (*info->callbacks->reloc_overflow)
903 (info, (h ? &h->root : NULL), name, howto->name,
904 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
1fe1f39c
NC
905 break;
906
907 case bfd_reloc_undefined:
1a72702b
AM
908 (*info->callbacks->undefined_symbol)
909 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1fe1f39c
NC
910 break;
911
912 case bfd_reloc_outofrange:
913 msg = _("internal error: out of range error");
914 goto common_error;
915
916 case bfd_reloc_notsupported:
917 msg = _("internal error: unsupported relocation error");
918 goto common_error;
919
920 case bfd_reloc_dangerous:
921 msg = _("internal error: dangerous error");
922 goto common_error;
923
924 default:
925 msg = _("internal error: unknown error");
926 /* Fall through. */
927
928 common_error:
1a72702b
AM
929 (*info->callbacks->warning) (info, msg, name, input_bfd,
930 input_section, rel->r_offset);
1fe1f39c
NC
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
950static bfd_boolean
951elf32_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. */
0e1862bb 966 if (bfd_link_relocatable (link_info)
1fe1f39c
NC
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
2c3fc389 976 (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
1fe1f39c
NC
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. */
e3f9830c 1107 if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1fe1f39c
NC
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. */
e3f9830c 1152 if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1fe1f39c
NC
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
17a83432
TL
1186 && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
1187 /* Or a Co-processor branch ('bcop'). */
1188 && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
1fe1f39c
NC
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. */
e3f9830c 1204 if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1fe1f39c
NC
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. */
e3f9830c 1245 if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1fe1f39c
NC
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
c9594989 1280 if (elf_section_data (sec)->relocs != internal_relocs)
1fe1f39c
NC
1281 free (internal_relocs);
1282
1283 return TRUE;
1284
1285 error_return:
c9594989 1286 if (symtab_hdr->contents != (unsigned char *) isymbuf)
1fe1f39c 1287 free (isymbuf);
c9594989 1288 if (elf_section_data (sec)->this_hdr.contents != contents)
1fe1f39c 1289 free (contents);
c9594989 1290 if (elf_section_data (sec)->relocs != internal_relocs)
1fe1f39c
NC
1291 free (internal_relocs);
1292
1293 return FALSE;
1294}
1295
1fe1f39c 1296/* Definitions for setting CRX target vector. */
6d00b590 1297#define TARGET_LITTLE_SYM crx_elf32_vec
1fe1f39c
NC
1298#define TARGET_LITTLE_NAME "elf32-crx"
1299#define ELF_ARCH bfd_arch_crx
1300#define ELF_MACHINE_CODE EM_CRX
1301#define ELF_MAXPAGESIZE 0x1
1302#define elf_symbol_leading_char '_'
1303
1304#define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
157090f7
AM
1305#define bfd_elf32_bfd_reloc_name_lookup \
1306 elf_crx_reloc_name_lookup
1fe1f39c 1307#define elf_info_to_howto elf_crx_info_to_howto
f3185997 1308#define elf_info_to_howto_rel NULL
1fe1f39c
NC
1309#define elf_backend_relocate_section elf32_crx_relocate_section
1310#define bfd_elf32_bfd_relax_section elf32_crx_relax_section
1311#define bfd_elf32_bfd_get_relocated_section_contents \
1312 elf32_crx_get_relocated_section_contents
1fe1f39c
NC
1313#define elf_backend_can_gc_sections 1
1314#define elf_backend_rela_normal 1
1315
1316#include "elf32-target.h"