bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-crx.c
CommitLineData
1fe1f39c 1/* BFD back-end for National Semiconductor's CRX ELF
c7e2358a
AM
2 Copyright 2004, 2005, 2006, 2007, 2009, 2010
3 Free Software Foundation, Inc.
1fe1f39c
NC
4 Written by Tomer Levi, NSC, Israel.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
cd123cb7 10 the Free Software Foundation; either version 3 of the License, or
1fe1f39c
NC
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
cd123cb7
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
1fe1f39c 22
1fe1f39c 23#include "sysdep.h"
3db64b00 24#include "bfd.h"
1fe1f39c
NC
25#include "bfdlink.h"
26#include "libbfd.h"
27#include "elf-bfd.h"
28#include "elf/crx.h"
29
30static reloc_howto_type *elf_crx_reloc_type_lookup
31 (bfd *, bfd_reloc_code_real_type);
32static void elf_crx_info_to_howto
33 (bfd *, arelent *, Elf_Internal_Rela *);
34static bfd_boolean elf32_crx_relax_delete_bytes
e3f9830c 35 (struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
1fe1f39c
NC
36static bfd_reloc_status_type crx_elf_final_link_relocate
37 (reloc_howto_type *, bfd *, bfd *, asection *,
38 bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
39 struct bfd_link_info *, asection *, int);
40static bfd_boolean elf32_crx_relocate_section
41 (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
42 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
1fe1f39c
NC
43static bfd_boolean elf32_crx_relax_section
44 (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
45static bfd_byte * elf32_crx_get_relocated_section_contents
46 (bfd *, struct bfd_link_info *, struct bfd_link_order *,
47 bfd_byte *, bfd_boolean, asymbol **);
48
49/* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type. */
50
51struct crx_reloc_map
52{
53 bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum. */
54 unsigned short crx_reloc_type; /* CRX relocation type. */
55};
56
57static const struct crx_reloc_map crx_reloc_map[R_CRX_MAX] =
58{
59 {BFD_RELOC_NONE, R_CRX_NONE},
60 {BFD_RELOC_CRX_REL4, R_CRX_REL4},
61 {BFD_RELOC_CRX_REL8, R_CRX_REL8},
62 {BFD_RELOC_CRX_REL8_CMP, R_CRX_REL8_CMP},
63 {BFD_RELOC_CRX_REL16, R_CRX_REL16},
64 {BFD_RELOC_CRX_REL24, R_CRX_REL24},
65 {BFD_RELOC_CRX_REL32, R_CRX_REL32},
66 {BFD_RELOC_CRX_REGREL12, R_CRX_REGREL12},
67 {BFD_RELOC_CRX_REGREL22, R_CRX_REGREL22},
68 {BFD_RELOC_CRX_REGREL28, R_CRX_REGREL28},
69 {BFD_RELOC_CRX_REGREL32, R_CRX_REGREL32},
70 {BFD_RELOC_CRX_ABS16, R_CRX_ABS16},
71 {BFD_RELOC_CRX_ABS32, R_CRX_ABS32},
72 {BFD_RELOC_CRX_NUM8, R_CRX_NUM8},
73 {BFD_RELOC_CRX_NUM16, R_CRX_NUM16},
74 {BFD_RELOC_CRX_NUM32, R_CRX_NUM32},
75 {BFD_RELOC_CRX_IMM16, R_CRX_IMM16},
670ec21d
NC
76 {BFD_RELOC_CRX_IMM32, R_CRX_IMM32},
77 {BFD_RELOC_CRX_SWITCH8, R_CRX_SWITCH8},
78 {BFD_RELOC_CRX_SWITCH16, R_CRX_SWITCH16},
79 {BFD_RELOC_CRX_SWITCH32, R_CRX_SWITCH32}
1fe1f39c
NC
80};
81
82static reloc_howto_type crx_elf_howto_table[] =
83{
84 HOWTO (R_CRX_NONE, /* type */
85 0, /* rightshift */
86 2, /* size */
87 32, /* bitsize */
88 FALSE, /* pc_relative */
89 0, /* bitpos */
90 complain_overflow_dont,/* complain_on_overflow */
91 bfd_elf_generic_reloc, /* special_function */
92 "R_CRX_NONE", /* name */
93 FALSE, /* partial_inplace */
94 0, /* src_mask */
95 0, /* dst_mask */
96 FALSE), /* pcrel_offset */
97
98 HOWTO (R_CRX_REL4, /* type */
99 1, /* rightshift */
100 0, /* size */
101 4, /* bitsize */
102 TRUE, /* pc_relative */
103 0, /* bitpos */
104 complain_overflow_bitfield,/* complain_on_overflow */
105 bfd_elf_generic_reloc, /* special_function */
106 "R_CRX_REL4", /* name */
107 FALSE, /* partial_inplace */
3614d36b 108 0x0, /* src_mask */
1fe1f39c
NC
109 0xf, /* dst_mask */
110 FALSE), /* pcrel_offset */
111
112 HOWTO (R_CRX_REL8, /* type */
113 1, /* rightshift */
114 0, /* size */
115 8, /* bitsize */
116 TRUE, /* pc_relative */
117 0, /* bitpos */
118 complain_overflow_bitfield,/* complain_on_overflow */
119 bfd_elf_generic_reloc, /* special_function */
120 "R_CRX_REL8", /* name */
121 FALSE, /* partial_inplace */
3614d36b 122 0x0, /* src_mask */
1fe1f39c
NC
123 0xff, /* dst_mask */
124 FALSE), /* pcrel_offset */
125
126 HOWTO (R_CRX_REL8_CMP, /* type */
127 1, /* rightshift */
128 0, /* size */
129 8, /* bitsize */
130 TRUE, /* pc_relative */
131 0, /* bitpos */
132 complain_overflow_bitfield,/* complain_on_overflow */
133 bfd_elf_generic_reloc, /* special_function */
134 "R_CRX_REL8_CMP", /* name */
135 FALSE, /* partial_inplace */
3614d36b 136 0x0, /* src_mask */
1fe1f39c
NC
137 0xff, /* dst_mask */
138 FALSE), /* pcrel_offset */
139
140 HOWTO (R_CRX_REL16, /* type */
141 1, /* rightshift */
142 1, /* size */
143 16, /* bitsize */
144 TRUE, /* pc_relative */
145 0, /* bitpos */
146 complain_overflow_bitfield,/* complain_on_overflow */
147 bfd_elf_generic_reloc, /* special_function */
148 "R_CRX_REL16", /* name */
149 FALSE, /* partial_inplace */
3614d36b 150 0x0, /* src_mask */
1fe1f39c
NC
151 0xffff, /* dst_mask */
152 FALSE), /* pcrel_offset */
153
154 HOWTO (R_CRX_REL24, /* type */
155 1, /* rightshift */
156 2, /* size */
157 24, /* bitsize */
158 TRUE, /* pc_relative */
159 0, /* bitpos */
160 complain_overflow_bitfield,/* complain_on_overflow */
161 bfd_elf_generic_reloc, /* special_function */
162 "R_CRX_REL24", /* name */
163 FALSE, /* partial_inplace */
3614d36b 164 0x0, /* src_mask */
1fe1f39c
NC
165 0xffffff, /* dst_mask */
166 FALSE), /* pcrel_offset */
167
168 HOWTO (R_CRX_REL32, /* type */
169 1, /* rightshift */
170 2, /* size */
171 32, /* bitsize */
172 TRUE, /* pc_relative */
173 0, /* bitpos */
174 complain_overflow_bitfield,/* complain_on_overflow */
175 bfd_elf_generic_reloc, /* special_function */
176 "R_CRX_REL32", /* name */
177 FALSE, /* partial_inplace */
3614d36b 178 0x0, /* src_mask */
1fe1f39c
NC
179 0xffffffff, /* dst_mask */
180 FALSE), /* pcrel_offset */
181
182 HOWTO (R_CRX_REGREL12, /* type */
183 0, /* rightshift */
184 1, /* size */
185 12, /* bitsize */
186 FALSE, /* pc_relative */
187 0, /* bitpos */
188 complain_overflow_bitfield,/* complain_on_overflow */
189 bfd_elf_generic_reloc, /* special_function */
190 "R_CRX_REGREL12", /* name */
191 FALSE, /* partial_inplace */
3614d36b 192 0x0, /* src_mask */
1fe1f39c
NC
193 0xfff, /* dst_mask */
194 FALSE), /* pcrel_offset */
195
196 HOWTO (R_CRX_REGREL22, /* type */
197 0, /* rightshift */
198 2, /* size */
199 22, /* bitsize */
200 FALSE, /* pc_relative */
201 0, /* bitpos */
202 complain_overflow_bitfield,/* complain_on_overflow */
203 bfd_elf_generic_reloc, /* special_function */
204 "R_CRX_REGREL22", /* name */
205 FALSE, /* partial_inplace */
3614d36b 206 0x0, /* src_mask */
1fe1f39c
NC
207 0x3fffff, /* dst_mask */
208 FALSE), /* pcrel_offset */
209
210 HOWTO (R_CRX_REGREL28, /* type */
211 0, /* rightshift */
212 2, /* size */
213 28, /* bitsize */
214 FALSE, /* pc_relative */
215 0, /* bitpos */
216 complain_overflow_bitfield,/* complain_on_overflow */
217 bfd_elf_generic_reloc, /* special_function */
218 "R_CRX_REGREL28", /* name */
219 FALSE, /* partial_inplace */
3614d36b 220 0x0, /* src_mask */
1fe1f39c
NC
221 0xfffffff, /* dst_mask */
222 FALSE), /* pcrel_offset */
223
224 HOWTO (R_CRX_REGREL32, /* type */
225 0, /* rightshift */
226 2, /* size */
227 32, /* bitsize */
228 FALSE, /* pc_relative */
229 0, /* bitpos */
230 complain_overflow_bitfield,/* complain_on_overflow */
231 bfd_elf_generic_reloc, /* special_function */
232 "R_CRX_REGREL32", /* name */
233 FALSE, /* partial_inplace */
3614d36b 234 0x0, /* src_mask */
1fe1f39c
NC
235 0xffffffff, /* dst_mask */
236 FALSE), /* pcrel_offset */
237
238 HOWTO (R_CRX_ABS16, /* type */
239 0, /* rightshift */
240 1, /* size */
241 16, /* bitsize */
242 FALSE, /* pc_relative */
243 0, /* bitpos */
244 complain_overflow_bitfield,/* complain_on_overflow */
245 bfd_elf_generic_reloc, /* special_function */
246 "R_CRX_ABS16", /* name */
247 FALSE, /* partial_inplace */
3614d36b 248 0x0, /* src_mask */
1fe1f39c
NC
249 0xffff, /* dst_mask */
250 FALSE), /* pcrel_offset */
251
252 HOWTO (R_CRX_ABS32, /* type */
253 0, /* rightshift */
254 2, /* size */
255 32, /* bitsize */
256 FALSE, /* pc_relative */
257 0, /* bitpos */
258 complain_overflow_bitfield,/* complain_on_overflow */
259 bfd_elf_generic_reloc, /* special_function */
260 "R_CRX_ABS32", /* name */
261 FALSE, /* partial_inplace */
3614d36b 262 0x0, /* src_mask */
1fe1f39c
NC
263 0xffffffff, /* dst_mask */
264 FALSE), /* pcrel_offset */
265
266 HOWTO (R_CRX_NUM8, /* type */
267 0, /* rightshift */
268 0, /* size */
269 8, /* bitsize */
270 FALSE, /* pc_relative */
271 0, /* bitpos */
272 complain_overflow_bitfield,/* complain_on_overflow */
273 bfd_elf_generic_reloc, /* special_function */
274 "R_CRX_NUM8", /* name */
275 FALSE, /* partial_inplace */
3614d36b 276 0x0, /* src_mask */
1fe1f39c
NC
277 0xff, /* dst_mask */
278 FALSE), /* pcrel_offset */
279
280 HOWTO (R_CRX_NUM16, /* type */
281 0, /* rightshift */
282 1, /* size */
283 16, /* bitsize */
284 FALSE, /* pc_relative */
285 0, /* bitpos */
286 complain_overflow_bitfield,/* complain_on_overflow */
287 bfd_elf_generic_reloc, /* special_function */
288 "R_CRX_NUM16", /* name */
289 FALSE, /* partial_inplace */
3614d36b 290 0x0, /* src_mask */
1fe1f39c
NC
291 0xffff, /* dst_mask */
292 FALSE), /* pcrel_offset */
293
294 HOWTO (R_CRX_NUM32, /* type */
295 0, /* rightshift */
296 2, /* size */
297 32, /* bitsize */
298 FALSE, /* pc_relative */
299 0, /* bitpos */
300 complain_overflow_bitfield,/* complain_on_overflow */
301 bfd_elf_generic_reloc, /* special_function */
302 "R_CRX_NUM32", /* name */
303 FALSE, /* partial_inplace */
3614d36b 304 0x0, /* src_mask */
1fe1f39c
NC
305 0xffffffff, /* dst_mask */
306 FALSE), /* pcrel_offset */
307
308 HOWTO (R_CRX_IMM16, /* type */
309 0, /* rightshift */
310 1, /* size */
311 16, /* bitsize */
312 FALSE, /* pc_relative */
313 0, /* bitpos */
314 complain_overflow_bitfield,/* complain_on_overflow */
315 bfd_elf_generic_reloc, /* special_function */
316 "R_CRX_IMM16", /* name */
317 FALSE, /* partial_inplace */
3614d36b 318 0x0, /* src_mask */
1fe1f39c
NC
319 0xffff, /* dst_mask */
320 FALSE), /* pcrel_offset */
321
322 HOWTO (R_CRX_IMM32, /* type */
323 0, /* rightshift */
324 2, /* size */
325 32, /* bitsize */
326 FALSE, /* pc_relative */
327 0, /* bitpos */
328 complain_overflow_bitfield,/* complain_on_overflow */
329 bfd_elf_generic_reloc, /* special_function */
330 "R_CRX_IMM32", /* name */
331 FALSE, /* partial_inplace */
3614d36b 332 0x0, /* src_mask */
1fe1f39c 333 0xffffffff, /* dst_mask */
670ec21d
NC
334 FALSE), /* pcrel_offset */
335
336 /* An 8 bit switch table entry. This is generated for an expression
337 such as ``.byte L1 - L2''. The offset holds the difference
338 between the reloc address and L2. */
339 HOWTO (R_CRX_SWITCH8, /* type */
340 0, /* rightshift */
341 0, /* size (0 = byte, 1 = short, 2 = long) */
342 8, /* bitsize */
343 FALSE, /* pc_relative */
344 0, /* bitpos */
345 complain_overflow_unsigned, /* complain_on_overflow */
346 bfd_elf_generic_reloc, /* special_function */
347 "R_CRX_SWITCH8", /* name */
348 FALSE, /* partial_inplace */
3614d36b 349 0x0, /* src_mask */
670ec21d
NC
350 0xff, /* dst_mask */
351 TRUE), /* pcrel_offset */
352
353 /* A 16 bit switch table entry. This is generated for an expression
354 such as ``.word L1 - L2''. The offset holds the difference
355 between the reloc address and L2. */
356 HOWTO (R_CRX_SWITCH16, /* type */
357 0, /* rightshift */
358 1, /* size (0 = byte, 1 = short, 2 = long) */
359 16, /* bitsize */
360 FALSE, /* pc_relative */
361 0, /* bitpos */
362 complain_overflow_unsigned, /* complain_on_overflow */
363 bfd_elf_generic_reloc, /* special_function */
364 "R_CRX_SWITCH16", /* name */
365 FALSE, /* partial_inplace */
3614d36b 366 0x0, /* src_mask */
670ec21d
NC
367 0xffff, /* dst_mask */
368 TRUE), /* pcrel_offset */
369
370 /* A 32 bit switch table entry. This is generated for an expression
371 such as ``.long L1 - L2''. The offset holds the difference
372 between the reloc address and L2. */
373 HOWTO (R_CRX_SWITCH32, /* type */
374 0, /* rightshift */
375 2, /* size (0 = byte, 1 = short, 2 = long) */
376 32, /* bitsize */
377 FALSE, /* pc_relative */
378 0, /* bitpos */
379 complain_overflow_unsigned, /* complain_on_overflow */
380 bfd_elf_generic_reloc, /* special_function */
381 "R_CRX_SWITCH32", /* name */
382 FALSE, /* partial_inplace */
3614d36b 383 0x0, /* src_mask */
670ec21d
NC
384 0xffffffff, /* dst_mask */
385 TRUE) /* pcrel_offset */
1fe1f39c
NC
386};
387
388/* Retrieve a howto ptr using a BFD reloc_code. */
389
390static reloc_howto_type *
391elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
392 bfd_reloc_code_real_type code)
393{
394 unsigned int i;
395
396 for (i = 0; i < R_CRX_MAX; i++)
397 if (code == crx_reloc_map[i].bfd_reloc_enum)
398 return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type];
399
400 printf ("This relocation Type is not supported -0x%x\n", code);
401 return 0;
402}
403
157090f7
AM
404static reloc_howto_type *
405elf_crx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
406 const char *r_name)
407{
408 unsigned int i;
409
410 for (i = 0;
411 i < sizeof (crx_elf_howto_table) / sizeof (crx_elf_howto_table[0]);
412 i++)
413 if (crx_elf_howto_table[i].name != NULL
414 && strcasecmp (crx_elf_howto_table[i].name, r_name) == 0)
415 return &crx_elf_howto_table[i];
416
417 return NULL;
418}
419
1fe1f39c
NC
420/* Retrieve a howto ptr using an internal relocation entry. */
421
422static void
423elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
424 Elf_Internal_Rela *dst)
425{
426 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
427 BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
428 cache_ptr->howto = &crx_elf_howto_table[r_type];
429}
430
431/* Perform a relocation as part of a final link. */
432
433static bfd_reloc_status_type
434crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
435 bfd *output_bfd ATTRIBUTE_UNUSED,
436 asection *input_section, bfd_byte *contents,
437 bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
438 struct bfd_link_info *info ATTRIBUTE_UNUSED,
439 asection *sec ATTRIBUTE_UNUSED,
440 int is_local ATTRIBUTE_UNUSED)
441{
442 unsigned short r_type = howto->type;
443 bfd_byte *hit_data = contents + offset;
444 bfd_vma reloc_bits, check;
445
446 switch (r_type)
447 {
448 case R_CRX_IMM16:
449 case R_CRX_IMM32:
450 case R_CRX_ABS16:
451 case R_CRX_ABS32:
452 case R_CRX_REL8_CMP:
453 case R_CRX_REL16:
454 case R_CRX_REL24:
455 case R_CRX_REL32:
456 case R_CRX_REGREL12:
457 case R_CRX_REGREL22:
458 case R_CRX_REGREL28:
459 case R_CRX_REGREL32:
460 /* 'hit_data' is relative to the start of the instruction, not the
461 relocation offset. Advance it to account for the exact offset. */
462 hit_data += 2;
463 break;
464
465 case R_CRX_REL4:
466 /* This relocation type is used only in 'Branch if Equal to 0'
467 instructions and requires special handling. */
468 Rvalue -= 1;
469 break;
470
471 case R_CRX_NONE:
472 return bfd_reloc_ok;
473 break;
474
670ec21d
NC
475 case R_CRX_SWITCH8:
476 case R_CRX_SWITCH16:
477 case R_CRX_SWITCH32:
478 /* We only care about the addend, where the difference between
479 expressions is kept. */
480 Rvalue = 0;
481
1fe1f39c
NC
482 default:
483 break;
484 }
485
486 if (howto->pc_relative)
487 {
488 /* Subtract the address of the section containing the location. */
489 Rvalue -= (input_section->output_section->vma
490 + input_section->output_offset);
491 /* Subtract the position of the location within the section. */
492 Rvalue -= offset;
493 }
494
495 /* Add in supplied addend. */
496 Rvalue += addend;
497
498 /* Complain if the bitfield overflows, whether it is considered
499 as signed or unsigned. */
500 check = Rvalue >> howto->rightshift;
501
502 /* Assumes two's complement. This expression avoids
503 overflow if howto->bitsize is the number of bits in
504 bfd_vma. */
505 reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
506
507 if (((bfd_vma) check & ~reloc_bits) != 0
508 && (((bfd_vma) check & ~reloc_bits)
509 != (-(bfd_vma) 1 & ~reloc_bits)))
510 {
511 /* The above right shift is incorrect for a signed
512 value. See if turning on the upper bits fixes the
513 overflow. */
514 if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
515 {
516 check |= ((bfd_vma) - 1
517 & ~((bfd_vma) - 1
518 >> howto->rightshift));
519 if (((bfd_vma) check & ~reloc_bits)
520 != (-(bfd_vma) 1 & ~reloc_bits))
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. */
528 Rvalue >>= (bfd_vma) howto->rightshift;
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
e3f9830c
TL
588elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
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
NC
634 {
635 /* Adjust the addend of SWITCH relocations in this section,
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
e3f9830c
TL
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.
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;
690
691 /* Loop only over the symbols whom been already checked. */
692 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
693 cur_sym_hashes++)
694 {
695 /* If the current symbol is identical to 'sym_hash', that means
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
757 (input_bfd, input_section, (PTR) NULL,
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
801 if (sections != NULL)
802 free (sections);
803 if (isymbuf != NULL
804 && symtab_hdr->contents != (unsigned char *) isymbuf)
805 free (isymbuf);
806 if (elf_section_data (input_section)->relocs != internal_relocs)
807 free (internal_relocs);
808 }
809
810 return data;
811
812 error_return:
813 if (sections != NULL)
814 free (sections);
815 if (isymbuf != NULL
816 && symtab_hdr->contents != (unsigned char *) isymbuf)
817 free (isymbuf);
818 if (internal_relocs != NULL
819 && elf_section_data (input_section)->relocs != internal_relocs)
820 free (internal_relocs);
821 return NULL;
822}
823
824/* Relocate a CRX ELF section. */
825
826static bfd_boolean
827elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
828 bfd *input_bfd, asection *input_section,
829 bfd_byte *contents, Elf_Internal_Rela *relocs,
830 Elf_Internal_Sym *local_syms,
831 asection **local_sections)
832{
833 Elf_Internal_Shdr *symtab_hdr;
834 struct elf_link_hash_entry **sym_hashes;
835 Elf_Internal_Rela *rel, *relend;
836
1fe1f39c
NC
837 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
838 sym_hashes = elf_sym_hashes (input_bfd);
839
840 rel = relocs;
841 relend = relocs + input_section->reloc_count;
842 for (; rel < relend; rel++)
843 {
844 int r_type;
845 reloc_howto_type *howto;
846 unsigned long r_symndx;
847 Elf_Internal_Sym *sym;
848 asection *sec;
849 struct elf_link_hash_entry *h;
850 bfd_vma relocation;
851 bfd_reloc_status_type r;
852
853 r_symndx = ELF32_R_SYM (rel->r_info);
854 r_type = ELF32_R_TYPE (rel->r_info);
855 howto = crx_elf_howto_table + (r_type);
856
857 h = NULL;
858 sym = NULL;
859 sec = NULL;
860 if (r_symndx < symtab_hdr->sh_info)
861 {
862 sym = local_syms + r_symndx;
863 sec = local_sections[r_symndx];
864 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
865 }
866 else
867 {
868 bfd_boolean unresolved_reloc, warned;
869
870 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
871 r_symndx, symtab_hdr, sym_hashes,
872 h, sec, relocation,
873 unresolved_reloc, warned);
874 }
875
ab96bf03
AM
876 if (sec != NULL && elf_discarded_section (sec))
877 {
878 /* For relocs against symbols from removed linkonce sections,
879 or sections discarded by a linker script, we just want the
880 section contents zeroed. Avoid any special processing. */
881 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
882 rel->r_info = 0;
883 rel->r_addend = 0;
884 continue;
885 }
886
887 if (info->relocatable)
888 continue;
889
1fe1f39c
NC
890 r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
891 input_section,
892 contents, rel->r_offset,
893 relocation, rel->r_addend,
894 info, sec, h == NULL);
895
896 if (r != bfd_reloc_ok)
897 {
898 const char *name;
899 const char *msg = (const char *) 0;
900
901 if (h != NULL)
902 name = h->root.root.string;
903 else
904 {
905 name = (bfd_elf_string_from_elf_section
906 (input_bfd, symtab_hdr->sh_link, sym->st_name));
907 if (name == NULL || *name == '\0')
908 name = bfd_section_name (input_bfd, sec);
909 }
910
911 switch (r)
912 {
913 case bfd_reloc_overflow:
914 if (!((*info->callbacks->reloc_overflow)
dfeffb9f
L
915 (info, (h ? &h->root : NULL), name, howto->name,
916 (bfd_vma) 0, input_bfd, input_section,
917 rel->r_offset)))
1fe1f39c
NC
918 return FALSE;
919 break;
920
921 case bfd_reloc_undefined:
922 if (!((*info->callbacks->undefined_symbol)
923 (info, name, input_bfd, input_section,
924 rel->r_offset, TRUE)))
925 return FALSE;
926 break;
927
928 case bfd_reloc_outofrange:
929 msg = _("internal error: out of range error");
930 goto common_error;
931
932 case bfd_reloc_notsupported:
933 msg = _("internal error: unsupported relocation error");
934 goto common_error;
935
936 case bfd_reloc_dangerous:
937 msg = _("internal error: dangerous error");
938 goto common_error;
939
940 default:
941 msg = _("internal error: unknown error");
942 /* Fall through. */
943
944 common_error:
945 if (!((*info->callbacks->warning)
946 (info, msg, name, input_bfd, input_section,
947 rel->r_offset)))
948 return FALSE;
949 break;
950 }
951 }
952 }
953
954 return TRUE;
955}
956
957/* This function handles relaxing for the CRX.
958
959 There's quite a few relaxing opportunites available on the CRX:
960
961 * bal/bcond:32 -> bal/bcond:16 2 bytes
962 * bcond:16 -> bcond:8 2 bytes
963 * cmpbcond:24 -> cmpbcond:8 2 bytes
964 * arithmetic imm32 -> arithmetic imm16 2 bytes
965
966 Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
967
968static bfd_boolean
969elf32_crx_relax_section (bfd *abfd, asection *sec,
970 struct bfd_link_info *link_info, bfd_boolean *again)
971{
972 Elf_Internal_Shdr *symtab_hdr;
973 Elf_Internal_Rela *internal_relocs;
974 Elf_Internal_Rela *irel, *irelend;
975 bfd_byte *contents = NULL;
976 Elf_Internal_Sym *isymbuf = NULL;
977
978 /* Assume nothing changes. */
979 *again = FALSE;
980
981 /* We don't have to do anything for a relocatable link, if
982 this section does not have relocs, or if this is not a
983 code section. */
984 if (link_info->relocatable
985 || (sec->flags & SEC_RELOC) == 0
986 || sec->reloc_count == 0
987 || (sec->flags & SEC_CODE) == 0)
988 return TRUE;
989
990 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
991
992 /* Get a copy of the native relocations. */
993 internal_relocs = (_bfd_elf_link_read_relocs
994 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
995 link_info->keep_memory));
996 if (internal_relocs == NULL)
997 goto error_return;
998
999 /* Walk through them looking for relaxing opportunities. */
1000 irelend = internal_relocs + sec->reloc_count;
1001 for (irel = internal_relocs; irel < irelend; irel++)
1002 {
1003 bfd_vma symval;
1004
1005 /* If this isn't something that can be relaxed, then ignore
1006 this reloc. */
1007 if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
1008 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
1009 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
1010 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
1011 continue;
1012
1013 /* Get the section contents if we haven't done so already. */
1014 if (contents == NULL)
1015 {
1016 /* Get cached copy if it exists. */
1017 if (elf_section_data (sec)->this_hdr.contents != NULL)
1018 contents = elf_section_data (sec)->this_hdr.contents;
1019 /* Go get them off disk. */
1020 else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1021 goto error_return;
1022 }
1023
1024 /* Read this BFD's local symbols if we haven't done so already. */
1025 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1026 {
1027 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1028 if (isymbuf == NULL)
1029 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1030 symtab_hdr->sh_info, 0,
1031 NULL, NULL, NULL);
1032 if (isymbuf == NULL)
1033 goto error_return;
1034 }
1035
1036 /* Get the value of the symbol referred to by the reloc. */
1037 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1038 {
1039 /* A local symbol. */
1040 Elf_Internal_Sym *isym;
1041 asection *sym_sec;
1042
1043 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1044 if (isym->st_shndx == SHN_UNDEF)
1045 sym_sec = bfd_und_section_ptr;
1046 else if (isym->st_shndx == SHN_ABS)
1047 sym_sec = bfd_abs_section_ptr;
1048 else if (isym->st_shndx == SHN_COMMON)
1049 sym_sec = bfd_com_section_ptr;
1050 else
1051 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1052 symval = (isym->st_value
1053 + sym_sec->output_section->vma
1054 + sym_sec->output_offset);
1055 }
1056 else
1057 {
1058 unsigned long indx;
1059 struct elf_link_hash_entry *h;
1060
1061 /* An external symbol. */
1062 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1063 h = elf_sym_hashes (abfd)[indx];
1064 BFD_ASSERT (h != NULL);
1065
1066 if (h->root.type != bfd_link_hash_defined
1067 && h->root.type != bfd_link_hash_defweak)
1068 /* This appears to be a reference to an undefined
1069 symbol. Just ignore it--it will be caught by the
1070 regular reloc processing. */
1071 continue;
1072
1073 symval = (h->root.u.def.value
1074 + h->root.u.def.section->output_section->vma
1075 + h->root.u.def.section->output_offset);
1076 }
1077
1078 /* For simplicity of coding, we are going to modify the section
1079 contents, the section relocs, and the BFD symbol table. We
1080 must tell the rest of the code not to free up this
1081 information. It would be possible to instead create a table
1082 of changes which have to be made, as is done in coff-mips.c;
1083 that would be more work, but would require less memory when
1084 the linker is run. */
1085
1086 /* Try to turn a 32bit pc-relative branch/call into
1087 a 16bit pc-relative branch/call. */
1088 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
1089 {
1090 bfd_vma value = symval;
1091
1092 /* Deal with pc-relative gunk. */
1093 value -= (sec->output_section->vma + sec->output_offset);
1094 value -= irel->r_offset;
1095 value += irel->r_addend;
1096
1097 /* See if the value will fit in 16 bits, note the high value is
1098 0xfffe + 2 as the target will be two bytes closer if we are
1099 able to relax. */
1100 if ((long) value < 0x10000 && (long) value > -0x10002)
1101 {
1102 unsigned short code;
1103
1104 /* Get the opcode. */
1105 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1106
1107 /* Verify it's a 'bal'/'bcond' and fix the opcode. */
1108 if ((code & 0xfff0) == 0x3170)
1109 bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1110 else if ((code & 0xf0ff) == 0x707f)
1111 bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
1112 else
1113 continue;
1114
1115 /* Note that we've changed the relocs, section contents, etc. */
1116 elf_section_data (sec)->relocs = internal_relocs;
1117 elf_section_data (sec)->this_hdr.contents = contents;
1118 symtab_hdr->contents = (unsigned char *) isymbuf;
1119
1120 /* Fix the relocation's type. */
1121 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1122 R_CRX_REL16);
1123
1124 /* Delete two bytes of data. */
e3f9830c 1125 if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1fe1f39c
NC
1126 irel->r_offset + 2, 2))
1127 goto error_return;
1128
1129 /* That will change things, so, we should relax again.
1130 Note that this is not required, and it may be slow. */
1131 *again = TRUE;
1132 }
1133 }
1134
1135 /* Try to turn a 16bit pc-relative branch into an
1136 8bit pc-relative branch. */
1137 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
1138 {
1139 bfd_vma value = symval;
1140
1141 /* Deal with pc-relative gunk. */
1142 value -= (sec->output_section->vma + sec->output_offset);
1143 value -= irel->r_offset;
1144 value += irel->r_addend;
1145
1146 /* See if the value will fit in 8 bits, note the high value is
1147 0xfc + 2 as the target will be two bytes closer if we are
1148 able to relax. */
1149 if ((long) value < 0xfe && (long) value > -0x100)
1150 {
1151 unsigned short code;
1152
1153 /* Get the opcode. */
1154 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1155
1156 /* Verify it's a 'bcond' opcode. */
1157 if ((code & 0xf0ff) != 0x707e)
1158 continue;
1159
1160 /* Note that we've changed the relocs, section contents, etc. */
1161 elf_section_data (sec)->relocs = internal_relocs;
1162 elf_section_data (sec)->this_hdr.contents = contents;
1163 symtab_hdr->contents = (unsigned char *) isymbuf;
1164
1165 /* Fix the relocation's type. */
1166 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1167 R_CRX_REL8);
1168
1169 /* Delete two bytes of data. */
e3f9830c 1170 if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1fe1f39c
NC
1171 irel->r_offset + 2, 2))
1172 goto error_return;
1173
1174 /* That will change things, so, we should relax again.
1175 Note that this is not required, and it may be slow. */
1176 *again = TRUE;
1177 }
1178 }
1179
1180 /* Try to turn a 24bit pc-relative cmp&branch into
1181 an 8bit pc-relative cmp&branch. */
1182 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1183 {
1184 bfd_vma value = symval;
1185
1186 /* Deal with pc-relative gunk. */
1187 value -= (sec->output_section->vma + sec->output_offset);
1188 value -= irel->r_offset;
1189 value += irel->r_addend;
1190
1191 /* See if the value will fit in 8 bits, note the high value is
1192 0x7e + 2 as the target will be two bytes closer if we are
1193 able to relax. */
1194 if ((long) value < 0x100 && (long) value > -0x100)
1195 {
1196 unsigned short code;
1197
1198 /* Get the opcode. */
1199 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1200
1201 /* Verify it's a 'cmp&branch' opcode. */
1202 if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1203 && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
17a83432
TL
1204 && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
1205 /* Or a Co-processor branch ('bcop'). */
1206 && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
1fe1f39c
NC
1207 continue;
1208
1209 /* Note that we've changed the relocs, section contents, etc. */
1210 elf_section_data (sec)->relocs = internal_relocs;
1211 elf_section_data (sec)->this_hdr.contents = contents;
1212 symtab_hdr->contents = (unsigned char *) isymbuf;
1213
1214 /* Fix the opcode. */
1215 bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1216
1217 /* Fix the relocation's type. */
1218 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1219 R_CRX_REL8_CMP);
1220
1221 /* Delete two bytes of data. */
e3f9830c 1222 if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1fe1f39c
NC
1223 irel->r_offset + 4, 2))
1224 goto error_return;
1225
1226 /* That will change things, so, we should relax again.
1227 Note that this is not required, and it may be slow. */
1228 *again = TRUE;
1229 }
1230 }
1231
1232 /* Try to turn a 32bit immediate address into
1233 a 16bit immediate address. */
1234 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1235 {
1236 bfd_vma value = symval;
1237
1238 /* See if the value will fit in 16 bits. */
1239 if ((long) value < 0x7fff && (long) value > -0x8000)
1240 {
1241 unsigned short code;
1242
1243 /* Get the opcode. */
1244 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1245
1246 /* Verify it's a 'arithmetic double'. */
1247 if ((code & 0xf0f0) != 0x20f0)
1248 continue;
1249
1250 /* Note that we've changed the relocs, section contents, etc. */
1251 elf_section_data (sec)->relocs = internal_relocs;
1252 elf_section_data (sec)->this_hdr.contents = contents;
1253 symtab_hdr->contents = (unsigned char *) isymbuf;
1254
1255 /* Fix the opcode. */
1256 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1257
1258 /* Fix the relocation's type. */
1259 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1260 R_CRX_IMM16);
1261
1262 /* Delete two bytes of data. */
e3f9830c 1263 if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1fe1f39c
NC
1264 irel->r_offset + 2, 2))
1265 goto error_return;
1266
1267 /* That will change things, so, we should relax again.
1268 Note that this is not required, and it may be slow. */
1269 *again = TRUE;
1270 }
1271 }
1272 }
1273
1274 if (isymbuf != NULL
1275 && symtab_hdr->contents != (unsigned char *) isymbuf)
1276 {
1277 if (! link_info->keep_memory)
1278 free (isymbuf);
1279 else
1280 {
1281 /* Cache the symbols for elf_link_input_bfd. */
1282 symtab_hdr->contents = (unsigned char *) isymbuf;
1283 }
1284 }
1285
1286 if (contents != NULL
1287 && elf_section_data (sec)->this_hdr.contents != contents)
1288 {
1289 if (! link_info->keep_memory)
1290 free (contents);
1291 else
1292 {
1293 /* Cache the section contents for elf_link_input_bfd. */
1294 elf_section_data (sec)->this_hdr.contents = contents;
1295 }
1296 }
1297
1298 if (internal_relocs != NULL
1299 && elf_section_data (sec)->relocs != internal_relocs)
1300 free (internal_relocs);
1301
1302 return TRUE;
1303
1304 error_return:
1305 if (isymbuf != NULL
1306 && symtab_hdr->contents != (unsigned char *) isymbuf)
1307 free (isymbuf);
1308 if (contents != NULL
1309 && elf_section_data (sec)->this_hdr.contents != contents)
1310 free (contents);
1311 if (internal_relocs != NULL
1312 && elf_section_data (sec)->relocs != internal_relocs)
1313 free (internal_relocs);
1314
1315 return FALSE;
1316}
1317
1fe1f39c
NC
1318/* Definitions for setting CRX target vector. */
1319#define TARGET_LITTLE_SYM bfd_elf32_crx_vec
1320#define TARGET_LITTLE_NAME "elf32-crx"
1321#define ELF_ARCH bfd_arch_crx
1322#define ELF_MACHINE_CODE EM_CRX
1323#define ELF_MAXPAGESIZE 0x1
1324#define elf_symbol_leading_char '_'
1325
1326#define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
157090f7
AM
1327#define bfd_elf32_bfd_reloc_name_lookup \
1328 elf_crx_reloc_name_lookup
1fe1f39c
NC
1329#define elf_info_to_howto elf_crx_info_to_howto
1330#define elf_info_to_howto_rel 0
1331#define elf_backend_relocate_section elf32_crx_relocate_section
1332#define bfd_elf32_bfd_relax_section elf32_crx_relax_section
1333#define bfd_elf32_bfd_get_relocated_section_contents \
1334 elf32_crx_get_relocated_section_contents
1fe1f39c
NC
1335#define elf_backend_can_gc_sections 1
1336#define elf_backend_rela_normal 1
1337
1338#include "elf32-target.h"
This page took 0.351238 seconds and 4 git commands to generate.