bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-crx.c
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
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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
28 static reloc_howto_type *elf_crx_reloc_type_lookup
29 (bfd *, bfd_reloc_code_real_type);
30 static void elf_crx_info_to_howto
31 (bfd *, arelent *, Elf_Internal_Rela *);
32 static bfd_boolean elf32_crx_relax_delete_bytes
33 (bfd *, asection *, bfd_vma, int);
34 static 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);
38 static bfd_boolean elf32_crx_relocate_section
39 (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
40 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
41 static asection * elf32_crx_gc_mark_hook
42 (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
43 struct elf_link_hash_entry *, Elf_Internal_Sym *);
44 static bfd_boolean elf32_crx_gc_sweep_hook
45 (bfd *, struct bfd_link_info *, asection *,
46 const Elf_Internal_Rela *);
47 static bfd_boolean elf32_crx_relax_section
48 (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
49 static 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
55 struct 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
61 static 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},
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}
84 };
85
86 static 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 */
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 */
390 };
391
392 /* Retrieve a howto ptr using a BFD reloc_code. */
393
394 static reloc_howto_type *
395 elf_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
410 static void
411 elf_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
421 static bfd_reloc_status_type
422 crx_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
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
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
547 if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32)
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
575 static bfd_boolean
576 elf32_crx_relax_delete_bytes (bfd *abfd, asection *sec,
577 bfd_vma addr, int count)
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;
589 unsigned int symcount;
590
591 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
592
593 contents = elf_section_data (sec)->this_hdr.contents;
594
595 /* The deletion must stop at the next ALIGN reloc for an aligment
596 power larger than the number of bytes we are deleting. */
597
598 irelalign = NULL;
599 toaddr = sec->size;
600
601 irel = elf_section_data (sec)->relocs;
602 irelend = irel + sec->reloc_count;
603
604 /* Actually delete the bytes. */
605 memmove (contents + addr, contents + addr + count,
606 (size_t) (toaddr - addr - count));
607 sec->size -= count;
608
609 /* Adjust all the relocs. */
610 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
611 {
612 /* Get the new reloc address. */
613 if ((irel->r_offset > addr
614 && irel->r_offset < toaddr))
615 irel->r_offset -= count;
616 }
617
618 /* Adjust the local symbols defined in this section. */
619 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
620 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
621 for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
622 {
623 if (isym->st_shndx == sec_shndx
624 && isym->st_value > addr
625 && isym->st_value < toaddr)
626 {
627 /* Adjust the addend of SWITCH relocations in this section,
628 which reference this local symbol. */
629 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
630 {
631 unsigned long r_symndx;
632 Elf_Internal_Sym *rsym;
633 bfd_vma addsym, subsym;
634
635 /* Skip if not a SWITCH relocation. */
636 if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
637 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
638 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
639 continue;
640
641 r_symndx = ELF32_R_SYM (irel->r_info);
642 rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
643
644 /* Skip if not the local adjusted symbol. */
645 if (rsym != isym)
646 continue;
647
648 addsym = isym->st_value;
649 subsym = addsym - irel->r_addend;
650
651 /* Fix the addend only when -->> (addsym > addr >= subsym). */
652 if (subsym <= addr)
653 irel->r_addend -= count;
654 else
655 continue;
656 }
657
658 isym->st_value -= count;
659 }
660 }
661
662 /* Now adjust the global symbols defined in this section. */
663 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
664 - symtab_hdr->sh_info);
665 sym_hashes = elf_sym_hashes (abfd);
666 end_hashes = sym_hashes + symcount;
667
668 for (; sym_hashes < end_hashes; sym_hashes++)
669 {
670 struct elf_link_hash_entry *sym_hash = *sym_hashes;
671
672 if ((sym_hash->root.type == bfd_link_hash_defined
673 || sym_hash->root.type == bfd_link_hash_defweak)
674 && sym_hash->root.u.def.section == sec
675 && sym_hash->root.u.def.value > addr
676 && sym_hash->root.u.def.value < toaddr)
677 sym_hash->root.u.def.value -= count;
678 }
679
680 return TRUE;
681 }
682
683 /* This is a version of bfd_generic_get_relocated_section_contents
684 which uses elf32_crx_relocate_section. */
685
686 static bfd_byte *
687 elf32_crx_get_relocated_section_contents (bfd *output_bfd,
688 struct bfd_link_info *link_info,
689 struct bfd_link_order *link_order,
690 bfd_byte *data,
691 bfd_boolean relocatable,
692 asymbol **symbols)
693 {
694 Elf_Internal_Shdr *symtab_hdr;
695 asection *input_section = link_order->u.indirect.section;
696 bfd *input_bfd = input_section->owner;
697 asection **sections = NULL;
698 Elf_Internal_Rela *internal_relocs = NULL;
699 Elf_Internal_Sym *isymbuf = NULL;
700
701 /* We only need to handle the case of relaxing, or of having a
702 particular set of section contents, specially. */
703 if (relocatable
704 || elf_section_data (input_section)->this_hdr.contents == NULL)
705 return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
706 link_order, data,
707 relocatable,
708 symbols);
709
710 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
711
712 memcpy (data, elf_section_data (input_section)->this_hdr.contents,
713 (size_t) input_section->size);
714
715 if ((input_section->flags & SEC_RELOC) != 0
716 && input_section->reloc_count > 0)
717 {
718 Elf_Internal_Sym *isym;
719 Elf_Internal_Sym *isymend;
720 asection **secpp;
721 bfd_size_type amt;
722
723 internal_relocs = (_bfd_elf_link_read_relocs
724 (input_bfd, input_section, (PTR) NULL,
725 (Elf_Internal_Rela *) NULL, FALSE));
726 if (internal_relocs == NULL)
727 goto error_return;
728
729 if (symtab_hdr->sh_info != 0)
730 {
731 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
732 if (isymbuf == NULL)
733 isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
734 symtab_hdr->sh_info, 0,
735 NULL, NULL, NULL);
736 if (isymbuf == NULL)
737 goto error_return;
738 }
739
740 amt = symtab_hdr->sh_info;
741 amt *= sizeof (asection *);
742 sections = bfd_malloc (amt);
743 if (sections == NULL && amt != 0)
744 goto error_return;
745
746 isymend = isymbuf + symtab_hdr->sh_info;
747 for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
748 {
749 asection *isec;
750
751 if (isym->st_shndx == SHN_UNDEF)
752 isec = bfd_und_section_ptr;
753 else if (isym->st_shndx == SHN_ABS)
754 isec = bfd_abs_section_ptr;
755 else if (isym->st_shndx == SHN_COMMON)
756 isec = bfd_com_section_ptr;
757 else
758 isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
759
760 *secpp = isec;
761 }
762
763 if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
764 input_section, data, internal_relocs,
765 isymbuf, sections))
766 goto error_return;
767
768 if (sections != NULL)
769 free (sections);
770 if (isymbuf != NULL
771 && symtab_hdr->contents != (unsigned char *) isymbuf)
772 free (isymbuf);
773 if (elf_section_data (input_section)->relocs != internal_relocs)
774 free (internal_relocs);
775 }
776
777 return data;
778
779 error_return:
780 if (sections != NULL)
781 free (sections);
782 if (isymbuf != NULL
783 && symtab_hdr->contents != (unsigned char *) isymbuf)
784 free (isymbuf);
785 if (internal_relocs != NULL
786 && elf_section_data (input_section)->relocs != internal_relocs)
787 free (internal_relocs);
788 return NULL;
789 }
790
791 /* Relocate a CRX ELF section. */
792
793 static bfd_boolean
794 elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
795 bfd *input_bfd, asection *input_section,
796 bfd_byte *contents, Elf_Internal_Rela *relocs,
797 Elf_Internal_Sym *local_syms,
798 asection **local_sections)
799 {
800 Elf_Internal_Shdr *symtab_hdr;
801 struct elf_link_hash_entry **sym_hashes;
802 Elf_Internal_Rela *rel, *relend;
803
804 if (info->relocatable)
805 return TRUE;
806
807 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
808 sym_hashes = elf_sym_hashes (input_bfd);
809
810 rel = relocs;
811 relend = relocs + input_section->reloc_count;
812 for (; rel < relend; rel++)
813 {
814 int r_type;
815 reloc_howto_type *howto;
816 unsigned long r_symndx;
817 Elf_Internal_Sym *sym;
818 asection *sec;
819 struct elf_link_hash_entry *h;
820 bfd_vma relocation;
821 bfd_reloc_status_type r;
822
823 r_symndx = ELF32_R_SYM (rel->r_info);
824 r_type = ELF32_R_TYPE (rel->r_info);
825 howto = crx_elf_howto_table + (r_type);
826
827 h = NULL;
828 sym = NULL;
829 sec = NULL;
830 if (r_symndx < symtab_hdr->sh_info)
831 {
832 sym = local_syms + r_symndx;
833 sec = local_sections[r_symndx];
834 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
835 }
836 else
837 {
838 bfd_boolean unresolved_reloc, warned;
839
840 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
841 r_symndx, symtab_hdr, sym_hashes,
842 h, sec, relocation,
843 unresolved_reloc, warned);
844 }
845
846 r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
847 input_section,
848 contents, rel->r_offset,
849 relocation, rel->r_addend,
850 info, sec, h == NULL);
851
852 if (r != bfd_reloc_ok)
853 {
854 const char *name;
855 const char *msg = (const char *) 0;
856
857 if (h != NULL)
858 name = h->root.root.string;
859 else
860 {
861 name = (bfd_elf_string_from_elf_section
862 (input_bfd, symtab_hdr->sh_link, sym->st_name));
863 if (name == NULL || *name == '\0')
864 name = bfd_section_name (input_bfd, sec);
865 }
866
867 switch (r)
868 {
869 case bfd_reloc_overflow:
870 if (!((*info->callbacks->reloc_overflow)
871 (info, (h ? &h->root : NULL), name, howto->name,
872 (bfd_vma) 0, input_bfd, input_section,
873 rel->r_offset)))
874 return FALSE;
875 break;
876
877 case bfd_reloc_undefined:
878 if (!((*info->callbacks->undefined_symbol)
879 (info, name, input_bfd, input_section,
880 rel->r_offset, TRUE)))
881 return FALSE;
882 break;
883
884 case bfd_reloc_outofrange:
885 msg = _("internal error: out of range error");
886 goto common_error;
887
888 case bfd_reloc_notsupported:
889 msg = _("internal error: unsupported relocation error");
890 goto common_error;
891
892 case bfd_reloc_dangerous:
893 msg = _("internal error: dangerous error");
894 goto common_error;
895
896 default:
897 msg = _("internal error: unknown error");
898 /* Fall through. */
899
900 common_error:
901 if (!((*info->callbacks->warning)
902 (info, msg, name, input_bfd, input_section,
903 rel->r_offset)))
904 return FALSE;
905 break;
906 }
907 }
908 }
909
910 return TRUE;
911 }
912
913 /* This function handles relaxing for the CRX.
914
915 There's quite a few relaxing opportunites available on the CRX:
916
917 * bal/bcond:32 -> bal/bcond:16 2 bytes
918 * bcond:16 -> bcond:8 2 bytes
919 * cmpbcond:24 -> cmpbcond:8 2 bytes
920 * arithmetic imm32 -> arithmetic imm16 2 bytes
921
922 Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
923
924 static bfd_boolean
925 elf32_crx_relax_section (bfd *abfd, asection *sec,
926 struct bfd_link_info *link_info, bfd_boolean *again)
927 {
928 Elf_Internal_Shdr *symtab_hdr;
929 Elf_Internal_Rela *internal_relocs;
930 Elf_Internal_Rela *irel, *irelend;
931 bfd_byte *contents = NULL;
932 Elf_Internal_Sym *isymbuf = NULL;
933
934 /* Assume nothing changes. */
935 *again = FALSE;
936
937 /* We don't have to do anything for a relocatable link, if
938 this section does not have relocs, or if this is not a
939 code section. */
940 if (link_info->relocatable
941 || (sec->flags & SEC_RELOC) == 0
942 || sec->reloc_count == 0
943 || (sec->flags & SEC_CODE) == 0)
944 return TRUE;
945
946 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
947
948 /* Get a copy of the native relocations. */
949 internal_relocs = (_bfd_elf_link_read_relocs
950 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
951 link_info->keep_memory));
952 if (internal_relocs == NULL)
953 goto error_return;
954
955 /* Walk through them looking for relaxing opportunities. */
956 irelend = internal_relocs + sec->reloc_count;
957 for (irel = internal_relocs; irel < irelend; irel++)
958 {
959 bfd_vma symval;
960
961 /* If this isn't something that can be relaxed, then ignore
962 this reloc. */
963 if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
964 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
965 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
966 && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
967 continue;
968
969 /* Get the section contents if we haven't done so already. */
970 if (contents == NULL)
971 {
972 /* Get cached copy if it exists. */
973 if (elf_section_data (sec)->this_hdr.contents != NULL)
974 contents = elf_section_data (sec)->this_hdr.contents;
975 /* Go get them off disk. */
976 else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
977 goto error_return;
978 }
979
980 /* Read this BFD's local symbols if we haven't done so already. */
981 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
982 {
983 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
984 if (isymbuf == NULL)
985 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
986 symtab_hdr->sh_info, 0,
987 NULL, NULL, NULL);
988 if (isymbuf == NULL)
989 goto error_return;
990 }
991
992 /* Get the value of the symbol referred to by the reloc. */
993 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
994 {
995 /* A local symbol. */
996 Elf_Internal_Sym *isym;
997 asection *sym_sec;
998
999 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1000 if (isym->st_shndx == SHN_UNDEF)
1001 sym_sec = bfd_und_section_ptr;
1002 else if (isym->st_shndx == SHN_ABS)
1003 sym_sec = bfd_abs_section_ptr;
1004 else if (isym->st_shndx == SHN_COMMON)
1005 sym_sec = bfd_com_section_ptr;
1006 else
1007 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1008 symval = (isym->st_value
1009 + sym_sec->output_section->vma
1010 + sym_sec->output_offset);
1011 }
1012 else
1013 {
1014 unsigned long indx;
1015 struct elf_link_hash_entry *h;
1016
1017 /* An external symbol. */
1018 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1019 h = elf_sym_hashes (abfd)[indx];
1020 BFD_ASSERT (h != NULL);
1021
1022 if (h->root.type != bfd_link_hash_defined
1023 && h->root.type != bfd_link_hash_defweak)
1024 /* This appears to be a reference to an undefined
1025 symbol. Just ignore it--it will be caught by the
1026 regular reloc processing. */
1027 continue;
1028
1029 symval = (h->root.u.def.value
1030 + h->root.u.def.section->output_section->vma
1031 + h->root.u.def.section->output_offset);
1032 }
1033
1034 /* For simplicity of coding, we are going to modify the section
1035 contents, the section relocs, and the BFD symbol table. We
1036 must tell the rest of the code not to free up this
1037 information. It would be possible to instead create a table
1038 of changes which have to be made, as is done in coff-mips.c;
1039 that would be more work, but would require less memory when
1040 the linker is run. */
1041
1042 /* Try to turn a 32bit pc-relative branch/call into
1043 a 16bit pc-relative branch/call. */
1044 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
1045 {
1046 bfd_vma value = symval;
1047
1048 /* Deal with pc-relative gunk. */
1049 value -= (sec->output_section->vma + sec->output_offset);
1050 value -= irel->r_offset;
1051 value += irel->r_addend;
1052
1053 /* See if the value will fit in 16 bits, note the high value is
1054 0xfffe + 2 as the target will be two bytes closer if we are
1055 able to relax. */
1056 if ((long) value < 0x10000 && (long) value > -0x10002)
1057 {
1058 unsigned short code;
1059
1060 /* Get the opcode. */
1061 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1062
1063 /* Verify it's a 'bal'/'bcond' and fix the opcode. */
1064 if ((code & 0xfff0) == 0x3170)
1065 bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1066 else if ((code & 0xf0ff) == 0x707f)
1067 bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
1068 else
1069 continue;
1070
1071 /* Note that we've changed the relocs, section contents, etc. */
1072 elf_section_data (sec)->relocs = internal_relocs;
1073 elf_section_data (sec)->this_hdr.contents = contents;
1074 symtab_hdr->contents = (unsigned char *) isymbuf;
1075
1076 /* Fix the relocation's type. */
1077 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1078 R_CRX_REL16);
1079
1080 /* Delete two bytes of data. */
1081 if (!elf32_crx_relax_delete_bytes (abfd, sec,
1082 irel->r_offset + 2, 2))
1083 goto error_return;
1084
1085 /* That will change things, so, we should relax again.
1086 Note that this is not required, and it may be slow. */
1087 *again = TRUE;
1088 }
1089 }
1090
1091 /* Try to turn a 16bit pc-relative branch into an
1092 8bit pc-relative branch. */
1093 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
1094 {
1095 bfd_vma value = symval;
1096
1097 /* Deal with pc-relative gunk. */
1098 value -= (sec->output_section->vma + sec->output_offset);
1099 value -= irel->r_offset;
1100 value += irel->r_addend;
1101
1102 /* See if the value will fit in 8 bits, note the high value is
1103 0xfc + 2 as the target will be two bytes closer if we are
1104 able to relax. */
1105 if ((long) value < 0xfe && (long) value > -0x100)
1106 {
1107 unsigned short code;
1108
1109 /* Get the opcode. */
1110 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1111
1112 /* Verify it's a 'bcond' opcode. */
1113 if ((code & 0xf0ff) != 0x707e)
1114 continue;
1115
1116 /* Note that we've changed the relocs, section contents, etc. */
1117 elf_section_data (sec)->relocs = internal_relocs;
1118 elf_section_data (sec)->this_hdr.contents = contents;
1119 symtab_hdr->contents = (unsigned char *) isymbuf;
1120
1121 /* Fix the relocation's type. */
1122 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1123 R_CRX_REL8);
1124
1125 /* Delete two bytes of data. */
1126 if (!elf32_crx_relax_delete_bytes (abfd, sec,
1127 irel->r_offset + 2, 2))
1128 goto error_return;
1129
1130 /* That will change things, so, we should relax again.
1131 Note that this is not required, and it may be slow. */
1132 *again = TRUE;
1133 }
1134 }
1135
1136 /* Try to turn a 24bit pc-relative cmp&branch into
1137 an 8bit pc-relative cmp&branch. */
1138 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1139 {
1140 bfd_vma value = symval;
1141
1142 /* Deal with pc-relative gunk. */
1143 value -= (sec->output_section->vma + sec->output_offset);
1144 value -= irel->r_offset;
1145 value += irel->r_addend;
1146
1147 /* See if the value will fit in 8 bits, note the high value is
1148 0x7e + 2 as the target will be two bytes closer if we are
1149 able to relax. */
1150 if ((long) value < 0x100 && (long) value > -0x100)
1151 {
1152 unsigned short code;
1153
1154 /* Get the opcode. */
1155 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1156
1157 /* Verify it's a 'cmp&branch' opcode. */
1158 if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1159 && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1160 && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0)
1161 continue;
1162
1163 /* Note that we've changed the relocs, section contents, etc. */
1164 elf_section_data (sec)->relocs = internal_relocs;
1165 elf_section_data (sec)->this_hdr.contents = contents;
1166 symtab_hdr->contents = (unsigned char *) isymbuf;
1167
1168 /* Fix the opcode. */
1169 bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1170
1171 /* Fix the relocation's type. */
1172 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1173 R_CRX_REL8_CMP);
1174
1175 /* Delete two bytes of data. */
1176 if (!elf32_crx_relax_delete_bytes (abfd, sec,
1177 irel->r_offset + 4, 2))
1178 goto error_return;
1179
1180 /* That will change things, so, we should relax again.
1181 Note that this is not required, and it may be slow. */
1182 *again = TRUE;
1183 }
1184 }
1185
1186 /* Try to turn a 32bit immediate address into
1187 a 16bit immediate address. */
1188 if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1189 {
1190 bfd_vma value = symval;
1191
1192 /* See if the value will fit in 16 bits. */
1193 if ((long) value < 0x7fff && (long) value > -0x8000)
1194 {
1195 unsigned short code;
1196
1197 /* Get the opcode. */
1198 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1199
1200 /* Verify it's a 'arithmetic double'. */
1201 if ((code & 0xf0f0) != 0x20f0)
1202 continue;
1203
1204 /* Note that we've changed the relocs, section contents, etc. */
1205 elf_section_data (sec)->relocs = internal_relocs;
1206 elf_section_data (sec)->this_hdr.contents = contents;
1207 symtab_hdr->contents = (unsigned char *) isymbuf;
1208
1209 /* Fix the opcode. */
1210 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1211
1212 /* Fix the relocation's type. */
1213 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1214 R_CRX_IMM16);
1215
1216 /* Delete two bytes of data. */
1217 if (!elf32_crx_relax_delete_bytes (abfd, sec,
1218 irel->r_offset + 2, 2))
1219 goto error_return;
1220
1221 /* That will change things, so, we should relax again.
1222 Note that this is not required, and it may be slow. */
1223 *again = TRUE;
1224 }
1225 }
1226 }
1227
1228 if (isymbuf != NULL
1229 && symtab_hdr->contents != (unsigned char *) isymbuf)
1230 {
1231 if (! link_info->keep_memory)
1232 free (isymbuf);
1233 else
1234 {
1235 /* Cache the symbols for elf_link_input_bfd. */
1236 symtab_hdr->contents = (unsigned char *) isymbuf;
1237 }
1238 }
1239
1240 if (contents != NULL
1241 && elf_section_data (sec)->this_hdr.contents != contents)
1242 {
1243 if (! link_info->keep_memory)
1244 free (contents);
1245 else
1246 {
1247 /* Cache the section contents for elf_link_input_bfd. */
1248 elf_section_data (sec)->this_hdr.contents = contents;
1249 }
1250 }
1251
1252 if (internal_relocs != NULL
1253 && elf_section_data (sec)->relocs != internal_relocs)
1254 free (internal_relocs);
1255
1256 return TRUE;
1257
1258 error_return:
1259 if (isymbuf != NULL
1260 && symtab_hdr->contents != (unsigned char *) isymbuf)
1261 free (isymbuf);
1262 if (contents != NULL
1263 && elf_section_data (sec)->this_hdr.contents != contents)
1264 free (contents);
1265 if (internal_relocs != NULL
1266 && elf_section_data (sec)->relocs != internal_relocs)
1267 free (internal_relocs);
1268
1269 return FALSE;
1270 }
1271
1272 static asection *
1273 elf32_crx_gc_mark_hook (asection *sec,
1274 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1275 Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1276 struct elf_link_hash_entry *h,
1277 Elf_Internal_Sym *sym)
1278 {
1279 if (h == NULL)
1280 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1281
1282 switch (h->root.type)
1283 {
1284 case bfd_link_hash_defined:
1285 case bfd_link_hash_defweak:
1286 return h->root.u.def.section;
1287
1288 case bfd_link_hash_common:
1289 return h->root.u.c.p->section;
1290
1291 default:
1292 return NULL;
1293 }
1294 }
1295
1296 /* Update the got entry reference counts for the section being removed. */
1297
1298 static bfd_boolean
1299 elf32_crx_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1300 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1301 asection *sec ATTRIBUTE_UNUSED,
1302 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1303 {
1304 /* We don't support garbage collection of GOT and PLT relocs yet. */
1305 return TRUE;
1306 }
1307
1308 /* Definitions for setting CRX target vector. */
1309 #define TARGET_LITTLE_SYM bfd_elf32_crx_vec
1310 #define TARGET_LITTLE_NAME "elf32-crx"
1311 #define ELF_ARCH bfd_arch_crx
1312 #define ELF_MACHINE_CODE EM_CRX
1313 #define ELF_MAXPAGESIZE 0x1
1314 #define elf_symbol_leading_char '_'
1315
1316 #define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
1317 #define elf_info_to_howto elf_crx_info_to_howto
1318 #define elf_info_to_howto_rel 0
1319 #define elf_backend_relocate_section elf32_crx_relocate_section
1320 #define bfd_elf32_bfd_relax_section elf32_crx_relax_section
1321 #define bfd_elf32_bfd_get_relocated_section_contents \
1322 elf32_crx_get_relocated_section_contents
1323 #define elf_backend_gc_mark_hook elf32_crx_gc_mark_hook
1324 #define elf_backend_gc_sweep_hook elf32_crx_gc_sweep_hook
1325 #define elf_backend_can_gc_sections 1
1326 #define elf_backend_rela_normal 1
1327
1328 #include "elf32-target.h"
This page took 0.054582 seconds and 5 git commands to generate.