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